1.Shift4
module top_module(
input clk,
input areset, // async active-high reset to zero
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk or posedge areset)//是异步置零
begin
if(areset)
q <= 4‘b0;
else if(load)
q <= data;
else if(ena)
q <= q >> 1;
end
endmodule
2.Rotate100
module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
reg temp;
always@(posedge clk)
begin
if(load)
q <= data;
else if(ena == 2‘b01)
begin
temp = q[0];
q = q >>1;
q[99] = temp;
end
else if(ena == 2‘b10)
begin
temp = q[99];
q = q << 1;
q[0] = temp;
end
else
q <= q;
end
endmodule
首先这是循环移位,其次此处的swap必须做阻塞赋值,否则并发则会出错。
3.shift18
module top_module(
input clk,
input load,
input ena,
input [1:0] amount,
input [63:0] data,
output reg [63:0] q);
reg temp;
always@(posedge clk)
begin
if(load)
q <= data;
else if(ena)
begin
temp = q[63];
case(amount)
2‘b00 : begin q = q << 1;end
2‘b01 : begin q = q << 8;end
2‘b10 : begin q = q >> 1; q[63:62] = {2{temp}};end
2‘b11 : begin q = q >> 8; q[63:56] = {8{temp}};end
default:;
endcase
end
else
q <= q;
end
endmodule
注意规则:算术左移和逻辑左移一致,右移是带符号位填充而非简单的0填充。
4.LFSR5
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5‘h1
output [4:0] q
);
always@(posedge clk)
begin
if(reset)
q <= 5‘h1;
else
begin
q[4] <= q[0];
q[3] <= q[4];
q[2] <= q[3] ^ q[0];
q[1] <= q[2];
q[0] <= q[1];
end
end
endmodule
本题实现了一个伽罗瓦线性反馈移位寄存器,通常这类寄存器被用来生成伪随机数序列,有许多应用。我也是第一次接触,不太熟悉。
参考链接
5.3bitLFSR
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [2:0] LEDR); // Q
always@(posedge KEY[0])
begin
LEDR[0] <= (KEY[1]) ? SW[0] : LEDR[2];
LEDR[1] <= (KEY[1]) ? SW[1] : LEDR[0];
LEDR[2] <= (KEY[1]) ? SW[2] : (LEDR[1] ^ LEDR[2]);
end
endmodule
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32‘h1
output [31:0] q
);
integer i;
always@(posedge clk)
begin
if(reset)
q <= 32‘h1;
else
begin
for(i=31; i>=0; i--)
begin
if(i==31)
q[i] <= q[0];
else if(i==21 || i==1 || i==0)
q[i] <= q[i+1] ^ q[0];
else
q[i] <= q[i+1];
end
end
end
endmodule
需要注意的是为伽罗瓦LFSR,而且索引是从0开始的。
7.shift register
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out);
reg d0;
reg d1;
reg d2;
always@(posedge clk)
begin
if(~resetn)
begin
d0 <= 1‘b0;
d1 <= 1‘b0;
d2 <= 1‘b0;
out <= 1‘b0;
end
else
begin
d0 <= in;
d1 <= d0;
d2 <= d1;
out <= d2;
end
end
endmodule
8.shift register
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
MUXDFF muxdff3(KEY[3], KEY[1], SW[3], KEY[2], KEY[0], LEDR[3]);
MUXDFF muxdff2(LEDR[3], KEY[1], SW[2], KEY[2], KEY[0], LEDR[2]);
MUXDFF muxdff1(LEDR[2], KEY[1], SW[1], KEY[2], KEY[0], LEDR[1]);
MUXDFF muxdff0(LEDR[1], KEY[1], SW[0], KEY[2], KEY[0], LEDR[0]);
endmodule
module MUXDFF (
input w,
input e,
input r,
input l,
input clk,
output q);
wire res;
wire d;
assign res = (e)? w : q;
assign d = (l)? r : res;
always@(posedge clk)
q <= d;
endmodule
9.3-input LUT
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
reg[7:0] r;
always@(posedge clk)
begin
if(enable)
begin
r = r<<1;
r[0] = S;
end
end
always@(A or B or C or r)
begin
case({{A},{B},{C}})
3‘b000 : Z <= r[0];
3‘b001 : Z <= r[1];
3‘b010 : Z <= r[2];
3‘b011 : Z <= r[3];
3‘b100 : Z <= r[4];
3‘b101 : Z <= r[5];
3‘b110 : Z <= r[6];
3‘b111 : Z <= r[7];
default:;
endcase
end
endmodule
本题容易出错在于,输出是异步输出,而非同步输出。
以下是more circuits的内容,只有三个题目就不单独写了。
1.rule90
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q );
reg q_1 = 0;
reg q_512 = 0;
integer i;
always@(posedge clk)
begin
if(load)
q <= data;
else
begin
for(i=0; i<512; i++)
begin
if(i == 0)
q[i] <= q_1 ^ q[i+1];
else if(i == 511)
q[i] <= q_512 ^ q[i-1];
else
q[i] <= q[i-1] ^ q[i+1];
end
end
end
endmodule
2.rule110
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q
);
integer i;
always@(posedge clk)
begin
if(load)
q <= data;
else
for(i=0; i<512; i++)
begin
if(i==0)
q[i] <= q[i] ;
else if(i==511)
q[i] <= q[i] | q[i-1];
else
q[i] <= ~( ((~q[i]) & (~q[i-1])) | (q[i-1] & q[i] & q[i+1]) );
end
end
endmodule
rule110也是很重要的东西。不过我也是第一次接触。这里要注意低位在右而不是高位。
[参考资料](https://uwe-repository.worktribe.com/output/1061875)
3.Conwaylife
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0] q );
reg[15:0] r1[15:0];
reg[15:0] r2[15:0];
integer i;
integer j;
integer k;
integer l;
integer count;
always@(posedge clk)
begin
if(load)
begin
for(i=0; i<16; i++)
begin
for(j=0; j<16; j++)
r1[i][j] = data[16*i + j];
end
end
else
r1 = r2;
for(i=0; i<16; i++)
begin
for(j=0; j<16; j++)
begin
count = 0;
for(k=-1; k<2; k++)//检索相邻的活者个数
begin
for(l=-1; l<2; l++)
begin
if(r1[(i+16+k)%16][(j+16+l)%16]==1)
count++;
end
end
if(r1[i][j]==1)
count--;
if(count<2 || count>3)
r2[i][j] = 1‘b0;
else if(count==2)
r2[i][j] = r1[i][j];
else
r2[i][j] = 1‘b1;
end
end
for(i=0; i<16; i++)
begin
for(j=0; j<16; j++)
q[i*16+j] = r1[i][j];
end;
end
endmodule
这个题的难度更大了,这里我用了两个寄存器,因为一个寄存器做综合就必须是非阻塞式的,而这里非阻塞式是没法成功的,load必须先存,然后再计算,如果是非阻塞式的,就会计算上一个周期留下的r1了而非新load进去的值,同时如果只用一个寄存器的话会比较复杂,两个寄存器看起来更清晰一些。
关于边界相邻的问题,这里其实类似卡诺图那种四面合拢的。我这里是利用类似补码的思想,取模来得到的。
最后输入输出都要作线性和矩阵之间的变换,注意不要出错。
这一题逻辑上并不那么复杂,但是实现起来会有很多问题,希望我们都能认真题会。
康威生命问题的提出者约翰康威老爷子去年因新冠肺炎去世谨在此表示哀悼
欢迎大家批评指正讨论。
[练习网址](https://hdlbits.01xz.net/wiki/Conwaylife)
https://hdlbits.01xz.net/wiki/Shift Register 与 More Circuits答案