几天前,我询问了一个模块( 这里 ),我想实现它接收输入样本的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_customNow 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_tbWhen 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.
更多推荐
发布评论