我的MSB下采样模块的Verilog测试平台设计(Verilog testbench design for my MSB downsampling module)

编程入门 行业动态 更新时间:2024-10-25 06:33:35
我的MSB下采样模块的Verilog测试平台设计(Verilog testbench design for my MSB downsampling module)

几天前,我询问了一个模块( 这里 ),我想实现它接收输入样本的MSB,累加它们(通过移位),并在32位输出位“填充”时将它们组合成输出样本。

感谢那里的帮助,我得到了这个实现,它不会产生任何编译错误,而且Xilinx 12.1看起来很好:

module my_rx_dsp0
#(
    //frontend bus width
    parameter WIDTH = 24
)
(
    //control signals
    input clock, //dsp clock
    input reset, //active high synchronous reset
    input clear, //active high on packet control init
    input enable, //active high when streaming enabled

    //user settings bus, controlled through user setting regs API
    input set_stb, input [7:0] set_addr, input [31:0] set_data,

    //full rate inputs directly from the RX frontend
    input [WIDTH-1:0] frontend_i,
    input [WIDTH-1:0] frontend_q,

    //full rate outputs directly to the DDC chain
    output [WIDTH-1:0] ddc_in_i,
    output [WIDTH-1:0] ddc_in_q,

    //strobed samples {I16,Q16} from the RX DDC chain
    input [31:0] ddc_out_sample,
    input ddc_out_strobe, //high on valid sample
    output ddc_out_enable, //enables DDC module

    //strobbed baseband samples {I16,Q16} from this module
    output reg [31:0] bb_sample,
    output reg bb_strobe //high on valid sample
);

    reg [3:0] i_msb;
    reg [3:0] q_msb;

    reg [31:0] temp_buff = 0;
    reg [1:0] count = 0;

    always @(posedge clock) begin 
        if(ddc_out_strobe) begin
            // bit shifter for MSB
            temp_buff <= {i_msb,q_msb,temp_buff[31:8]};
            // to avoid if-else condition
            count <= (count==2'd3) ? 2'd0 : (count+1);
        end
    end

    always @(*) begin
        i_msb = ddc_out_sample[31:28];
        q_msb = ddc_out_sample[15:12];
        // to avoid if-else condition   
        bb_strobe = (count==2'd3);
        bb_sample = bb_strobe ? temp_buff : 32'd0;  
    end

    assign ddc_in_i = frontend_i;
    assign ddc_in_q = frontend_q;
    assign ddc_out_enable = enable; 

endmodule //my_rx_dsp0_custom
 

现在我想用一些例子来实现一个测试my_rx_dsp0.v的测试平台。 我实现了一个my_rx_dsp0_tb_2.v ,它从一个名为my_input.dat的文件中读取32位样本,作为input s ddc_out_sample提供给模块。 然后将它们与存储在my_output.dat的正确值进行my_output.dat 。

注意:我自己没有编写这个测试平台,我从一个开源项目的另一个测试平台中进行了调整。

这是实施:

module my_rx_dsp0_tb ( );

reg clk;
reg reset;
reg enable;
reg ddc_out_strobe; //high on valid sample
reg [31:0] ddc_out_sample;
wire [31:0] bb_sample = 32'd0;
wire bb_strobe;
wire ddc_out_enable = 1'b1; //enables DDC module

parameter WIDTH = 24;
parameter clocks = 2; // number of clocks per input

reg endofsim = 0;
integer number_of_errors;
initial number_of_errors = 0;

wire set_stb = 1;
wire [7:0] set_addr;
wire [31:0] set_data;
wire [WIDTH-1:0] frontend_i;
wire [WIDTH-1:0] frontend_q;
wire [WIDTH-1:0] ddc_in_i;
wire [WIDTH-1:0] ddc_in_q;

reg signed [31:0] compare_out;

// Setup the clock
initial clk = 1'b0;
always #5 clk <= ~clk ;

// Come out of reset after a while
initial reset = 1'b1 ;
initial #1000 reset = 1'b0 ;

// Enable the entire system
initial enable = 1'b1 ;

// Instantiate UUT
my_rx_dsp0 #(.WIDTH(WIDTH)) UUT_rx_dsp0
    (   .clock(clk), .reset(reset), .clear(clear), .enable(enable),
        .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
        .frontend_i(frontend_i), .frontend_q(frontend_q),
        .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q),
        .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable),
        .bb_sample(bb_sample), .bb_strobe(bb_strobe) );

