【SNN脉冲神经网络6】硬件神经网络Router架构(个人项目)

发布于:2025-07-03 ⋅ 阅读:(22) ⋅ 点赞:(0)

声明:因为这是个人项目,仅提供于学习交流展示。所以我将我的代码删减了一些重要部分,我也没有提供完整的测试文件,因此我的代码无法直接运行。这样做的主要目的是避免有人恶意抄袭,借本项目冒充个人成果。

对于硬件神经网络的实现,可以大致区分为硬件神经元本身以及神经网络本身。

对于硬件神经网络的单个节点,其主要功能为与内部的神经元进行数据交互,同时它也要负责与外部的神经元进行信息交互。

首先是其内部单元架构,其内部单元主要包括发送数据单元,接收数据单元,存储数据单元,以及与Neuron Core相连接的单元,大致示意图如下所示:

其次是网络节点与外部的连接,整体架构如下图所示。我们设定的是平面网络结构,因此可以将其分为东南西北四个方向。 每一个连接线路中间都有一个reg作为数据的缓存,以及一个flag作为数据缓存位的标志位。

其中,Router连接之间的reg的标志位是由连接双方所决定的。也就是说,在接受双方都会提供一个标志位来共同决定缓存reg的标志位。其具体架构以及使用办法如下图所示:

下面是例程代码:

1.1 发送数据模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/11 00:38:25
// Design Name: 
// Module Name: send_one
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module send_one(
    input                               sys_clk                    ,
    input                               sys_rst_n                  ,
    // 来自FIFO的数据指示
    input                               empty                      ,
    // data input
    // 来自FIFO的数据输出
    input              [   7:0]         data_output                ,
    // data output
    // 即将传输给四个方向,以及内核core的数据
    output reg         [   7:0]         send_west_data             ,
    output reg         [   7:0]         send_east_data             ,
    output reg         [   7:0]         send_north_data            ,
    output reg         [   7:0]         send_south_data            ,
    output reg         [   7:0]         send_core_data             ,
    // flag singal, 1 means there is data data
    // 传输标志位,已在Router_One文件中解释清楚
    input                               send_west_flag             ,
    input                               send_east_flag             ,
    input                               send_north_flag            ,
    input                               send_south_flag            ,
    input                               send_core_flag             ,
    // self singal
    // 已在Router_One文件中解释清楚
    output reg                          send_west_flag_B           ,
    output reg                          send_east_flag_B           ,
    output reg                          send_north_flag_B          ,
    output reg                          send_south_flag_B          ,
    output reg                          send_core_flag_B           ,
    output reg                          rd_en                       
    );

// any data have, sign is valid
// flag==0, means there is empty reg
// 数据中转标志,表示当前的数据是否已经被处理
reg                                     send_center_flag           ;
// 表示当前Router的位置,用于判断数据传输方向
    parameter                           localpostion=2'b00         ;

always @(negedge sys_rst_n or negedge sys_clk) begin
    if (!sys_rst_n) begin
        // 在复位时所有的标志位都清0
        send_west_flag_B<=0;
        send_east_flag_B<=0;
        send_north_flag_B<=0;
        send_south_flag_B<=0;
        send_core_flag_B<=0;
        // 数据的存储寄存器也清零
        send_west_data<=0;
        send_east_data<=0;
        send_north_data<=0;
        send_south_data<=0;
        send_core_data<=0;
        // 数据的核心中转标志也清零
        send_center_flag<=0;
    end
    // 首先判断是否已将准备好将数据传输到别的方向
    else if (send_center_flag==1) begin
        
        //       North        //
        // West  Center  East //
        //       South        //
        
        // judge the East and West
        // 先判断东西方向(左右)
        if (data_output[7]>localpostion[1]) begin
            // 再判断这个位置是否已经空出来了
            if (send_west_flag==0) begin
                // 如果空出来了,那么就将数据传输到此位
                // 将向外发送标志位取反,告诉外面这里已经有数据了
                // 将向内的标志位清零,表示可以接受新的数据
                send_center_flag<=0;
            end
            else begin
                // 如果没有空出来,就继续等待,同时向内的标志位置1,表示还不能接受新的数据
                send_center_flag<=1;
            end
        end
        else if (data_output[7]<localpostion[1]) begin
            if(send_east_flag==0) begin
                send_east_data<=data_output;
                send_center_flag<=0;
            end
            else begin
                send_center_flag<=1;
            end
        end
        // judge the North and South
        // 在判断南北方向(上下)
        else if (data_output[6]>localpostion[0]) begin
            if (send_north_flag==0) begin
                send_north_data<=data_output;
                send_center_flag<=0;
            end
            else begin
                send_center_flag<=1;
            end
        end
        else if (data_output[6]<localpostion[0]) begin
            if (send_south_flag==0) begin
                send_south_data<=data_output;
                send_center_flag<=0;
            end
            else begin
                send_center_flag<=1;
            end
        end
        // if the data arrive the terminal, send it to the core
        // 如果到了这里,那说明该数据已经抵达目标位置了
        else begin
            // 同样,还是判断传向core block的位置有没有空出来
            if (send_core_flag==0) begin
                // 如果空出来了,那么就将数据传输到此位
                send_core_data<=data_output;
                // 将向外发送标志位取反,告诉外面这里已经有数据了
                // 将向内的标志位清零,表示可以接受新的数据
            end
            else begin
                // 如果没有空出来,就继续等待,同时向内的标志位置1,表示还不能接受新的数据
            end
        end
    end
    else begin

    end
