目录
## 题目1:rule 90规则90是具有有趣属性的一维元胞自动机。
## 题目1:rule 90
规则90是具有有趣属性的一维元胞自动机。
规则很简单。有一个一维的单元格数组(打开或关闭)。在每个时间步长中,每个单元的下一个状态是单元的两个当前邻居的异或。下表是表示此规则的更详细的方式,其中单元格的下一个状态是自身及其两个相邻项的函数:
left | center | right | Center's next state |
---|---|---|---|
1 | 1 | 1 | 0 |
1 | 1 | 0 | 1 |
1 | 0 | 1 | 0 |
1 | 0 | 0 | 1 |
0 | 1 | 1 | 1 |
0 | 1 | 0 | 0 |
0 | 0 | 1 | 1 |
0 | 0 | 0 | 0 |
(“规则 90”的名称来自读取“下一个状态”列:01011010是十进制 90。
在该电路中,创建一个512单元系统(q[511:0]),并在每个时钟周期内前进一个时间步长。load输入指示系统的状态应加载数据[511:0]。假设边界(q[-1] 和 q[512])均为零(关闭)。
模块声明
module top_module( input clk, input load, input [511:0] data, output [511:0] q );
提示:
对于 q[511:0] = 1 的初始状态,前几次迭代为:
1
10
101
1000
10100
100010
1010101
10000000
这形成了谢尔宾斯基三角形的一半。
分析:观察上表可得,其逻辑关系为:左边的逻辑值与右边的逻辑值异或,便能得到下一个状态的值。同时要形成谢尔宾斯基三角形的一半通过观察可知第一位总是1,因此在最高位采用0^0即可。
代码如下:
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q );
always @(posedge clk)
begin
if(load)
q <= data;
else
q <= {1'b0,q[511:1]}^{q[510:0],1'b0};
end
endmodule
仿真结果如下:
题目2:rule 100
规则110是一个具有有趣属性(例如图灵完备)的一维元胞自动机。
有一个一维的单元格数组(打开或关闭)。在每个时间步长中,每个单元格的状态都会发生变化。在规则 110 中,根据下表,每个单元的下一个状态仅取决于自身及其两个相邻单元:
left | center | right | Center's next state |
---|---|---|---|
1 | 1 | 1 | 0 |
1 | 1 | 0 | 1 |
1 | 0 | 1 | 1 |
1 | 0 | 0 | 0 |
0 | 1 | 1 | 1 |
0 | 1 | 0 | 1 |
0 | 0 | 1 | 1 |
0 | 0 | 0 | 0 |
(“规则 110”的名称来自读取“下一个状态”列:01101110是十进制 110。
在该电路中,创建一个512单元系统(q[511:0]),并在每个时钟周期内前进一个时间步长。load输入指示系统的状态应加载数据[511:0]。假设边界(q[-1] 和 q[512])均为零(关闭)。
模块声明
module top_module( input clk, input load, input [511:0] data, output [511:0] q );
提示:
对于 q[511:0] = 1 的初始状态,前几次迭代为:
1
11
111
1101
11111
110001
1110011
11010111
分析:观察rule 100的状态转移表并不能直接观察其逻辑关系,因此可以考虑画出其卡诺图,然后通过圈1法对其逻辑表达式进行化简。其卡诺图如下图所示。设left = A,center = B,right = C,输出为Center's next state。
得出其逻辑表达式为:Center's next state = B&~C+~A&C+~B&C。
由此可得代码如下:
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q
);
always @(posedge clk)
begin
if(load)
q <= data;
else
q <= (q & ~{q[510:0],1'b0}) | (~{1'b0,q[511:1]} & {q[510:0],1'b0}) | (~q & {q[510:0],1'b0});
end
endmodule
仿真结果:
题目3:Conwaylife
康威的生命游戏是一个二维元胞自动机。
“游戏”在二维单元格网格上播放,其中每个单元格为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 中,用于加载初始状态。
- q:游戏的16x16当前状态,每个时钟周期更新。
游戏状态应在每个时钟周期前移一个时间步长。
约翰·康威(John Conway),数学家和生命游戏元胞自动机的创造者,于2020年4月11日因COVID-19去世。
模块声明
module top_module( input clk, input load, input [255:0] data, output [255:0] q );
提示:
一个易于理解并测试一些边界条件的测试用例是blinker 256'h7。它是行 0 列 0-2 中的 3 个单元格。它在一行 3 个单元格和一列 3 个单元格之间振荡(在第 1 列中,在第 1 列中,第 15、0 和 1 行中)。
此处代码参考用Verilog实现二维细胞自动机——康威生命游戏(Conway's Game of Life)_早睡身体好~的博客-CSDN博客_conway生命游戏 verilog
module top_module(
input clk,
input load,
input [255:0] data,
output [255:0]q );
reg [255:0] q_next;//存储次态
reg [3:0]sum;//记录每次遍历的和
integer i;//定义正整数i,作为for循环判断的条件量
always@(posedge clk)
if(load)
q <= data;
else begin
for( i = 0;i < 256;i=i+1) begin
if(i==0)//左上角
sum = q[1]+q[16]+q[17]+q[240]+q[241]+q[15]+q[31]+q[255];
else if(i==15)//右上角
sum = q[14]+q[16]+q[0]+q[240]+q[254]+q[30]+q[31]+q[255];
else if(i==240)//左下角
sum = q[0]+q[15]+q[239]+q[241]+q[1]+q[224]+q[225]+q[255];
else if(i==255)//右下角
sum = q[0]+q[15]+q[14]+q[224]+q[238]+q[240]+q[239]+q[254];
else if(0<i & i<15)//上边界
sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17]+q[i+239]+q[i+240]+q[i+241];
else if(i%16==0)//左边界
sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17]+q[i-16]+q[i-15]+q[i+31];
else if(i%16==15)//右边界
sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i-17]+q[i-16]+q[i-15]+q[i-31];
else if(240<i & i<255)//下边界
sum = q[i-1]+q[i+1]+q[i-17]+q[i-16]+q[i-15]+q[i-239]+q[i-240]+q[i-241];
else //非边界
sum = q[i-1]+q[i+1]+q[i-17]+q[i-16]+q[i-15]+q[i+15]+q[i+16]+q[i+17];
case(sum) //根据邻居数量判断次态
2:q_next[i]=q[i];
3:q_next[i]=1;
default:q_next[i]=0;
endcase
end
q = q_next;
end
endmodule
其中值得注意的是使用quartus ii应将输出output输出语句改为:output reg [255:0]q ); 否则将会提示你没有定义q的类型从而报错。
使用quartus ii 画出逻辑图:
由逻辑图可知,该程序全由加法器组成,看似复杂庞大,实际占用的资源并不会太多。