【IC】NoC设计入门 --交换矩阵
你完全说对了!这确实是所有组件中**最“直观”**的一个。
它就是 “交换矩阵” (Crossbar),我们“十字路口”的**“立交桥”或“扳道岔”**系统。
1. 💡 “交换矩阵” (Crossbar) 的“顿悟”时刻
它听起来很“矩阵”,很复杂,但它的核心功能非常简单:
一个 Crossbar 就是一堆“多路选择器” (Multiplexer, MUX) 的集合。
我们来思考一下。在我们的5x5路由器中,我们有5个输出端口(东、南、西、北、本地)。
让我们只看**“东输出” (East Output)** 这个端口:
-
问题: 它的“数据”可以来自哪里?
-
答案: 它可以来自“北输入”、“南输入”、“西输入”或“本地输入”。(在我们的XY路由中,它不会来自“东输入”)。
-
结论: “东输出”端口需要一个 “4选1”的MUX。
-
MUX的数据输入:
i_data_north,i_data_south,i_data_west,i_data_local。 -
MUX的“选择”信号 (sel): 这个MUX由谁来“控制”?
-
答案: 由我们刚刚设计的**“东出口仲裁器” (
arbiter_for_east)** 来控制!
arbiter_for_east 的 o_gnt (授权) 输出信号,就是这个MUX的“选择”信号!
因此,一个5x5的Crossbar,本质上就是5个并排的MUX:
- 一个 “4选1 MUX” 来决定**“东输出”**的数据。
- 一个 “4选1 MUX” 来决定**“北输出”**的数据。
- 一个 “4选1 MUX” 来决定**“南输出”**的数据。
- …以此类推。
2. 🔌 模块“蓝图” (Module Interface)
这是一个纯组合逻辑模块。它不需要 clk 或 rst_n。它就是一堆“开关”和“电线”,“授权”信号一来,它就“立刻”接通。
/** 模块:5x5 交换矩阵 (Crossbar)* 功能:基于仲裁器的“授权”信号,将输入数据“切换”到正确的输出端口* 类型:纯组合逻辑 (Combinational)*/
module crossbar_5x5 #(parameter FLIT_WIDTH = 32 // 必须和 FIFO 的 FLIT_WIDTH 保持一致
)(// ---- 5个“数据”输入 (来自5个Input Port的FIFO输出) ----input [FLIT_WIDTH-1:0] i_data_north,input [FLIT_WIDTH-1:0] i_data_south,input [FLIT_WIDTH-1:0] i_data_east,input [FLIT_WIDTH-1:0] i_data_west,input [FLIT_WIDTH-1:0] i_data_local,// ---- 5组“控制”输入 (来自5个Arbiter的“授权”输出) ----// 注意:每个都是 4-bit, 对应 4 个可能的请求者input [3:0] i_gnt_for_north, // 授权给“北出口”的One-Hot向量input [3:0] i_gnt_for_south,input [3:0] i_gnt_for_east,input [3:0] i_gnt_for_west,input [3:0] i_gnt_for_local,// ---- 5个“数据”输出 (去往5个Output Port) ----output [FLIT_WIDTH-1:0] o_data_north,output [FLIT_WIDTH-1:0] o_data_south,output [FLIT_WIDTH-1:0] o_data_east,output [FLIT_WIDTH-1:0] o_data_west,output [FLIT_WIDTH-1:0] o_data_local
);// TODO: 实现 5 个并行的 One-Hot MUXendmodule
3. 🚦 核心逻辑实现 (One-Hot MUX)
我们如何用“仲裁器”的One-Hot (独热) 输出 (o_gnt) 来实现一个MUX?
arbiter_for_east(东出口仲裁器) 的i_gnt_for_east是一个4位向量,我们假设它的“请求者”顺序是:[0]=North,[1]=South,[2]=West,[3]=Local。- 如果它授权给“North”,
i_gnt_for_east将是4'b0001。 - 如果它授权给“West”,
i_gnt_for_east将是4'b0100。 - 如果它谁也没授权,
i_gnt_for_east将是4'b0000。
我们可以用一种非常“硬件化”、非常高效的方式来实现这个MUX:
/** 模块:5x5 交换矩阵 (Crossbar)* ... (接口同上) ...*/
module crossbar_5x5 #(parameter FLIT_WIDTH = 32
)(// ... (输入/输出接口同上) ...// ---------------------------------------------// 核心逻辑:5个并行的 MUX// ---------------------------------------------// -- 1. "东" 出口的 MUX --// "东"出口可以被 N, S, W, L 请求// 假设 i_gnt_for_east[0] = Grant to North// i_gnt_for_east[1] = Grant to South// i_gnt_for_east[2] = Grant to West// i_gnt_for_east[3] = Grant to Localassign o_data_east = (i_data_north & {FLIT_WIDTH{i_gnt_for_east[0]}}) | // "与": 如果gnt[0]是0, 结果是0(i_data_south & {FLIT_WIDTH{i_gnt_for_east[1]}}) | // "或": 因为是One-Hot,(i_data_west & {FLIT_WIDTH{i_gnt_for_east[2]}}) | // 最多只有1项不是0(i_data_local & {FLIT_WIDTH{i_gnt_for_east[3]}});// -- 2. "北" 出口的 MUX --// "北"出口可以被 S, E, W, L 请求// 假设 i_gnt_for_north[0] = Grant to South// i_gnt_for_north[1] = Grant to East// i_gnt_for_north[2] = Grant to West// i_gnt_for_north[3] = Grant to Localassign o_data_north = (i_data_south & {FLIT_WIDTH{i_gnt_for_north[0]}}) |(i_data_east & {FLIT_WIDTH{i_gnt_for_north[1]}}) |(i_data_west & {FLIT_WIDTH{i_gnt_for_north[2]}}) |(i_data_local & {FLIT_WIDTH{i_gnt_for_north[3]}});// -- 3. "南" 出口的 MUX --// "南"出口可以被 N, E, W, L 请求assign o_data_south = (i_data_north & {FLIT_WIDTH{i_gnt_for_south[0]}}) |(i_data_east & {FLIT_WIDTH{i_gnt_for_south[1]}}) |(i_data_west & {FLIT_WIDTH{i_gnt_for_south[2]}}) |(i_data_local & {FLIT_WIDTH{i_gnt_for_south[3]}});// -- 4. "西" 出口的 MUX --// "西"出口可以被 N, S, E, L 请求assign o_data_west = (i_data_north & {FLIT_WIDTH{i_gnt_for_west[0]}}) |(i_data_south & {FLIT_WIDTH{i_gnt_for_west[1]}}) |(i_data_east & {FLIT_WIDTH{i_gnt_for_west[2]}}) |(i_data_local & {FLIT_WIDTH{i_gnt_for_west[3]}});// -- 5. "本地" 出口的 MUX --// "本地"出口可以被 N, S, E, W 请求assign o_data_local = (i_data_north & {FLIT_WIDTH{i_gnt_for_local[0]}}) |(i_data_south & {FLIT_WIDTH{i_gnt_for_local[1]}}) |(i_data_east & {FLIT_WIDTH{i_gnt_for_local[2]}}) |(i_data_west & {FLIT_WIDTH{i_gnt_for_local[3]}});endmodule
🔍 代码解析
-
assign- 我们在这里只用了
assign关键字。这告诉Verilog:“这是一个纯组合逻辑的‘连接’”。 o_data_east不是一个reg(寄存器),它就是一根“导线” (wire),它的“值”完全由assign右侧的计算结果立即决定。
- 我们在这里只用了
-
{FLIT_WIDTH{...}}(Verilog复制操作符)- 这是实现“One-Hot MUX”的“黑魔法”。
i_gnt_for_east[0]是一个 1-bit 信号 (1'b1或1'b0)。{FLIT_WIDTH{i_gnt_for_east[0]}}的意思是:“把这个 1-bit 信号复制 FLIT_WIDTH 次(比如32次)”。- 结果:
- 如果
i_gnt_for_east[0]是1'b1(授权),它就变成32'b111...1(即32'hFFFFFFFF)。 - 如果
i_gnt_for_east[0]是1'b0(未授权),它就变成32'b000...0(即32'h0)。
- 如果
-
&(按位与) 和|(按位或)(i_data_north & 32'hFFFFFFFF)的结果是i_data_north。(i_data_north & 32'h00000000)的结果是32'h0。- 因为
i_gnt_for_east是 One-Hot(最多只有1位是’1’),所以assign o_data_east = ...的|(或) 运算中,最多只有一项是“真实数据”,其他所有项都是32'h0。 - 这就在硬件上完美地实现了一个 MUX!
🏁 恭喜!你完成了所有“砖块”!
我们已经成功地“制造”了建造一个路由器(十字路口)所需的全部4个核心组件:
simple_fifo:“停车场”(时序逻辑,存储)routing_logic:“GPS导航仪”(组合逻辑,计算)arbiter_4_to_1:“交通警察”(时序逻辑,状态机)crossbar_5x5:“立交桥”(组合逻辑,连接)
“理论课”和“零件制造课”到此结束。
你已经准备好进入“总装”阶段了。
