在modesim上仿真verilog代码遇到了一个奇怪的问题,代码写的是非阻塞赋值语句但是仿真结果缺变成了阻塞语句的赋值结果
部分代码如下
module mapminmax_apply(
input wire clk,
input signed [12:0] filter_in,
input signed [12:0] data,
input wire enable,
output reg [25:0] q1, // 输出信号也需要设置为寄存器类型以便在always块中赋值 sfix29_en24
output reg [25:0] q2 // 输出信号也需要设置为寄存器类型以便在always块中赋值 sfix29_en24
);
always @(posedge clk) begin
if (enable) begin
// 步骤1:减去xoffset,将赋值结果修改成sfix26_en24
filter_in1 <= $signed({filter_in,{12{1'b0}}}) - x1_step1_xoffset1; //没有加$signed不能识别出来是否有符号位
//data1 <= data - x1_step1_xoffset2; // 本质上是data - 0,那就什么也不计算,直接阻塞赋值
data1 <= {data,{12{1'b0}}};
问题就出在filter_in1和data1的非阻塞赋值上
仿真结果如下图
可以看到由filter_in,data端口输入的数据在经过非阻塞赋值后,确显示的是阻塞赋值的结果,没有一个周期后输出。
由于我在该model之上直接用tb文件提取txt文件中的数据充当输入,所以当时没有发现这个问题。
但是当我将filter_in通过计算后再通过寄存器赋值给wire类型输出到该model当输入时,出现了问题,filter_in1的非阻塞赋值正常了,但是data1的非阻塞赋值还是没有正常,导致他们两个的输出时间不一致。
解决办法:将data在输入该模块之前也像filter_in一样通过一个寄存器,就可以都实现非阻塞赋值
在filter计算结果的结尾,都通过寄存器(部分代码)error_in为原来的data输入
always @ ( posedge clk)
begin: Output_Register_process
if (reset == 1'b1) begin
output_register <= 0;
end
else begin
if (phase_13 == 1'b1) begin
output_register <= output_typeconvert;
error_out_register <=error_in;
end
end
end // Output_Register_process
// Assignment Statements
assign filter_out = output_register;
assign error_out =error_out_register;
endmodule // filter
最终修改好的结果图