//-------Setup file IO-------//
//
integer i, r_in, r_out, infile, outfile;

initial begin
    infile = $fopen("my_input.dat","r");
    outfile = $fopen("my_output.dat","r");
    $timeformat(-9, 2, " ns", 10) ;
    // for n=9,p=2 digits after decimal pointer
    //min_field_width=10 number of character positions for %t
end      

//-------Get sim values and display errors-------//
//
initial begin
    // Initialize inputs
    ddc_out_strobe <= 1'd0;
    ddc_out_sample <= 32'd0;

    // Wait for reset to go away
    @(negedge reset) #0;

    while(!endofsim) begin
        // Write the input from the file or 0 if EndOfFile(EOF)
        @(posedge clk) begin
            #1
            ddc_out_strobe <= 1'b1;
            if(!$feof(infile))
                r_in = $fscanf(infile,"%b\n",ddc_out_sample);
            else
                ddc_out_sample <= 32'd0;
        end
        //
        // Clocked in; set the strobe to 0 if the # of clocks/sample
        // is greater than 1
        if( clocks > 1 ) begin
            @(posedge clk) begin
                ddc_out_strobe <= 1'b0  ;
            end

            // Wait for the specified # of cycles
            for( i = 0 ; i < (clocks-2) ; i = i + 1 ) begin
                @(posedge clk) #1 ;
            end
        end
        //

        //
        // Print out the number of errors that occured
        if(number_of_errors) begin
            $display("FAILED: %d errors during simulation",number_of_errors) ;
        end else begin
            $display("PASSED: Simulation successful") ;
        end 
        // 
    end 
end

//-------Comparison btwn simulated values vs known good values-------//
//
always @(posedge clk) begin
    if(reset)
        endofsim <= 1'b0 ;
    else begin
        if(!$feof(outfile)) begin
            if(bb_strobe) begin
                r_out = $fscanf(outfile,"%b\n",compare_out);
                if(compare_out != bb_sample) begin
                    $display("%t: %b != %b",$realtime,bb_sample,compare_out);
                    number_of_errors = number_of_errors + 1;
                end else begin
                    $display("%t: %b = %b",$realtime,bb_sample,compare_out);
                end
            end
        end else begin
            // Signal end of simulation when no more outputs
            endofsim <= 1'b1 ;
        end
    end
end 

endmodule // my_rx_dsp0_tb
 

使用Xilinx ISE Suite Edition 12.1中的ISim进行模拟时,我无法从模块中获得所需的功能。 我担心输出包含几个x状态(未知状态),而不是预期的1秒或0秒。

问题这是由于:

1)使用$fscanf读取文件的方式?

2)初始化reg [31:0] temp_buff = 0我错了吗?

3)或者有人知道出了什么问题?

来自测试平台的错误提示(例如): xx000x00xxx00x0xx000x0x000000000 != 10000110111001011100010001101100

A couple of days ago I asked about a module (here) I wanted to implement which takes the MSB of input samples, accumulates them (by shifting) and combines them into the output sample when the 32 output bit is "filled".

Thanks to the help there, I got this implementation, which doesn't produce any compilation errors and seemed fine with Xilinx 12.1:

