【IC】NoC设计入门 -- 路由逻辑

“砖块”(FIFO)已经造好,现在我们来造“GPS导航仪”。

这就是 “路由逻辑” (Routing Logic, RC) 模块。

这是我们整个“十字路口”(路由器)的“大脑”。


1. 🎯 “路由逻辑” (RC) 的任务

  • 比喻: “问询处”或“GPS导航仪”。
  • 功能: 它的工作极其专注——“只做计算,不做存储”
  • 输入: 1. “我”的坐标 (e.g., 我是 (1, 1) 号路口)
    2. “车队”的目的地坐标 (e.g., 它想去 (3, 2))
  • 输出: “计算结果” (e.g., “它必须从‘东出口’走!”)

关键的工程概念:
这个模块不需要时钟 (clk)!它是一个纯组合逻辑 (Combinational Logic) 模块。

为什么?因为“计算”应该是**“即时”的。当“输入”(目的地)一确定,“输出”(该走哪个门)就应该立刻**(在几个纳秒的门延迟后)被计算出来。我们不希望在这个决策上多花一个时钟周期。

我们将使用 always @(*)(Verilog中的“组合逻辑”标准写法)来实现它。


2. 📐 模块“蓝图” (Module Interface)

在设计中,我们必须给“坐标”定义一个位宽。假设我们的“城市” (Mesh) 最大不超过 16x16。

  • 16=2416 = 2^416=24,所以我们需要 4位 (bit) 来表示 X 坐标,4位来表示 Y 坐标。
/*
 * 模块:路由逻辑 (Routing Logic)
 * 功能:实现确定性的 (Deterministic) XY 路由算法
 * 类型:纯组合逻辑
 */
module routing_logic #(
    // 参数:定义坐标的位宽
    parameter COORD_WIDTH = 4 
) (
    // ---- 输入 ----
    // “车队”的目的地坐标 (来自 Head Flit)
    input [COORD_WIDTH-1:0] i_dest_x,
    input [COORD_WIDTH-1:0] i_dest_y,

    // “我”自己的坐标 (这个路由器被实例化时,它的“身份”)
    input [COORD_WIDTH-1:0] i_curr_x,
    input [COORD_WIDTH-1:0] i_curr_y,

    // ---- 输出 ----
    // “计算结果”:你想去哪个出口?(5个出口,1-bit 信号)
    // 这是“请求信号”,它们将发往“仲裁器”(Arbiter)
    output reg o_req_north, // 1'b1 = 我想去北
    output reg o_req_south, // 1'b1 = 我想去南
    output reg o_req_east,  // 1'b1 = 我想去东
    output reg o_req_west,  // 1'b1 = 我想去西
    output reg o_req_local  // 1'b1 = 目的地就是我,我要“弹出”(eject)
);

    // TODO: 在这里实现 XY 路由的 "if-else" 逻辑...

endmodule

3. 🧠 核心逻辑实现 (XY 路由算法)

现在我们来填充 TODO 部分。我们将用Verilog实现我们第二阶段学到的“XY路由”规则。

规则:

  1. 规则0 (最高优先级): 目的地就是“我”吗?
    • 如果是,请求 “本地 (Local)” 出口。
  2. 规则1 (X方向): 目的地和“我”的 X 坐标不相等吗?
    • 如果 dest_x > curr_x,请求 “东 (East)” 出口。
    • 如果 dest_x < curr_x,请求 “西 (West)” 出口。
  3. 规则2 (Y方向): X 坐标已经相等,但 Y 坐标不相等吗?
    • 如果 dest_y > curr_y,请求 “北 (North)” 出口。
    • 如果 dest_y < curr_y,请求 “南 (South)” 出口。

下面是代码:

/*
 * 模块:路由逻辑 (Routing Logic)
 * 功能:实现确定性的 (Deterministic) XY 路由算法
 * 类型:纯组合逻辑
 */