end

// manage the fifo
// 管理FIFO的数据出入
always @(negedge sys_rst_n or negedge sys_clk) begin
    if (!sys_rst_n) begin
        rd_en<=0;
    end
    // 如果要更新一次输出数据,首先判断FIFO内是否还有数据,同时判断外部的寄存器是否能接受新的数据
        // 可以的话,下一个clk刷新新的数据
        // 同时更新标志位,表示当前已经有数据需要被处理了
    // 如果条件不满足,那就不更新数据
    else begin
        rd_en<=0;
    end
end

endmodule

1.2 发送数据模块测试文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/15 22:04:45
// Design Name: 
// Module Name: tb_send_one
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_send_one(

    );
// Inputs
reg                                     sys_clk                    ;
reg                                     sys_rst_n                  ;
reg                                     send_west_flag             ;
reg                                     send_east_flag             ;
reg                                     send_north_flag            ;
reg                                     send_south_flag            ;
reg                                     send_core_flag             ;
// Outputs
wire                   [   7:0]         send_west_data             ;
wire                   [   7:0]         send_east_data             ;
wire                   [   7:0]         send_north_data            ;
wire                   [   7:0]         send_south_data            ;
wire                   [   7:0]         send_core_data             ;
// send_one data
wire                                    send_west_flag_B           ;
wire                                    send_east_flag_B           ;
wire                                    send_north_flag_B          ;
wire                                    send_south_flag_B          ;
wire                                    send_core_flag_B           ;
// fifo data
reg                                     wr_en                      ;
reg                    [   7:0]         data_in                    ;
wire                                    fifo_full                  ;
wire                                    empty                      ;
wire                   [   7:0]         data_output                ;
wire                   [   9:0]         wr_data_count              ;
wire                   [   9:0]         rd_data_count              ;
wire                                    rd_en                      ;

// Instantiate the Unit Under Test (UUT)
send_one uut (
    .sys_clk                           (sys_clk                   ),
    .sys_rst_n                         (sys_rst_n                 ),
    .empty                             (empty                     ),
    .data_output                       (data_output               ),
    .send_west_data                    (send_west_data            ),
    .send_east_data                    (send_east_data            ),
    .send_north_data                   (send_north_data           ),
    .send_south_data                   (send_south_data           ),
    .send_core_data                    (send_core_data            ),

    .send_west_flag                    (send_west_flag            ),
    .send_east_flag                    (send_east_flag            ),
    .send_north_flag                   (send_north_flag           ),
    .send_south_flag                   (send_south_flag           ),
    .send_core_flag                    (send_core_flag            ),

    .send_west_flag_B                  (send_west_flag_B          ),
    .send_east_flag_B                  (send_east_flag_B          ),
    .send_north_flag_B                 (send_north_flag_B         ),
    .send_south_flag_B                 (send_south_flag_B         ),
    .send_core_flag_B                  (send_core_flag_B          ),

    .rd_en                             (rd_en                     ) 
);