module my_rx_dsp0
#(
    //frontend bus width
    parameter WIDTH = 24
)
(
    //control signals
    input clock, //dsp clock
    input reset, //active high synchronous reset
    input clear, //active high on packet control init
    input enable, //active high when streaming enabled

    //user settings bus, controlled through user setting regs API
    input set_stb, input [7:0] set_addr, input [31:0] set_data,

    //full rate inputs directly from the RX frontend
    input [WIDTH-1:0] frontend_i,
    input [WIDTH-1:0] frontend_q,

    //full rate outputs directly to the DDC chain
    output [WIDTH-1:0] ddc_in_i,
    output [WIDTH-1:0] ddc_in_q,

    //strobed samples {I16,Q16} from the RX DDC chain
    input [31:0] ddc_out_sample,
    input ddc_out_strobe, //high on valid sample
    output ddc_out_enable, //enables DDC module

    //strobbed baseband samples {I16,Q16} from this module
    output reg [31:0] bb_sample,
    output reg bb_strobe //high on valid sample
);

    reg [3:0] i_msb;
    reg [3:0] q_msb;

    reg [31:0] temp_buff = 0;
    reg [1:0] count = 0;

    always @(posedge clock) begin 
        if(ddc_out_strobe) begin
            // bit shifter for MSB
            temp_buff <= {i_msb,q_msb,temp_buff[31:8]};
            // to avoid if-else condition
            count <= (count==2'd3) ? 2'd0 : (count+1);
        end
    end

    always @(*) begin
        i_msb = ddc_out_sample[31:28];
        q_msb = ddc_out_sample[15:12];
        // to avoid if-else condition   
        bb_strobe = (count==2'd3);
        bb_sample = bb_strobe ? temp_buff : 32'd0;  
    end

    assign ddc_in_i = frontend_i;
    assign ddc_in_q = frontend_q;
    assign ddc_out_enable = enable; 

endmodule //my_rx_dsp0_custom
 

Now I wanted to implement a testbench that tests my_rx_dsp0.v with some examples. I implemented a my_rx_dsp0_tb_2.v, which reads 32 bit samples from a file named my_input.dat to feed to the module as inputs ddc_out_sample. They are then compared to the correct values stored at my_output.dat.

Note: I did not write this testbench myself, I adapted it from another testbench from an open-source project.

Here is the implementation:

module my_rx_dsp0_tb ( );

reg clk;
reg reset;
reg enable;
reg ddc_out_strobe; //high on valid sample
reg [31:0] ddc_out_sample;
wire [31:0] bb_sample = 32'd0;
wire bb_strobe;
wire ddc_out_enable = 1'b1; //enables DDC module

parameter WIDTH = 24;
parameter clocks = 2; // number of clocks per input

reg endofsim = 0;
integer number_of_errors;
initial number_of_errors = 0;

wire set_stb = 1;
wire [7:0] set_addr;
wire [31:0] set_data;
wire [WIDTH-1:0] frontend_i;
wire [WIDTH-1:0] frontend_q;
wire [WIDTH-1:0] ddc_in_i;
wire [WIDTH-1:0] ddc_in_q;

reg signed [31:0] compare_out;

// Setup the clock
initial clk = 1'b0;
always #5 clk <= ~clk ;

// Come out of reset after a while
initial reset = 1'b1 ;
initial #1000 reset = 1'b0 ;

// Enable the entire system
initial enable = 1'b1 ;

// Instantiate UUT
my_rx_dsp0 #(.WIDTH(WIDTH)) UUT_rx_dsp0
    (   .clock(clk), .reset(reset), .clear(clear), .enable(enable),
        .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
        .frontend_i(frontend_i), .frontend_q(frontend_q),
        .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q),
        .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable),
        .bb_sample(bb_sample), .bb_strobe(bb_strobe) );

//-------Setup file IO-------//
//
integer i, r_in, r_out, infile, outfile;

initial begin
    infile = $fopen("my_input.dat","r");
    outfile = $fopen("my_output.dat","r");
    $timeformat(-9, 2, " ns", 10) ;
    // for n=9,p=2 digits after decimal pointer
    //min_field_width=10 number of character positions for %t
end      

