实例化问题
理论上在顶层模块或testbench文件中的实例化模块是并行执行的,但实际上在程序执行的过程中会出现短暂的延迟,尤其信号恰好处于时钟上升沿的时候,波形的变化会变得很明显。所以在实现具体电路时应尽量化繁为简
module top_module ( input clk, input x, output z ); wire xo,an,ro,q0,q1,q2,qf1,qf2; QQ qq0(.clk(clk),.d(xo),.q(q0)); QQ qq1(.clk(clk),.d(an),.q(q1),.qf(qf1)); QQ qq2(.clk(clk),.d(ro),.q(q2),.qf(qf2)); assign xo = x^q0; assign an = x&qf1; assign ro = x|qf2; assign z = ~(q0|q1|q2); endmodule module QQ( input clk, input d, output reg q, output reg qf ); always@(posedge clk) begin q<=d; qf<=~d; end endmodule
module top_module ( input clk, input x, output z ); wire xo,an,ro,q0,q1,q2; QQ qq0(.clk(clk),.d(xo),.q(q0)); QQ qq1(.clk(clk),.d(an),.q(q1)); QQ qq2(.clk(clk),.d(ro),.q(q2)); assign xo = x^q0; assign an = x&~q1; assign ro = x|~q2; assign z = ~(q0|q1|q2); endmodule module QQ( input clk, input d, output reg q ); always@(posedge clk) begin q<=d; end endmodule
module top_module ( input clk, input x, output z ); reg Q1,Q2,Q3; always @(posedge clk) begin Q1 <= (x ^ Q1); Q2 <= (x & ~Q2); Q3 <= (x | ~Q3); end assign z = ~(Q1|Q2|Q3); endmodule
仿真后波形可以看到的是,第一段代码出现的波形与第二三段代码出现的波形并不相同,而其基于的基础电路都是相同的。
另外可见
https://blog.csdn.net/weixin_41687532/article/details/119877946
对于解决办法,我所能想到的只有延时,希望在学习过程中能有一些别的想法吧。
波形图分析
在对总线变化进行分析时,若总线遵循同一变化规则,则可以视为一条信号线,通过分析一条信号线的高低电平变化可以快速得出变化公式如
always语句块
检测时钟上升沿时,信号变化若恰好处于上升沿有可能会发生竞争冒险的情况,所以一般信号的变化不会在时钟检测边沿处发生,如上图的情况,信号的变化总是略晚于上升沿。
逻辑符号的使用
在条件判断时不要省略写法,注意需要判断数据的位数,需要多位同时判断时使用位运算逻辑符,在位数不等或仅仅逻辑判断时使用逻辑运算符,在一般情况下使用逻辑运算符比较常见。请注意!!!
always语句块中不能出现实例化电路的部分,实例化模块只能在always外或generate中产生,always中仅仅用到信号的综合
if_else
使用中需要注意always中符合条件语句后程序就只运行if_else中间的语句,运行完直接跳出不会再顺序执行其他的条件判断如:
只会执行某一if_else中的语句,满足后执行完内部语句直接跳出,其他语句忽略,所以在写if_else语句时要尽可能的将信号的情况写完,包括所要执行的语句。
状态机编写问题
在编写状态机时,可以引入当前状态和下一状态的中间变量,在状态改变结束后赋值,但需要注意的是在中间状态变量未赋值的情况下容易出现信号高低的随机可能,所以要使用阻塞赋值,变量有明确的值后再进行下一步赋值
如果采用非阻塞赋值由于并行执行的原因信号会出现不稳定的情况
如以下简单示例
module top_module(clk, reset, in, out); input clk; input reset; // Synchronous reset to state B input in; output out;// reg out; reg present_state, next_state; parameter B=1'b1,A=1'b0; always @(posedge clk) begin if (reset) begin // reset logic present_state<=B; out<=1'b1; end else begin case (present_state) // state transition logic B:begin if(in==1'b0) next_state=A; else next_state=B; end A:begin if(in==1'b0) next_state=B; else next_state=A; end endcase // State flip-flops present_state = next_state; case (present_state) // output logic A:out<=1'b0; B:out<=1'b1; endcase end end endmodule
在状态转换逻辑中使用阻塞和非阻塞赋值的情况是不一样的,并且实际上阻塞赋值语句的波形是我们需要且稳定的。
存在一个状态的下一级为多个状态的情况时及有多个条件进行状态转换时使用case内含if语句要注意条件的优先顺序。