// Instantiate fifo_one
fifo_generator_0 u_fifo_generator_0(
    .rst                               (~sys_rst_n                ),
    .wr_clk                            (sys_clk                   ),
    .rd_clk                            (sys_clk                   ),
    .wr_en                             (wr_en                     ),
    .rd_en                             (rd_en                     ),
    .din                               (data_in                   ),
    .dout                              (data_output               ),
    .almost_full                       (almost_full               ),
    .almost_empty                      (almost_empty              ),
    .full                              (fifo_full                 ),
    .empty                             (empty                     ),
    .wr_data_count                     (wr_data_count             ),
    .rd_data_count                     (rd_data_count             ),
    .wr_rst_busy                       (wr_rst_busy               ),
    .rd_rst_busy                       (rd_rst_busy               ) 
);


// store the data in fifo
initial begin
    wr_en<=0;
    sys_rst_n = 0;
    send_west_flag<=0;
    send_east_flag<=0;
    send_north_flag<=0;
    send_south_flag<=0;
    send_core_flag<=0;
    data_in<=0;
    // open the fifo and restore some data
    // Release reset
    #200 sys_rst_n = 1;
    // write data to fifo
    #600 wr_en<=1;
        data_in<=8'b00_000001;
    #20 data_in<=8'b01_000001;
    #20 data_in<=8'b10_000001;
    #20 data_in<=8'b01_000010;
    #20 data_in<=8'b11_000010;
end

endmodule

2.1 接受数据模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/11 00:37:51
// Design Name: 
// Module Name: recive_one
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module recive_one(
    input                               sys_clk                    ,
    input                               sys_rst_n                  ,
    input                               full                       ,
    // flag input
    input              [   7:0]         recive_west_data           ,
    input              [   7:0]         recive_east_data           ,
    input              [   7:0]         recive_north_data          ,
    input              [   7:0]         recive_south_data          ,
    input              [   7:0]         recive_local1_data         ,
    input              [   7:0]         recive_local2_data         ,
    // flag singal, 1 means there is data data 
    input                               recive_west_flag           ,
    input                               recive_east_flag           ,
    input                               recive_north_flag          ,
    input                               recive_south_flag          ,
    input                               recive_local1_flag         ,
    input                               recive_local2_flag         ,
    // self flag
    output reg                          recive_west_flag_A         ,
    output reg                          recive_east_flag_A         ,
    output reg                          recive_north_flag_A        ,
    output reg                          recive_south_flag_A        ,
    output reg                          recive_local1_flag_A       ,
    output reg                          recive_local2_flag_A       ,
    // write flag
    output reg                          wr_en                      ,
    // data output 
    output reg         [   7:0]         data_in                     
    );

// flag to judge there is data or not
// 这个标志位表示一个总的数据汇总
wire                                    recive_flag                ;
// any data have, sign is valid
    parameter                           localpostion=2'b00         ;

always @(negedge sys_rst_n or posedge sys_clk) begin
    if (!sys_rst_n) begin
        recive_west_flag_A<=0;
        recive_east_flag_A<=0;
        recive_north_flag_A<=0;
        recive_south_flag_A<=0;
        recive_local1_flag_A<=0;
        recive_local2_flag_A<=0;
        wr_en<=0;
        data_in<=0;
    end
    // 如果有数据需要被接受,且FIFO也还没满
    else if (recive_flag==1&&full!=1) begin
        // 先判断是哪一个方向有数据需要被接受了
        // 这里一定要注意!!!
        // 虽然可能会有很多个数据都需要被接受,也就是下面的判定可能会被满足很多次
        // 但我们只允许执行一次写操作,因为只有一个FIFO,如果同时处理,则可能会遗漏数据
        if (recive_west_flag==1) begin
            // 将这个需要被接受的数据传给FIFO
            data_in<=recive_west_data;
        end
        else if (recive_east_flag==1) begin
            data_in<=recive_east_data;
        end
        else if (recive_north_flag==1) begin
            data_in<=recive_north_data;
        end
        else if (recive_south_flag==1) begin
            data_in<=recive_south_data;
        end
        else if (recive_local1_flag==1) begin
            data_in<=recive_local1_data;
        end
        else if (recive_local2_flag==1) begin
            data_in<=recive_local2_data;
        end
        // 在准备好数据过后,写使能有效,将数据给写进去
    end
    else begin
        // 否则就不管
    end
end

endmodule

2.2 接受数据模块测试文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/11 17:59:59
// Design Name: 
// Module Name: tb_recive_one
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module tb_recive_one(
);

// Clock and reset
reg                                     sys_clk                    ;
reg                                     sys_rst_n                  ;

