Conway GameOfLife 二维CA 涌现
1970年,数学家John Horton Conway发明了"生命游戏"(Game of Life)——也许是人类设计的最优雅的数学系统之一。规则极其简单,却能产生令人震撼的复杂行为:滑翔机飞翔、振荡器脉动、枪手射击、甚至通用图灵机。
生命游戏不是传统意义上的"游戏"——没有玩家,没有输入,只有初始配置和规则。你设定初始状态,然后观察它自行演化。正是这种"无人驾驶"的特性,使得生命游戏成为涌现(Emergence)的经典范例——整体大于部分之和。
Conway生命游戏的规则:
每个元胞有2个状态(生/死),使用Moore邻域(8邻居)
等价编码:B3/S23(Born 3, Survive 2 or 3)
静止体是稳定结构——每一步都保持不变。它们是生命游戏的"原子",是最简单的稳定构型。
| 名称 | 大小 | 形状描述 | 验证 |
|---|---|---|---|
| 方块(Block) | 4 cells | 2×2正方形 | 每个元胞恰好3个邻居→存活 |
| 蜂巢(Beehive) | 6 cells | 六角形 | 内部元胞2-3邻居,外部元胞1-2邻居 |
| 面包(Bread) | 7 cells | 不对称6角形 | 最大7-cell静止体 |
| 船(Boat) | 5 cells | 方格缺一角 | 最小的非对称静止体 |
| 浴缸(Tub) | 4 cells | 菱形+中心 | 中心元胞0个邻居但被3个邻居包围 |
振荡器在若干步后回到初始状态,周期性地变化。
| 名称 | 周期 | 描述 |
|---|---|---|
| 闪光灯(Blinker) | 2 | 3个水平元胞 ↔ 3个垂直元胞 |
| 蟾蜍(Toad) | 2 | 两行3元胞,错开一位 |
| 信号灯(Beacon) | 2 | 两个对角方块交替闪烁 |
| 脉冲星(Pulsar) | 3 | 对称的复杂振荡器,48个元胞 |
| 五重奏(Pentadecathlon) | 15 | 周期15的振荡器 |
飞船是移动结构——经过若干步后平移到新位置。它们是生命游戏中最重要的结构,因为它们可以携带信息。
| 名称 | 速度 | 方向 | 元胞数 |
|---|---|---|---|
| 滑翔机(Glider) | c/4 对角 | 对角线 | 5 |
| 轻量飞船(LWSS) | c/2 正交 | 水平/垂直 | 9 |
| 中量飞船(MWSS) | c/2 正交 | 水平/垂直 | 11 |
| 重量飞船(HWSS) | c/2 正交 | 水平/垂直 | 13 |
这是第一个已知的"枪"——一个周期性产生滑翔机的有限图案。它由两个"皇后蜂穿梭机"相互作用形成,每30步产生一个滑翔机。Gosper枪的发现证明了一个重要事实:生命游戏中的图案可以无限增长。
生命游戏中的"光速":
信息传播速度受邻域限制。Moore邻域下:
对角线方向:c_diag = 1/4(滑翔机速度)
正交方向:c_orth = 1/2(LWSS速度)
没有任何结构能以超过1格/步的速度传播
// ============================================================================
// life_core.v - Conway生命游戏核心
// Moore邻域邻居计数 + B3/S23规则
// 参数化设计:支持任意网格大小
// ============================================================================
module life_core #(
parameter WIDTH = 64,
parameter HEIGHT = 64
)(
input wire clk,
input wire rst_n,
input wire enable,
input wire init,
input wire [WIDTH*HEIGHT-1:0] seed,
output wire [WIDTH*HEIGHT-1:0] state,
output wire [31:0] generation,
output wire [31:0] population
);
reg [WIDTH*HEIGHT-1:0] curr;
wire [WIDTH*HEIGHT-1:0] nxt;
// 每个元胞的邻居计数与规则应用
genvar gx, gy;
generate
for (gy = 0; gy < HEIGHT; gy = gy + 1) begin : gen_row
for (gx = 0; gx < WIDTH; gx = gx + 1) begin : gen_col
localparam integer idx = gy * WIDTH + gx;
// 环形边界坐标
localparam integer xm = (gx == 0) ? WIDTH-1 : gx-1;
localparam integer xp = (gx == WIDTH-1) ? 0 : gx+1;
localparam integer ym = (gy == 0) ? HEIGHT-1 : gy-1;
localparam integer yp = (gy == HEIGHT-1) ? 0 : gy+1;
// 8个Moore邻居
wire [7:0] neighbors;
assign neighbors[0] = curr[ym*WIDTH+xm]; // 左上
assign neighbors[1] = curr[ym*WIDTH+gx]; // 上
assign neighbors[2] = curr[ym*WIDTH+xp]; // 右上
assign neighbors[3] = curr[gy*WIDTH+xm]; // 左
assign neighbors[4] = curr[gy*WIDTH+xp]; // 右
assign neighbors[5] = curr[yp*WIDTH+xm]; // 左下
assign neighbors[6] = curr[yp*WIDTH+gx]; // 下
assign neighbors[7] = curr[yp*WIDTH+xp]; // 右下
// 邻居计数(4位)
wire [3:0] ncount = neighbors[0] + neighbors[1] +
neighbors[2] + neighbors[3] +
neighbors[4] + neighbors[5] +
neighbors[6] + neighbors[7];
// B3/S23规则
wire self = curr[idx];
assign nxt[idx] = self ? (ncount == 4'd2 || ncount == 4'd3) :
(ncount == 4'd3);
end
end
endgenerate
// 状态更新
reg [31:0] gen_reg;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
curr <= {WIDTH*HEIGHT{1'b0}};
gen_reg <= 32'd0;
end else if (init) begin
curr <= seed;
gen_reg <= 32'd0;
end else if (enable) begin
curr <= nxt;
gen_reg <= gen_reg + 32'd1;
end
end
assign state = curr;
assign generation = gen_reg;
// 种群计数(加法器树)
integer p;
reg [31:0] pop_reg;
always @(*) begin
pop_reg = 32'd0;
for (p = 0; p < WIDTH*HEIGHT; p = p + 1)
pop_reg = pop_reg + curr[p];
end
assign population = pop_reg;
endmodule
不可判定性:给定一个初始配置,不存在通用算法能判断该配置是否会最终消亡。这是Rice定理在生命游戏中的体现——生命游戏是图灵完备的,因此其长期行为是不可判定的。
Garden of Eden:某些配置没有前驱——它们不可能从任何之前的状态演化而来。这些配置称为"Garden of Eden"模式。第一例由Roger Banks在1971年发现。
Still Life枚举:
1982年,John Conway自己证明了生命游戏是图灵完备的。证明方法:
2010年,Paul Rendell构造了一个在生命游戏中运行的具体图灵机实现——使用了超过10,000个活元胞!
010 001 111(3×3网格中的滑ider)。画出每一步的状态。
life_core,实现"环形边界"和"固定死边界"两种模式。比较R-pentomino种子在两种边界下的演化差异。
你已经进入了二维CA的世界!Conway生命游戏是最经典的CA,也是涌现理论的起点。从5个细胞的滑翔机到通用计算机,生命游戏展示了简单规则的无限可能。
将CA从理论变为可运行的硬件系统需要解决许多工程细节。以下是基于实践经验的详细指南:
CA系统通常需要多个时钟域:
跨时钟域同步使用双触发器或异步FIFO
| 优化项 | 方法 | 节省量 |
|---|---|---|
| 邻居计数器 | 增量更新替代全加法 | ~40% LUT |
| 状态存储 | BRAM替代分布式RAM | ~60% FF |
| 规则查找 | 硬编码XOR替代MUX | ~75% LUT(XOR规则) |
| 显示输出 | 行缓冲替代全帧缓冲 | ~50% BRAM |
| 边界处理 | 环形替代固定(零开销) | 0 |
CA系统的调试有其特殊性:
为CA引擎建立性能基准:
关键性能指标:
理论峰值PPS = f_clk × W × H(全并行)
实际PPS取决于架构——行缓冲约为理论值的1/H
元胞自动机课程 · 从Conway到Langton到Lattice Gas