You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilog流水线感知器输出较测试平台晚一个时钟周期求助

单层感知器Verilog模块延迟问题排查求助

我设计了一个单层感知器Verilog模块,功能逻辑符合预期,但输出结果相比测试平台的预期值恰好晚一个时钟周期,导致断言报错。调整过valid信号位置、添加手动延迟均未解决问题,怀疑是流水线/时序逻辑出错。以下是相关代码、数据文件及仿真截图,使用AMD Vivado工具开发,恳请协助排查。


感知器模块代码

// 感知器模块代码
`timescale 1ns / 1ps

module perceptron(
    input rst_n,
    input clk,
    input signed [7:0] x1,
    input signed [7:0] x2,
    input valid_in,
    output reg y,
    output reg y_valid
    );
   
   reg signed [7:0] w1 = 8'sb00000010; //weight 1
   reg signed [7:0] w2 = 8'sb11111110; //weight 2
   reg signed [7:0] b = 8'sb11111101; //bias
   
   //stage 1: p1 = w1*x1 and p2 = w2*x2.
   //stage 2: s = p1 + p2 + b
   
   reg valid_pipe;
   reg signed [15:0] p1;
   reg signed [15:0] p2;
   reg signed [15:0] s;
   
   
   always @(posedge clk) begin 
        if (!rst_n) begin
            y <= 1'b0;
//            y_valid <= 1'b0;
//            w1 <= 8'b0;
//            w2 <= 8'b0;
//            b <= 8'b0;
            valid_pipe <= 1'b0;
//            p1 <= 16'b0;
//            p2 <= 16'b0;
//            s <= 16'b0;
                        
        end
        
        else begin
            //->first pipe cycle
            valid_pipe <= valid_in;
            p1 <= w1 * x1;
            p2 <= w2 * x2;
            //valid_pipe <= valid_in;
            
            //-->second pipe cycle
            //y_valid <= valid_pipe;
            s <= p1 + p2 + b;
            y <= (s >= 0)? 1'b1 : 1'b0;
            y_valid <= valid_pipe;

            
            end 
          
        end
   
endmodule

测试平台代码

`timescale 1ns / 1ps

module tb_perceptron(
    );
    
    
reg clk;
reg rst_n;
    wire signed [7:0] x1;
    wire signed [7:0] x2;
    wire y;
    wire tb_y;
    reg valid_in; 
    wire y_valid;
    
    reg [3:0] addr_in, addr_y;
    
    perceptron dut (.*);   

    rom #( .addr_width (4), .data_width (8), .init_file("x1.dat") )
 x1_mem(                                                                   
.addr(addr_in),                                         
.data (x1)                                         
);    

    rom #( .addr_width (4), .data_width (8), .init_file("x2.dat") )
 x2_mem(                                                                   
.addr(addr_in),                                         
.data (x2)                                         
);    

    rom #( .addr_width (4), .data_width (1), .init_file("y.dat") )
 y_mem(                                                                   
.addr(addr_y),                                         
.data (tb_y)                                         
);    
    
    always #5 clk = ~clk;
    
    //integer file_handle;
    
    
    
    initial
        begin
        //file_handle = $fopen("output.txt", "w");
            //i edit here for delay for check. 
            //#5;
            clk = 0;
            rst_n = 1'h0;
            valid_in = 0;
            
            #73 rst_n = 1'h1;
            #17;
            addr_in = 4'h0;
            #20;
            valid_in = 1;
           
            for (integer i = 0; i < 16; i = i + 1)
            begin
                #10;
                //assert (y == tb_y);
                addr_in = addr_in + 1;
            end 
            valid_in = 0;
            #50;
            //$fclose(file_handle);                  
        end
        
        always_ff @ (posedge clk)
            begin
                if (!rst_n)
                    begin
                        addr_y <= #0.1 4'h0;
                    end
                else if (y_valid)
                    begin
                     //$fwrite(file_handle, "%b\n", y);
                     assert (y == tb_y)
                     else $error("y not equal to tb_y");
                        addr_y <= #0.1 addr_y + 1;
                    end
            end
    
    
endmodule

ROM模块代码

`timescale 1ns/1ps

module rom #(addr_width = 4, data_width = 4, string init_file = "dummy.dat" )
(
input [addr_width-1:0]addr,
output [data_width-1:0]data
);

reg [data_width-1:0] mem [ (1<<addr_width)-1:0];

initial
    begin
        $readmemb (init_file, mem);
        /*for (integer i = 0; i < 16; i = i + 1)
        begin 
            mem[i] = 4'hf - i;
        end*/
    end
    
assign data = mem[addr];


endmodule

数据文件

x1.dat

00000101
11111100
00000000
00001100
11111100
00000100
00000100
00000100
11111100
11111100
00100000
00000100
11111100
11111100
00000000
00000100

x2.dat

11111010
00000100
00000000
11111100
00000100
11111100
11111100
00000100
11111100
00000100
11111100
11111100
00000000
11110000
00000100
11111100

y.dat

1
0
0
1
0
1
1
0
0
0
1
1
0
1
0
1

仿真截图

输出y与测试平台预期tb_y对比


内容的提问来源于stack exchange,提问作者redpocket

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:55:32