几天前我问了一个我想要实现的模块(here),它接收输入样本的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
中存储的正确值进行比较。
注意:我自己没有编写这个测试平台,我是从开源项目的另一个测试平台改编而来的。
以下是实施:
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
答案 0 :(得分:0)
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问题。基于示例错误,它看起来像数据未命中匹配。根据提供的信息,很难说它是测试平台还是设计问题。可能只是时钟或传播偏斜。