导言
HDLBits网站More circuits中的Conwaylife即Game of life,由数学家John Conway创造。
之所以特别关注到这个题目,是因为某位同学曾拿这个游戏作为一门芯片设计课程的PJ。当时觉得生命游戏在众多坦克大战、走迷宫等小游戏中挺有新意,其实现程度比这个题目本身要复杂很多,比如精美的GUI和复杂的场景。
思路
题目告诉我们,这个16×16的细胞网格是一个toroid,可以理解为网格的四边连在了一起而没有边界。我的思路是将整个toroid展平成一个18×18的平面网格,用二维矩阵的方式来处理它。
- 16×16的阵列不大不小,一个一个列出元素来还是有些麻烦的。用4×4的小阵列厘清边界关系,尤其是多出来的两行两列的元素是从哪里来的。
- 扩展后的18×18的阵列与原来16×16阵列中的元素必须正确对应起来,比如扩展后阵列的[1][2]其实是原阵列的[0][1]号元素。
代码
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0] q );
integer i,m,n;
reg [17:0] g_2d [17:0];
reg [2:0] sum;
// extend 16×16 toroid to 18×18 grid
always@(*) begin
g_2d[0] = {q[16*15],q[16*15 +: 16],q[16*16 -1]};
g_2d[17] = {q[16*0],q[16*0 +: 16],q[16*1 -1]};
for(i = 1 ; i < 17 ; i += 1) begin //note index starting point
g_2d[i] = {q[16*(i-1)],q[16*(i-1) +: 16],q[16*i -1]};
end
end
// judge every cell’s life
always@(posedge clk) begin
if(load) begin
q <= data;
end
else begin
for(m = 0 ; m < 16 ; m += 1) begin: row
for(n = 0 ; n < 16 ; n += 1) begin: col
sum = g_2d[m][n] + g_2d[m][n+1] + g_2d[m][n+2]
+ g_2d[m+1][n] + g_2d[m+1][n+2]
+ g_2d[m+2][n] + g_2d[m+2][n+1] + g_2d[m+2][n+2];
case(sum)
3'b010: q[16*m+n] <= q[16*m+n];
3'b011: q[16*m+n] <= 1'b1;
default: q[16*m+n] <= 1'b0;
endcase
end
end
end
end
endmodule
小结
本次练习学习或加强的知识点:
- 固定位宽的数据表达方式可以为: a[m +: n]即从m开始往上数n位,a[m -: n]即从m开始往下数n位,其中的n是固定位宽。我总是记不清冒号在前还是在后,一个小技巧是把冒号看作等号,+/-看所运算符,那么就类似于+=。
- 统计某个数据中“1”的个数,常用的方法是for-loop中将每位数据做加法,得到的和其实就是“1”的个数。
- Verilog二维数组(用memory来表达应该更合适吧)中单个数据的引用方式是q[m][n]。