// Inputs to recive_one
reg                    [   7:0]         recive_west_data, recive_east_data, recive_north_data, recive_south_data, recive_local1_data, recive_local2_data;
wire                                    recive_west_flag, recive_east_flag, recive_north_flag, recive_south_flag, recive_local1_flag, recive_local2_flag;

// Outputs from recive_one
wire                                    wr_en                      ;
wire                   [   7:0]         data_in                    ;
wire                                    recive_west_flag_A         ;
wire                                    recive_east_flag_A         ;
wire                                    recive_north_flag_A        ;
wire                                    recive_south_flag_A        ;
wire                                    recive_local1_flag_A       ;
wire                                    recive_local2_flag_A       ;
reg                                     recive_west_flag_B         ;
reg                                     recive_east_flag_B         ;
reg                                     recive_north_flag_B        ;
reg                                     recive_south_flag_B        ;
reg                                     recive_local1_flag_B       ;
reg                                     recive_local2_flag_B       ;
// FIFO signals
wire                                    fifo_full   ,fifo_empty    ;
wire                   [   7:0]         fifo_rd_data               ;
wire                   [   9:0]         wr_data_count              ;
wire                   [   9:0]         rd_data_count              ;
reg                                     rd_en                      ;

assign recive_local1_flag=(recive_local1_flag_A^recive_local1_flag_B);
assign recive_local2_flag=(recive_local2_flag_A^recive_local2_flag_B);

recive_one uut_recive_one (
    .sys_clk                           (sys_clk                   ),
    .sys_rst_n                         (sys_rst_n                 ),
    .full                              (fifo_full                 ),
    .recive_west_data                  (recive_west_data          ),
    .recive_east_data                  (recive_east_data          ),
    .recive_north_data                 (recive_north_data         ),
    .recive_south_data                 (recive_south_data         ),
    .recive_local1_data                (recive_local1_data        ),
    .recive_local2_data                (recive_local2_data        ),

    .recive_west_flag                  (recive_west_flag          ),
    .recive_east_flag                  (recive_east_flag          ),
    .recive_north_flag                 (recive_north_flag         ),
    .recive_south_flag                 (recive_south_flag         ),
    .recive_local1_flag                (recive_local1_flag        ),
    .recive_local2_flag                (recive_local2_flag        ),

    .recive_west_flag_A                (recive_west_flag_A        ),
    .recive_east_flag_A                (recive_east_flag_A        ),
    .recive_north_flag_A               (recive_north_flag_A       ),
    .recive_south_flag_A               (recive_south_flag_A       ),
    .recive_local1_flag_A              (recive_local1_flag_A      ),
    .recive_local2_flag_A              (recive_local2_flag_A      ),
    .wr_en                             (wr_en                     ),
    .data_in                           (data_in                   ) 
);

// Instantiate fifo_one
fifo_generator_0 u_fifo_generator_0(
    .rst                               (~sys_rst_n                ),//
    .wr_clk                            (sys_clk                   ),//
    .rd_clk                            (sys_clk                   ),//
    .wr_en                             (wr_en                     ),
    .rd_en                             (rd_en                     ),
    .din                               (data_in                   ),
    .dout                              (fifo_rd_data              ),
    .almost_full                       (almost_full               ),
    .almost_empty                      (almost_empty              ),
    .full                              (fifo_full                 ),
    .empty                             (fifo_empty                ),
    .wr_data_count                     (wr_data_count             ),
    .rd_data_count                     (rd_data_count             ),
    .wr_rst_busy                       (wr_rst_busy               ),
    .rd_rst_busy                       (rd_rst_busy               ) 
);


// Test sequence
initial begin
    // Initialize inputs
    sys_rst_n = 0;
    recive_west_data = 8'h00;
    recive_east_data = 8'h00;
    recive_north_data = 8'h00;
    recive_south_data = 8'h00;
    recive_local1_data = 8'h00;
    recive_local2_data = 8'h00;
    recive_west_flag_B=0;
    recive_east_flag_B=0;
    recive_north_flag_B=0;
    recive_south_flag_B=0;
    recive_local1_flag_B=0;
    recive_local2_flag_B=0;
    rd_en = 0;

    // Release reset
    #400 sys_rst_n = 1;

    // Test case 1: Send a data from the west
    #3000
    recive_west_data = 8'hAA;
    recive_south_data = 8'hDD;
    recive_west_flag_B=~recive_west_flag_B;
    recive_south_flag_B=~recive_south_flag_B;

    // Test case 3: Read data from FIFO
    #200 rd_en = 1;

