Verilog代码中always块多次赋值后H_value仅显示最终值的问题咨询
Verilog always块多次赋值的仿真结果异常分析
设计代码
module calH( input clk, input rst, input [1:0] xin, input [15:0] coeff, //4bit per coefficient output reg [1:0] xout, //1 bit per x output wire [7:0] H_value ); reg [7:0] H_p; //processed H always@(posedge clk or negedge rst) begin if(~rst) begin //set initial condition H_p <= 0; end else begin //cal H H_p <= xin[0]*xin[0]*coeff[15 -: 4]; H_p <= xin[0]*xin[1]*coeff[11 -: 4]; H_p <= xin[1]*xin[0]*coeff[7 -: 4]; H_p <= xin[1]*xin[1]*coeff[3 -: 4]; end end assign H_value = H_p; endmodule
问题描述
测试台中设置coeff=16'h1234,预期H_value在时钟沿触发后依次输出1→2→3→4,但Modelsim仿真结果仅显示4,请问原因是什么?
解答
- 核心原因:Verilog非阻塞赋值的并行特性
在同一个always@(posedge clk)触发的块中,对同一个寄存器H_p的多次非阻塞赋值(<=)是并行执行的,而非顺序执行。所有赋值语句的右侧表达式会先被计算,然后在时钟沿结束后统一更新寄存器的值。但因为是对同一个寄存器赋值,只有最后一条赋值语句的结果会覆盖前面所有的,最终H_p只会被最后一条语句H_p <= xin[1]*xin[1]*coeff[3 -: 4]更新。
当coeff=16'h1234时,coeff[3 -: 4]对应低4位的4'h4,因此最终H_value只会输出4,和仿真结果一致。
- 实现预期依次输出的修正方案
如果需要在四个时钟周期内依次输出1→2→3→4,需要引入计数器或状态机控制每个时钟周期执行一次赋值:
reg [1:0] cnt; always@(posedge clk or negedge rst) begin if(~rst) begin H_p <= 0; cnt <= 0; end else begin case(cnt) 2'd0: H_p <= xin[0]*xin[0]*coeff[15 -: 4]; 2'd1: H_p <= xin[0]*xin[1]*coeff[11 -: 4]; 2'd2: H_p <= xin[1]*xin[0]*coeff[7 -: 4]; 2'd3: H_p <= xin[1]*xin[1]*coeff[3 -: 4]; endcase cnt <= cnt + 1'b1; end end
这样每个时钟周期cnt递增,依次执行不同的赋值语句,就能得到预期的序列输出。
内容的提问来源于stack exchange,提问作者Steve Deltora
相关产品推荐
相关产品推荐

