题目:
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.
AI翻译如下
The game state should advance by one timestep every clock cycle.
(康威的生命游戏是一个二维元胞自动机。
“游戏”是在二维单元格上进行的,其中每个单元格要么是 1(活)要么是 0(死)。在每个时间步长中,每个单元格都会根据其拥有的邻居数量而改变状态:
- 0-1 邻居:单元格变为 0。
- 2 个邻居:单元状态不变。
- 3 个邻居:单元格变为 1。
- 4+ 邻居:单元格变为 0。
该游戏是为无限网格而制定的。在此电路中,我们将使用 16x16 网格。为了让事情变得更有趣,我们将使用 16x16 的环形线圈,其中两侧环绕到网格的另一侧。例如,角单元格 (0,0) 有 8 个相邻单元:(15,1)、(15,0)、(15,15)、(0,1)、(0,15)、(1,1)、(1,0) 和 (1,15)。16x16 网格由长度为 256 的向量表示,其中每行 16 个单元格由一个子向量表示:q[15:0] 是第 0 行,q[31:16] 是第 1 行,依此类推(此工具接受 SystemVerilog,因此如果您愿意,可以使用 2D 向量。
- load:在下一个时钟边沿将数据加载到 q 中,用于加载初始状态。
- 问:游戏的 16x16 当前状态,每个时钟周期更新。
游戏状态应在每个时钟周期前进一个时间步长。)
模块声明
Module Declaration
module top_module( input clk, input load, input [255:0] data, output [255:0] q );
以下是草稿分析
实现代码
module top_module(
input clk,
input load,
input [255:0] data,
output reg [255:0] q );
reg [3:0] cnt; //定义一个计数器
reg [255:0] q_next; //暂存输入值
integer i,i_0,i_1; //设置循环变量和中间变量
always@(posedge clk)
if(load)begin
q=data;
end
else begin
for(i=0;i<256;i++)begin
i_0=(i+16)% 256;//上一格
i_1=(i-16+256)% 256; //下一格
cnt=q[(i/16)*16+(i-1+16)%16]//左一格
+q[(i/16)*16+(i+1)%16]//右一格
+q[i_0]//上一格
+q[i_1]//下一格
+q[(i_0/16)*16+(i_0-1+16)%16]//左上角(上一格和左一格嵌套,下面同理)
+q[(i_1/16)*16+(i_1-1+16)%16]//左下角
+q[(i_0/16)*16+(i_0+1)%16]//右上角
+q[(i_1/16)*16+(i_1+1)%16];//右下角
case(cnt) //赋值
4'd0:q_next[i]=1'b0;
4'd1:q_next[i]=1'b0;
4'd2:q_next[i]=q[i];
4'd3:q_next[i]=1'b1;
default:q_next[i]=1'b0;
endcase
end
q = q_next;
end
endmodule
此代码参考:原文链接:https://blog.csdn.net/weixin_46817835/article/details/124289842
并对核心部分代码进行了简化,使之更加通用与不同行列的二维元胞数组