end

endmodule

3.1 顶层文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/08 23:12:41
// Design Name: 
// Module Name: Router_5
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module Router_One(
    // system input
    input                               sys_clk                    ,
    input                               sys_rst_n                  ,
    
    
    //                          Recive Data                       //
    //                          Recive Data                       //
    //                          Recive Data                       //
    
    
    // flag input
    // 下面的是针对Router的来自四个方向的输入
    input              [   7:0]         recive_west_data           ,
    input              [   7:0]         recive_east_data           ,
    input              [   7:0]         recive_north_data          ,
    input              [   7:0]         recive_south_data          ,
    // flag singal (1 means there is data data)
    // 下面是接受标志位,一但其中某个flag为1,则表示有数据包
    input                               recive_west_flag           ,
    input                               recive_east_flag           ,
    input                               recive_north_flag          ,
    input                               recive_south_flag          ,
    // self flag
    // flag_A是来自接受方的标志位
    // flag_B是来自发送方的标志位
    // 一般flag与flag_A与flag_B之间存在关系:
    // send_west_flag=(send_west_flag_A^send_west_flag_B);
    // 一开始,flag_A与flag_B都为0,表示没有数据
    // 一但自己完成了对数据的处理,此时flag_A反转,表示可以接受新数据
    // 当外方放入新的数据,flag_B反转,表示已经放入新数据
    output                              recive_west_flag_A         ,
    output                              recive_east_flag_A         ,
    output                              recive_north_flag_A        ,
    output                              recive_south_flag_A        ,
    
    
    //                         Send Data                          //
    //                         Send Data                          //
    //                         Send Data                          //
    
    
    // data output
    // 下面是往外面四个方向的传输数据
    output             [   7:0]         send_west_data             ,
    output             [   7:0]         send_east_data             ,
    output             [   7:0]         send_north_data            ,
    output             [   7:0]         send_south_data            ,
    // flag singal (1 means there is data data)
    // 数据发送标志位,以上面的接受flag类似(事实上就是同一个信号)
    // 为0表示位置为空,可以传输数据,为1表示位置有数据,不能传输数据
    input                               send_west_flag             ,
    input                               send_east_flag             ,
    input                               send_north_flag            ,
    input                               send_south_flag            ,
    // self singal
    // flag_B已经在上面解释过了
    output                              send_west_flag_B           ,
    output                              send_east_flag_B           ,
    output                              send_north_flag_B          ,
    output                              send_south_flag_B          ,
    
    
    //                         Core Data                          //
    //                         Core Data                          //
    //                         Core Data                          //
    
    
    // data connect with buffer
    // send_core_flag是与内核计算单元的数据中转量
    input                               send_core_flag             ,
    // send_core_flag_B来自发送给core block一方的标志位
    output                              send_core_flag_B           ,
    // 最终发送到core block的buffer
    output reg         [  63:0]         buffer_64                  ,

    // recive_local1_data和recive_local2_data是来自core block一方的数据
    input              [   7:0]         recive_local1_data         ,
    input              [   7:0]         recive_local2_data         ,
    // 类似的,表示数据是否已经接受的标志位
    input                               recive_local1_flag         ,
    input                               recive_local2_flag         ,
    // 来自core block一方的标志位
    output                              recive_local1_flag_A       ,
    output                              recive_local2_flag_A        
);

// 即将发送给Router的一个中间变量
wire                   [   7:0]         send_core_data             ;
// 给FIFO的中间变量
wire                   [   7:0]         data_in                    ;
wire                   [   7:0]         data_output                ;
wire                                    wr_en                      ;
wire                                    rd_en                      ;
wire                                    almost_full                ;
wire                                    almost_empty               ;
wire                                    full                       ;
wire                                    empty                      ;
wire                   [   7:0]         wr_data_count              ;
wire                   [   7:0]         rd_data_count              ;
wire                                    wr_rst_busy                ;
wire                                    rd_rst_busy                ;

// Instantiate fifo_one
fifo_generator_0 u_fifo_generator_0(
    .rst                               (~sys_rst_n                ),
    .wr_clk                            (sys_clk                   ),
    .rd_clk                            (sys_clk                   ),
    .wr_en                             (wr_en                     ),
    .rd_en                             (rd_en                     ),
    .din                               (data_in                   ),
    .dout                              (data_output               ),
    .almost_full                       (almost_full               ),
    .almost_empty                      (almost_empty              ),
    .full                              (full                      ),
    .empty                             (empty                     ),
    .wr_data_count                     (wr_data_count             ),
    .rd_data_count                     (rd_data_count             ),
    .wr_rst_busy                       (wr_rst_busy               ),
    .rd_rst_busy                       (rd_rst_busy               ) 
);