module routing_logic #(
    parameter COORD_WIDTH = 4 
) (
    // ---- 输入 ----
    input [COORD_WIDTH-1:0] i_dest_x,
    input [COORD_WIDTH-1:0] i_dest_y,
    input [COORD_WIDTH-1:0] i_curr_x,
    input [COORD_WIDTH-1:0] i_curr_y,

    // ---- 输出 ----
    output reg o_req_north,
    output reg o_req_south,
    output reg o_req_east, 
    output reg o_req_west, 
    output reg o_req_local 
);

    // ---------------------------------------------
    // 核心时序逻辑:使用 "always @(*)" 来表示这是一个“组合逻辑”
    // ---------------------------------------------
    always @(*) begin
        // --- 关键安全措施:防止产生“锁存器”(Latch) ---
        // 在所有 "if" 判断开始前,先把所有出口的请求都设为 0 (不请求)
        o_req_north = 1'b0;
        o_req_south = 1'b0;
        o_req_east  = 1'b0;
        o_req_west  = 1'b0;
        o_req_local = 1'b0;

        // --- 开始执行 XY 路由算法 ---

        // 规则 0:目的地就是“我”吗?
        // (注意:用 `==` 比较多位宽)
        if ( (i_dest_x == i_curr_x) && (i_dest_y == i_curr_y) ) begin
            o_req_local = 1'b1; // 请求“本地”出口
        end
        
        // 规则 1:X 坐标不匹配吗?(先走 X 方向)
        // (注意:用 `else if`)
        else if (i_dest_x > i_curr_x) begin
            o_req_east = 1'b1;  // 请求“东”出口
        end
        else if (i_dest_x < i_curr_x) begin
            o_req_west = 1'b1;  // 请求“西”出口
        end
        
        // 规则 2:X 坐标已匹配,该走 Y 方向了
        else if (i_dest_y > i_curr_y) begin
            o_req_north = 1'b1; // 请求“北”出口
        end
        else if (i_dest_y < i_curr_y) begin
            o_req_south = 1'b1; // 请求“南”出口
        end
        
        // 默认 'else':
        // 如果出现 (dest_x == curr_x) 且 (dest_y == curr_y)
        // 这种情况在 规则0 已经被捕获了。
        // 所以我们不需要一个 'else',因为默认值 (全0) 已经处理了
        // 所有未明确的情况(虽然在这个设计里所有情况都已被覆盖)。
        
    end

endmodule

🔍 代码解析

  1. always @(*)

    • 这是“圣杯”。它告诉Verilog编译器:“请把这里面的逻辑实现为纯组合逻辑(只用与门、或门、非门、Mux)”。
    • *” (星号) 的意思是:always 块内任何一个 input (如 i_dest_x) 发生变化,就立刻重新计算整个块。
    • 这完美地模拟了我们的“GPS”——你一输入新地址,它就“立刻”算出新路线。
  2. o_req_north = 1'b0; (默认值)

    • 这是always @(*)块中最重要的“安全措施”
    • 为什么? 组合逻辑必须在所有可能的条件下,为所有输出都指定一个值。
    • 如果你漏掉了(比如,你只写了 if (A) B=1,但没写 else B=0),编译器会“懵”:“在 A 不为1时,B 应该保持它上一次的值吗?”——这种“保持”行为,就是**“锁存器”(Latch)**。
    • Latch是时序设计中的“毒药”,它会带来无法预测的行为。
    • 我们的办法:always 块的最开头,先把所有输出都清零。这样,我们只需要在 if 语句中把“想要的那个”设为 1 就行了,绝对安全,绝无 Latch。

恭喜!你完成了第二块“砖”

你现在有了:

  1. simple_fifo:“停车场”,它负责**“存储”** Flits(时序逻辑)。
  2. routing_logic:“GPS导航仪”,它负责**“计算”** 路径(组合逻辑)。

我们如何把它们“连接”起来?

  • 当一个“火车头”(Head Flit) 到达 simple_fifo 的“队首”(output)时…
  • “输入端口”(Input Port)模块会把这个Flit的“目的地坐标”(o_data[19:12]) 喂给 routing_logici_dest_x/i_dest_y
  • 同时,routing_logic 的5个 o_req_... 输出信号,将作为“请求”,发给我们下一个要造的组件——“交通警察”

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值