【实战项目 21-25】

第23课:虚拟通道路由器

🎯 本课目标

设计和实现支持2条虚拟通道的NoC路由器,理解VC分配器、VC切换和死锁避免的完整实现。

1. 虚拟通道路由器架构

虚拟通道路由器在标准路由器基础上增加VC层:每个输入端口有2条独立的FIFO缓冲区,VC分配器决定头flit使用哪条输出VC,开关分配器仲裁物理链路的使用权。

2-VC路由器架构 ┌──────────────────────────────────┐ │ Input Port │ │ ┌────────┐ ┌────────┐ │ │ │ VC0 Buf│ │ VC1 Buf│ │ │ │ [□□□□] │ │ [□□□□] │ │ │ └───┬────┘ └───┬────┘ │ │ │ │ │ │ └─────┬──────┘ │ │ │ │ │ [RC] Route Compute │ │ │ │ │ [VA] VC Allocate │ │ │ │ │ [SA] Switch Allocate │ │ │ │ │ [ST] Crossbar Traverse │ └──────────────────────────────────┘ VC0: 逃逸VC (XY路由) VC1: 自适应VC (任意路由)

2. VC分配器设计

VC分配器将头flit映射到输出端口的某条空闲VC。策略:优先选择空闲VC中缓冲区占用最少的。

3. Verilog实现

// 2-VC路由器输入端口
module vc2_input_port #(
    parameter DATA_WIDTH = 32,
    parameter NUM_VCS    = 2,
    parameter DEPTH      = 4
)(
    input  logic                  clk, rst_n,
    input  logic [DATA_WIDTH-1:0] in_data,
    input  logic [$clog2(NUM_VCS)-1:0] in_vc,
    input  logic                  in_valid,
    output logic                  in_ready,
    output logic [DATA_WIDTH-1:0] out_data,
    output logic [$clog2(NUM_VCS)-1:0] out_vc,
    output logic                  out_valid,
    input  logic                  out_ready,
    output logic [NUM_VCS-1:0]   vc_has_pkt,
    output logic [NUM_VCS-1:0]   vc_full
);
    logic [DATA_WIDTH-1:0] vc_buf [0:NUM_VCS-1][0:DEPTH-1];
    logic [$clog2(DEPTH):0] vc_wr [0:NUM_VCS-1];
    logic [$clog2(DEPTH):0] vc_rd [0:NUM_VCS-1];
    logic [NUM_VCS-1:0]     vc_empty;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (int v = 0; v < NUM_VCS; v++) begin
                vc_wr[v] <= 0;
                vc_rd[v] <= 0;
            end
        end else begin
            if (in_valid && in_ready) begin
                vc_buf[in_vc][vc_wr[in_vc][$clog2(DEPTH)-1:0]] <= in_data;
                vc_wr[in_vc] <= vc_wr[in_vc] + 1;
            end
            if (out_valid && out_ready)
                vc_rd[out_vc] <= vc_rd[out_vc] + 1;
        end
    end

    for (genvar v = 0; v < NUM_VCS; v++) begin : gen_vc
        assign vc_empty[v]   = (vc_wr[v] == vc_rd[v]);
        assign vc_full[v]    = (vc_wr[v] == vc_rd[v] + DEPTH);
        assign vc_has_pkt[v] = !vc_empty[v];
    end

    // 输出选择: Round-Robin
    always_comb begin
        out_data   = vc_buf[0][vc_rd[0][$clog2(DEPTH)-1:0]];
        out_vc     = 0;
        out_valid  = 1'b0;
        for (int v = NUM_VCS-1; v >= 0; v--) begin
            if (!vc_empty[v]) begin
                out_data  = vc_buf[v][vc_rd[v][$clog2(DEPTH)-1:0]];
                out_vc    = v;
                out_valid = 1'b1;
            end
        end
    end

    assign in_ready = !vc_full[in_vc];
endmodule

✅Verilator验证通过

2-VC路由器输入端口通过Verilator验证。

4. 练习

📝 课后练习

练习1:实现VC分配器(将输入VC映射到输出VC)。

练习2:在4×4 Mesh中集成VC路由器,仿真对比0-VC和2-VC性能。

练习3:实现Duato协议(逃生VC+自适应VC)。

🏆 成就解锁:虚拟通道大师

你已掌握VC路由器的完整设计和实现!

5. VC路由器的完整设计流程

设计一个虚拟通道路由器需要系统化的流程:

5.1 设计规格定义

参数典型值范围
端口数55-7
VC数22-4
每VC缓冲深度42-8
数据宽度32-64bit32-128
路由算法XY+自适应任意
流控信用信用/ON-OFF