// recive part
recive_one u_recive_one(
    .sys_clk                           (sys_clk                   ),
    .sys_rst_n                         (sys_rst_n                 ),
    .full                              (full                      ),
    // flag input
    .recive_west_data                  (recive_west_data          ),
    .recive_east_data                  (recive_east_data          ),
    .recive_north_data                 (recive_north_data         ),
    .recive_south_data                 (recive_south_data         ),
    .recive_local1_data                (recive_local1_data        ),
    .recive_local2_data                (recive_local2_data        ),
    // flag singal, 1 means there is data data 
    .recive_west_flag                  (recive_west_flag          ),
    .recive_east_flag                  (recive_east_flag          ),
    .recive_north_flag                 (recive_north_flag         ),
    .recive_south_flag                 (recive_south_flag         ),
    .recive_local1_flag                (recive_local1_flag        ),
    .recive_local2_flag                (recive_local2_flag        ),
    // self flag
    .recive_west_flag_A                (recive_west_flag_A        ),
    .recive_east_flag_A                (recive_east_flag_A        ),
    .recive_north_flag_A               (recive_north_flag_A       ),
    .recive_south_flag_A               (recive_south_flag_A       ),
    .recive_local1_flag_A              (recive_local1_flag_A      ),
    .recive_local2_flag_A              (recive_local2_flag_A      ),
    // write flag
    .wr_en                             (wr_en                     ),
    // data output 
    .data_in                           (data_in                   ) 
);

// send part
send_one u_send_one(
    .sys_clk                           (sys_clk                   ),
    .sys_rst_n                         (sys_rst_n                 ),
    .empty                             (empty                     ),
    // data input
    .data_output                       (data_output               ),
    // data output
    .send_west_data                    (send_west_data            ),
    .send_east_data                    (send_east_data            ),
    .send_north_data                   (send_north_data           ),
    .send_south_data                   (send_south_data           ),
    .send_core_data                    (send_core_data            ),
    // flag singal, 1 means there is data data
    .send_west_flag                    (send_west_flag            ),
    .send_east_flag                    (send_east_flag            ),
    .send_north_flag                   (send_north_flag           ),
    .send_south_flag                   (send_south_flag           ),
    .send_core_flag                    (send_core_flag            ),
    // self singal
    .send_west_flag_B                  (send_west_flag_B          ),
    .send_east_flag_B                  (send_east_flag_B          ),
    .send_north_flag_B                 (send_north_flag_B         ),
    .send_south_flag_B                 (send_south_flag_B         ),
    .send_core_flag_B                  (send_core_flag_B          ),
    .rd_en                             (rd_en                     ) 
);

// deal with the data from send to center part
// 这里是把data最后传输给buffer的实际位置
always @(negedge sys_rst_n or posedge sys_clk) begin
    if (!sys_rst_n) begin
        buffer_64<=0;
    end
    // 先判断是否有有需要处理的数据,然后在进行分配
    else if () begin
        case ()
            6'b000000:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001;
            6'b000001:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010;
            6'b000010:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100;
            6'b000011:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000;
            6'b000100:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000;
            6'b000101:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000;
            6'b000110:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000;
            6'b000111:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000;
            6'b001000:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000;
            6'b001001:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000;
            6'b001010:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000;
            6'b001011:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000;
            6'b001100:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000;
            6'b001101:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000;
            6'b001110:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000;
            6'b001111:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000;
            6'b010000:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000;
            6'b010001:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000;
            6'b010010:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000;
            6'b010011:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000;
            6'b010100:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000;
            6'b010101:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000;
            6'b010110:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000;
            6'b010111:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000;
            6'b011000:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000;
            6'b011001:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000;
            6'b011010:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000;
            6'b011011:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000;
            6'b011100:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000;
            6'b011101:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000;
            6'b011110:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000;
            6'b011111:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000;
            6'b100000:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100001:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100010:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100011:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100100:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100101:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100110:buffer_64<=64'b0000_0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b100111:buffer_64<=64'b0000_0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101000:buffer_64<=64'b0000_0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101001:buffer_64<=64'b0000_0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101010:buffer_64<=64'b0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101011:buffer_64<=64'b0000_0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101100:buffer_64<=64'b0000_0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101101:buffer_64<=64'b0000_0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101110:buffer_64<=64'b0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b101111:buffer_64<=64'b0000_0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110000:buffer_64<=64'b0000_0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110001:buffer_64<=64'b0000_0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110010:buffer_64<=64'b0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110011:buffer_64<=64'b0000_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110100:buffer_64<=64'b0000_0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110101:buffer_64<=64'b0000_0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110110:buffer_64<=64'b0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b110111:buffer_64<=64'b0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111000:buffer_64<=64'b0000_0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111001:buffer_64<=64'b0000_0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111010:buffer_64<=64'b0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111011:buffer_64<=64'b0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111100:buffer_64<=64'b0001_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111101:buffer_64<=64'b0010_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111110:buffer_64<=64'b0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            6'b111111:buffer_64<=64'b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000;
            default:buffer_64<=0;
        endcase
    end