//-------Get sim values and display errors-------//
//
initial begin
    // Initialize inputs
    ddc_out_strobe <= 1'd0;
    ddc_out_sample <= 32'd0;

    // Wait for reset to go away
    @(negedge reset) #0;

    while(!endofsim) begin
        // Write the input from the file or 0 if EndOfFile(EOF)
        @(posedge clk) begin
            #1
            ddc_out_strobe <= 1'b1;
            if(!$feof(infile))
                r_in = $fscanf(infile,"%b\n",ddc_out_sample);
            else
                ddc_out_sample <= 32'd0;
        end
        //
        // Clocked in; set the strobe to 0 if the # of clocks/sample
        // is greater than 1
        if( clocks > 1 ) begin
            @(posedge clk) begin
                ddc_out_strobe <= 1'b0  ;
            end

            // Wait for the specified # of cycles
            for( i = 0 ; i < (clocks-2) ; i = i + 1 ) begin
                @(posedge clk) #1 ;
            end
        end
        //

        //
        // Print out the number of errors that occured
        if(number_of_errors) begin
            $display("FAILED: %d errors during simulation",number_of_errors) ;
        end else begin
            $display("PASSED: Simulation successful") ;
        end 
        // 
    end 
end

//-------Comparison btwn simulated values vs known good values-------//
//
always @(posedge clk) begin
    if(reset)
        endofsim <= 1'b0 ;
    else begin
        if(!$feof(outfile)) begin
            if(bb_strobe) begin
                r_out = $fscanf(outfile,"%b\n",compare_out);
                if(compare_out != bb_sample) begin
                    $display("%t: %b != %b",$realtime,bb_sample,compare_out);
                    number_of_errors = number_of_errors + 1;
                end else begin
                    $display("%t: %b = %b",$realtime,bb_sample,compare_out);
                end
            end
        end else begin
            // Signal end of simulation when no more outputs
            endofsim <= 1'b1 ;
        end
    end
end 

endmodule // my_rx_dsp0_tb
 

When simulating with ISim from Xilinx ISE Suite Edition 12.1 I do not get the desired functionality from the module. I am afraid the output contains several x states (unknown states), instead of 1s or 0s as expected.

Question Is this due to:

1) The way the files are being read with $fscanf?

2) Did I wrong by initializing reg [31:0] temp_buff = 0?

3) Or does someone have an idea on what went wrong?

The error prompts from the testbench are (as an example): xx000x00xxx00x0xx000x0x000000000 != 10000110111001011100010001101100

最满意答案

X来自bb_sample和ddc_out_enable上的多个冲突驱动程序。 wire类型合并驱动程序,相同强度的冲突位值解析为X.

UUT_rx_dsp0是潜水员。 但是,您通过声明电线的方式添加了其他驱动程序。

... wire [31:0] bb_sample = 32'd0; // "= 32'd0" is a continuous driver wire bb_strobe; wire ddc_out_enable = 1'b1; // "= 1'd1" is a continuous driver ...

你想要的是:

... wire [31:0] bb_sample; wire bb_strobe; wire ddc_out_enable; ...

纠正上述问题将解决X问题。 基于示例错误,它看起来像数据未命中匹配。 根据提供的信息,很难说它是测试平台还是设计问题。 可能只是时钟或传播偏斜。

The X is from having multiple conflicting drivers on bb_sample and ddc_out_enable. The wire type merges the drivers, conflicting bit values of the same strength resolve as X.

UUT_rx_dsp0 is the intended diver. However you added and additional drivers from the way you declared your wires.

... wire [31:0] bb_sample = 32'd0; // "= 32'd0" is a continuous driver wire bb_strobe; wire ddc_out_enable = 1'b1; // "= 1'd1" is a continuous driver ...

What you want is:

... wire [31:0] bb_sample; wire bb_strobe; wire ddc_out_enable; ...

Correcting the above will resolve the X issue. Based on the example error it looks like are data miss matches. With the provided information, it is hard to tell it if it a test-bench or design issue. Could be just clock or propagation skew.

更多推荐

本文发布于:2023-08-06 05:31:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1444825.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   测试   平台   Verilog   MSB

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!