Question:
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.
分析:该题主要是需要考虑边缘情况,看到有很多博主是将边缘情况全都表示出来,这样也不妨是一种做法。这里比较推荐在周围加一圈padding,将1616的网格扩充为1818的网格,扩充的内容即为边缘的neighbours,扩充完后便可直接用counter对neighbour进行计数,从而求解。
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0] q );
reg [3:0] counter;
reg [323:0] data_padding;
reg [255:0] q_next;
//change state
always @(posedge clk) begin
if(load)
q <= data;
else
q <= q_next;
end
//calculate q_next
always @(*) begin
data_padding[17:0] = {q[240],q[255:240],q[255]};
data_padding[323:306] = {q[0],q[15:0],q[15]};
for(int i=1;i<17;i++) begin
data_padding[i*18 +:18] = {q[(i-1)*16],q[(i-1)*16 +: 16],q[i*16-1]};
end
for(int i=1;i<17;i++) begin
for(int j=1;j<17;j++) begin
counter = data_padding[18*i+j-1]+data_padding[18*i+j+1]+data_padding[18*(i-1)+j-1]
+data_padding[18*(i-1)+j]+data_padding[18*(i-1)+j+1]
+data_padding[18*(i+1)+j-1]+data_padding[18*(i+1)+j]+data_padding[18*(i+1)+j+1];
case(counter)
2: q_next[16*(i-1)+j-1] <= q[16*(i-1)+j-1];
3: q_next[16*(i-1)+j-1] <= 1;
default: q_next[16*(i-1)+j-1] <= 0;
endcase
end
end
end
endmodule