end

endmodule

3.2 顶层测试文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/19 23:24:38
// Design Name: 
// Module Name: tb_Router_one
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_Router_one(

    );
reg                                     sys_clk                    ;
reg                                     sys_rst_n                  ;


//                          Recive Data                       //
//                          Recive Data                       //
//                          Recive Data                       //


reg                    [   7:0]         recive_west_data           ;
reg                    [   7:0]         recive_east_data           ;
reg                    [   7:0]         recive_north_data          ;
reg                    [   7:0]         recive_south_data          ;
reg                    [   7:0]         recive_local1_data         ;
reg                    [   7:0]         recive_local2_data         ;
wire                                    recive_west_flag_A         ;
wire                                    recive_east_flag_A         ;
wire                                    recive_north_flag_A        ;
wire                                    recive_south_flag_A        ;
wire                                    recive_local1_flag_A       ;
wire                                    recive_local2_flag_A       ;


//                         Send Data                          //
//                         Send Data                          //
//                         Send Data                          //


wire                   [   7:0]         send_west_data             ;
wire                   [   7:0]         send_east_data             ;
wire                   [   7:0]         send_north_data            ;
wire                   [   7:0]         send_south_data            ;

reg                                     send_west_flag             ;
reg                                     send_east_flag             ;
reg                                     send_north_flag            ;
reg                                     send_south_flag            ;
wire                                    send_core_flag             ;

wire                                    send_west_flag_B           ;
wire                                    send_east_flag_B           ;
wire                                    send_north_flag_B          ;
wire                                    send_south_flag_B          ;
wire                                    send_core_flag_B           ;

reg                                     recive_west_flag_B         ;
reg                                     recive_east_flag_B         ;
reg                                     recive_north_flag_B        ;
reg                                     recive_south_flag_B        ;
reg                                     recive_local1_flag_B       ;
reg                                     recive_local2_flag_B       ;


//                         Core Data                          //
//                         Core Data                          //
//                         Core Data                          //


// output to buffer
wire                   [  63:0]         buffer_64                  ;
// 上面的数据变量基本都在Router_One中定义了,这里依据变量的名字也大概能判断

// 这里就是将flag_A和flag_B进行异或,得到flag,这样就可以判断flag是否发生变化
wire                                    recive_west_flag           ;
wire                                    recive_east_flag           ;
wire                                    recive_north_flag          ;
wire                                    recive_south_flag          ;
wire                                    recive_local1_flag         ;
wire                                    recive_local2_flag         ;

// 这里也是一样,只是没有core block单元,所以这里的测试文件我们代替core block进行操作
// 理论上这里send_core_flag_A由core block控制
// 如果他完成了buffer输入数据的处理,这里就是改变flag_A表示已经处理好了,可以接受新数据
reg                                     send_core_flag_A           ;
assign send_core_flag = (send_core_flag_B^send_core_flag_A);

