1. Rule90
各单元的下一状态是此时当前单元相邻两位的异或。
在这个电路中,创建一个512单元系统(q(511:0)),并在每个时钟周期中前进一个时间步长。加载(load)表明系统的状态应该加载data[511:0]至q中,假设边界(q[0]和q[512])都为零。
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q );
int i;
always@(posedge clk) begin
if(load)
q <= data;
else begin
q[0] <= q[1]^0;
q[511] <= 0 ^ q[510];
for(i=1;i<511;i++)
q[i] <= q[i-1]^q[i+1];
end
end
endmodule
2.Rule 110
与题目一类似,状态转移条件发生变化,如下图所示:
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q
);
int i;
always @(posedge clk ) begin
if(load)
q <= data;
else begin
q[0] <= q[0];
q[511] <= (q[511] ^ q[510] )|| ( q[510] );
for(i = 1; i<511;i=i+1)
q[i] <= (q[i] ^ q[i - 1] )|| (!q[i+1] & q[i-1]);
end
end
endmodule
3. Conway’s Game of life 16*16
一个中心点周围有8个邻居,如果周围的邻居中1的数目为0-1个,那么中心点变为0;如果周围邻居中1的数目为2个,那么中心点状态不变;如果周围邻居中1的数目为3个,中心点变为1;如果周围邻居中1的数目大于3个,中心点变为0。
我们可以将周围的8个邻居的值都加起来来判断周围邻居中1的个数,值得注意的是,这里我们在for中使用了阻塞赋值,因需要当前拍(本周期)得到结果在当前拍(本周期)就去判断。
建议大家做该题的时候花一个16*16的方阵,分析边界条件,达到事半功倍的效果。
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0] q );
reg [15:0] q_2d [15:0];
wire [2:0] nghbr_num [255:0];
int i_d,i_u,j_l,j_r;
always@(*)begin
for(int i=0;i<16;i++)begin
for(int j=0;j<16;j++)begin
i_u=(i==0)?i-1+16:i-1;
i_d=(i==15)?i+1-16:i+1;
j_l=(j==0)?j-1+16:j-1;
j_r=(j==15)?j+1-16:j+1;
nghbr_num[i*16+j] = q_2d[i_u][j_l] + q_2d[i_u][j] + q_2d[i_u][j_r]
+ q_2d[i][j_l]+ q_2d[i][j_r]
+ q_2d[i_d][j_l] + q_2d[i_d][j] + q_2d[i_d][j_r];
end
end
end
always@(posedge clk)begin
if(load)begin
for(int i=0;i<16;i++)begin
for(int j=0;j<16;j++)begin
q_2d[i][j] <= data[i*16+j];
end
end
end
else begin
for(int i = 0 ; i < 16 ; i = i + 1) begin
for(int j = 0 ; j < 16 ; j = j + 1) begin
if(nghbr_num[i*16+j] < 2)
q_2d[i][j] <= 1'b0;
else if (nghbr_num[i*16+j] > 3)
q_2d[i][j] <= 1'b0;
else if (nghbr_num[i*16+j] == 3)
q_2d[i][j] <= 1'b1;
else
q_2d[i][j] <= q_2d[i][j];
end
end
end
end
always@(*) begin
for(int i = 0 ; i < 16 ; i = i + 1) begin
for(int j = 0 ; j < 16 ; j = j + 1) begin
q[i*16+j] = q_2d[i][j];
end
end
end
endmodule