Verilog中assign与always执行顺序及MAC模块反馈逻辑疑问
代码原文(注:原文存在一处语法笔误,always行敏感列表前遗漏@符号,正确写法需补充)
module mult_acc(input data1,data2, clk,aclr,output reg mac_out); wire mult_out,add_out; assign add_out = mult_out+mac_out; // dataflow multiplier my_mult(.in1(data1),.in2(data2),.out(mult_out)); always @(posedge clk, posedge aclr) begin if(aclr) mac_out<= 1'b0; else mac_out<= add_out; end endmodule
疑问解答
1. 反馈关系是否由assign语句定义?
是。assign add_out = mult_out + mac_out;这条连续赋值语句定义了反馈的数值连接:寄存器mac_out存储的上一周期累加结果,会和乘法器输出mult_out相加得到add_out;而add_out又会在时钟上升沿被锁存回mac_out,形成完整的累加反馈回路。
2. 模块实例化my_mult是否会输出mult_out?
是。multiplier my_mult(.in1(data1),.in2(data2),.out(mult_out));是将data1、data2接入乘法器模块的输入端口,同时把乘法器的输出端口绑定到mult_out这个wire变量上。只要multiplier模块内部逻辑正确,就会输出data1与data2的乘法结果到mult_out。
3. 若assign语句与mult_out并发执行,assign如何获取最新的mult_out值?
Verilog中assign语句属于组合逻辑的连续赋值,不存在“执行顺序”的概念——当mult_out或mac_out的数值发生变化时,add_out会立即同步更新为两者的和。也就是说,mult_out一产生新值,assign就会用这个新值计算add_out,不需要等待任何操作完成。
4. always块是否在assign和mult_out执行后才运行?
不是。这个always块是时序逻辑,仅在时钟上升沿或复位信号上升沿触发时执行块内的赋值操作。而assign和乘法器的组合逻辑是持续响应输入变化的:在时钟上升沿到来前,mult_out和add_out已经稳定在当前输入对应的数值,此时always块触发,将add_out锁存到mac_out中。
Verilog中assign语句与always块的执行逻辑
Verilog是并发执行的硬件描述语言,assign和always块之间不存在“先后执行顺序”,它们各自独立响应自身的触发条件:
assign语句属于连续赋值,只要右侧的任意变量发生变化,左侧变量会立即更新,全程持续生效,用于描述组合逻辑。always块分两种类型:- 带时钟/复位触发的(如本例的
@(posedge clk, posedge aclr))是时序逻辑,仅当触发事件(时钟沿、复位沿)发生时,才会执行块内的赋值操作,通常用非阻塞赋值<=来保证时序正确性。 - 敏感列表为组合信号的(如
@(a or b))是组合逻辑,和assign类似,当敏感信号变化时立即执行,但写法不同。
- 带时钟/复位触发的(如本例的
简言之,组合逻辑(assign、组合型always块)实时响应输入变化,时序逻辑(时钟触发的always块)仅在特定事件触发时动作,二者并行运作,没有先后执行的顺序。
内容的提问来源于stack exchange,提问作者Kanmani