// 下面的Router_One已经在之前的文件里定义过了
Router_One u_Router_One(
    // system input
    .sys_clk                           (sys_clk                   ),
    .sys_rst_n                         (sys_rst_n                 ),
    
    
    //                          Recive Data                       //
    //                          Recive Data                       //
    //                          Recive Data                       //
    
    
    // flag input
    .recive_west_data                  (recive_west_data          ),
    .recive_east_data                  (recive_east_data          ),
    .recive_north_data                 (recive_north_data         ),
    .recive_south_data                 (recive_south_data         ),
    .recive_local1_data                (recive_local1_data        ),
    .recive_local2_data                (recive_local2_data        ),
    // flag singal(1 means there is data data)
    .recive_west_flag                  (recive_west_flag          ),
    .recive_east_flag                  (recive_east_flag          ),
    .recive_north_flag                 (recive_north_flag         ),
    .recive_south_flag                 (recive_south_flag         ),
    .recive_local1_flag                (recive_local1_flag        ),
    .recive_local2_flag                (recive_local2_flag        ),
    // self flag
    .recive_west_flag_A                (recive_west_flag_A        ),
    .recive_east_flag_A                (recive_east_flag_A        ),
    .recive_north_flag_A               (recive_north_flag_A       ),
    .recive_south_flag_A               (recive_south_flag_A       ),
    .recive_local1_flag_A              (recive_local1_flag_A      ),
    .recive_local2_flag_A              (recive_local2_flag_A      ),
    
    
    //                         Send Data                          //
    //                         Send Data                          //
    //                         Send Data                          //
    
    
    // data output
    .send_west_data                    (send_west_data            ),
    .send_east_data                    (send_east_data            ),
    .send_north_data                   (send_north_data           ),
    .send_south_data                   (send_south_data           ),
    // flag singal(1 means there is data data)
    .send_west_flag                    (send_west_flag            ),
    .send_east_flag                    (send_east_flag            ),
    .send_north_flag                   (send_north_flag           ),
    .send_south_flag                   (send_south_flag           ),
    .send_core_flag                    (send_core_flag            ),
    // self singal
    .send_west_flag_B                  (send_west_flag_B          ),
    .send_east_flag_B                  (send_east_flag_B          ),
    .send_north_flag_B                 (send_north_flag_B         ),
    .send_south_flag_B                 (send_south_flag_B         ),
    .send_core_flag_B                  (send_core_flag_B          ),
    
    
    //                         Core Data                          //
    //                         Core Data                          //
    //                         Core Data                          //
    
    
    // output to buffer
    .buffer_64                         (buffer_64                 ) 
);

// Test sequence
// 开始设定测试程序
initial begin
    // 刚开始时,假定没有任何数据,所有的flag与reg都是空的
    // Initialize inputs
    sys_rst_n <= 0;
    sys_clk <= 0;
    recive_west_data<=8'h00;
    recive_east_data<=8'h00;
    recive_north_data<=8'h00;
    recive_south_flag_B=0;
    recive_local1_flag_B=0;
    recive_local2_flag_B=0;

    send_west_flag<=0;
    send_east_flag<=0;
    send_north_flag<=0;
    send_south_flag<=0;

    // Release reset
    // 现在开始初始化FIFO
    #200 sys_rst_n = 1;

    // Test case 1: Send a data from the west
    // 留上充分的时间等待FIFO初始化完成
    #600
    // 此时我们一次性一口气同时给4个数据,来测试recive模块的能力
    recive_west_data = 8'b10_000001;
    recive_south_data =8'b11_000100;
    // 标志位去反,表示有数据
    recive_north_flag_B=~recive_north_flag_B;
    recive_south_flag_B=~recive_south_flag_B;

    // 当recive模块完成对外部数据的接受后,FIFO内存有待处理的数据,empty为0
    // 此时send模块检测到FIFO有数据,开始向外部传输数据
    // 在测试中途改变west的flag,假装此时west有数据,以此来判定send是否正常

    // 过一段时间后,west_flag恢复为0,表示reg已经空出来了,可以存数据了

    // 再等一会,又一次同时给5个数据,并且还有core block方向的数据
    #10
    recive_west_data = 8'b00_000001;
    recive_north_data =8'b01_000111;
    recive_south_flag_B=~recive_south_flag_B;
    recive_local1_flag_B=~recive_local1_flag_B;
    // 同样的,在测试中途改变core的flag,假装此时core有数据,以此来判定send是否正常

    #150;
    // 过一段时间,core的flag恢复,再来看看是否正常
    send_core_flag_A<=~send_core_flag_A;
    // 最后观察传输过程中,是否有数据遗漏,或者方向出错。
end

endmodule

声明:因为这是个人项目,仅提供于学习交流展示。所以我将我的代码删减了一些重要部分,我也没有提供完整的测试文件,因此我的代码无法直接运行。这样做的主要目的是避免有人恶意抄袭,借本项目冒充个人成果。


网站公告

今日签到

点亮在社区的每一天
去签到