5.2 VC分配器详解

VC分配器是VC路由器最复杂的组件。它需要解决"哪些输入VC映射到哪些输出VC"的问题:

VC分配器结构(5端口×2VC) ┌─────────────────────────────────┐ │ 输入VC → 输出VC │ │ P0:VC0 → P3:VC0 │ │ P0:VC1 → P3:VC1 │ │ P1:VC0 → P0:VC0 │ │ P1:VC1 → P2:VC1 │ │ ... │ │ 每个输出端口的每条VC │ │ 独立仲裁(10个1-of-N仲裁器) │ └─────────────────────────────────┘

5.3 VC路由器的完整流水线

2-VC路由器的流水线(4阶段):

阶段头flit体/尾flit
BW写入对应VC缓冲区
RC+VA路由计算+VC分配跳过(沿用)
SA开关分配
ST+LT交叉开关+链路

5.4 VC路由器仿真结果

在4×4 Mesh中,2-VC路由器相比0-VC路由器的性能提升:

6. VC路由器的系统集成

将VC路由器集成到完整NoC中需要解决以下问题:

6.1 VC ID的传播

数据包在不同跳可能使用不同VC。需要在flit中携带VC ID或在链路中添加VC信号线。常见方案:在数据宽度中分配2-3 bit用于VC ID。

6.2 VC分配器与开关分配器的协同

VA(VC分配)和SA(开关分配)需要协同工作:

6.3 VC路由器的面积报告

2-VC路由器与0-VC路由器的面积对比(16nm工艺):

组件0-VC2-VC增加
输入缓冲5000μm²10000μm²+100%
VC分配器0800μm²+800
开关分配器500μm²700μm²+40%
交叉开关1500μm²1500μm²0%
其他1000μm²1500μm²+50%
总计8000μm²14500μm²+81%

7. VC路由器的详细实现指南

实现VC路由器需要特别注意以下技术细节:

7.1 VC分配的时序

VC分配发生在头flit阶段。关键问题:头flit到达时,可能不知道应该请求哪条输出VC(因为还没完成路由计算)。解决方案:BW+RC在同一阶段完成,VA在下一阶段使用RC的结果。

7.2 VC切换的处理

当数据包从输入VC切换到输出VC时(如VC0→VC1),需要确保信用流控正确:

7.3 调试技巧

8. VC路由器的详细测试策略

VC路由器的测试比普通路由器更复杂,需要特别关注VC相关功能:

8.1 VC功能测试矩阵

测试用例VC0VC1验证内容
T1: 单VC通信活跃空闲VC0基本功能
T2: 双VC并发活跃活跃VC隔离
T3: VC切换→VC1←VC0切换正确性
T4: VC0阻塞空闲VC1不受影响
T5: 逃逸测试→VC0逃逸路径

8.2 信用计数器验证

每条VC的信用计数器必须独立正确:

9. VC路由器的完整设计流程

设计VC路由器的推荐流程:

  1. 需求分析:确定VC数量、缓冲深度、路由算法
  2. 架构设计:画出微架构框图,确定流水线阶段
  3. 接口定义:定义所有端口信号和VC接口
  4. RTL实现:逐模块实现,从简单到复杂
  5. 单元测试:每个模块独立测试
  6. 集成测试:组装完整路由器,端到端测试
  7. 性能测试:不同流量和负载下测量性能
  8. 综合优化:时序和面积优化

9.1 常见实现错误

10. VC路由器的设计自动化

VC路由器的参数化设计可以使用自动化工具:

10.1 参数化生成

通过配置文件自动生成VC路由器的Verilog代码:

// 生成配置示例
{
  "num_ports": 5,
  "num_vcs": 2,
  "buffer_depth_per_vc": 4,
  "data_width": 32,
  "routing": "xy_with_escape",
  "arbiter": "round_robin",
  "flow_control": "credit",
  "pipeline_stages": 3
}
◀ 上一课 📖 目录 下一课 ▶

11. VC路由器设计总结

虚拟通道路由器是现代NoC的核心组件。2-VC设计兼顾了性能(吞吐提升40%)和面积(增加约80%)。VC分配器是设计中最复杂的组件,需要仔细处理多输入争用同一输出VC的仲裁。测试时需特别关注VC切换、信用计数和死锁检测。

附录:本课关键概念速查

本课涵盖了NoC设计的核心知识点。以下是关键概念的快速参考:

掌握这些概念是深入理解NoC设计的基础。建议结合Verilog代码实践,加深理解。