Conway's Game of Life is a two-dimensional cellular automaton.
The "game" is played on a two-dimensional grid of cells, where each cell is either 1 (alive) or 0 (dead). At each time step, each cell changes state depending on how many neighbours it has:
0-1 neighbour: Cell becomes 0.
2 neighbours: Cell state does not change.
3 neighbours: Cell becomes 1.
4+ neighbours: Cell becomes 0.
The game is formulated for an infinite grid. In this circuit, we will use a 16x16 grid. To make things more interesting, we will use a 16x16 toroid, where the sides wrap around to the other side of the grid. For example, the corner cell (0,0) has 8 neighbours: (15,1), (15,0), (15,15), (0,1), (0,15), (1,1), (1,0), and (1,15). The 16x16 grid is represented by a length 256 vector, where each row of 16 cells is represented by a sub-vector: q[15:0] is row 0, q[31:16] is row 1, etc. (This tool accepts SystemVerilog, so you may use 2D vectors if you wish.)
load: Loads data into q at the next clock edge, for loading initial state.
q: The 16x16 current state of the game, updated every clock cycle.
The game state should advance by one timestep every clock cycle.
个人提交代码:
大体思路是按四角、四边、内部分类,利用generate for语句使其分别通过判定模块进行判定,得到对应位置的q_next
//Conwaylife
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0] q );
wire [255:0] q_next;
//四个角
deter U0 (.center(q[0]),
.in({q[255],q[240],q[241],q[15],q[1],q[31],q[16],q[17]}),
.out(q_next[0])
);
deter U15 (.center(q[15]),
.in({q[255:254],q[240],q[14],q[0],q[31:30],q[16]}),
.out(q_next[15])
);
deter U240 (.center(q[240]),
.in({q[239],q[225:224],q[255],q[241],q[15],q[1:0]}),
.out(q_next[240])
);
deter U255 (.center(q[255]),
.in({q[239:238],q[224],q[254],q[240],q[15:14],q[0]}),
.out(q_next[255])
);
//四条边
genvar u; //上侧1-14位
generate
for (u=1;u<15;u=u+1)
begin:UP
deter UP_deter (.center(q[u]),
.in({q[u+241:u+239],q[u-1],q[u+1],q[u+17:u+15]}),
.out(q_next[u])
);
end
endgenerate
genvar d; //下侧241-254位
generate
for (d=241;d<255;d=d+1)
begin:DOWN
deter DOWN_deter (.center(q[d]),
.in({q[d-15:d-17],q[d-1],q[d+1],q[d-239:d-241]}),
.out(q_next[d])
);
end
endgenerate
genvar l; //左侧16(16x1)...224(16x14)
generate
for (l=16;l<225;l=l+16)
begin:LEFT
deter LEFT_deter (.center(q[l]),
.in({q[l-1],q[l-15:l-16],q[l+15],q[l+1],q[l+31],q[l+17:l+16]}),
.out(q_next[l])
);
end
endgenerate
genvar r; //右侧31(+16),47...239
generate
for (r=31;r<240;r=r+16)
begin:RIGHT
deter RIGHT_deter (.center(q[r]),
.in({q[r-16:r-17],q[r-31],q[r-1],q[r-15],q[r+16:r+15],q[r+1]}),
.out(q_next[r])
);
end
endgenerate
//内部
// 0 .............15
// 17 ....... 30
// 33 ....... 46
// ............
// ............
// 225....... 238
// 240 ............255
genvar j,k; //j行,k列
generate
for (j=17;j<226;j=j+16)
begin: ROW_j
for (k=0;k<14;k=k+1)
begin: COLUM_k
deter IN_deter (.center(q[j+k]),
.in({q[j+k-15:j+k-17],q[j+k-1],q[j+k+1],q[j+k+17:j+k+15]}),
.out(q_next[j+k])
);
end
end
endgenerate
always @(posedge clk)
begin
if (load)
q <= data;
else
q <= q_next;
end
endmodule
module deter ( //判定模块
input center,
input [7:0]in,
output out
);
wire [3:0]num;
always @(*)
begin
num = 3'b0;
for (int i=0;i<8;i=i+1) //检测1的个数
begin
num = num + in[i];
end
case(num) //根据1的个数确定输出
4'd2: out = center;
4'd3: out = 1'b1;
default : out = 1'b0;
endcase
end
endmodule