VL2 异步复位的串联T触发器
要求:

思路一:先写一个T触发器模块,再例化使用
`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output q
);
//*************code***********//
wire q1;
Tff tf1(clk , rst , data , q1);
Tff tf2(clk , rst , q1 , q);
//*************code***********//
endmodule
module Tff(
input clk , rst ,
input data,
output reg q
);
always @(posedge clk , negedge rst ) begin
if(!rst) q <= 0;
else
q <= (data) ? (~q) : q ;
end
endmodule
注意:
1.Tff模块得用 <= 非阻塞赋值
2.Tff_2里边的q得用wire类型,因为reg类型不能在例化语句里用,否则报错

总结一下阻塞赋值和非阻塞赋值:
✅ 阻塞赋值(=)
1.顺序执行:像 C 语言一样,一条语句执行完才执行下一条。
2.立即更新:赋值右边计算后,左边变量立刻被更新,后续语句看到的是新值。
3.通常用于 组合逻辑(如 always @(*) 块)。
✅ 非阻塞赋值(<=)
1.并行调度:所有非阻塞赋值的右边先计算,等到块结束时再同时更新左边。
2.延迟更新:在当前 always 块内,读取的仍是旧值。
3.通常用于 时序逻辑(如 always @(posedge clk) 块)。
解释:
“块结束时”指的是 当前过程块(always 或 initial 块)中所有语句的执行逻辑完成之后,具体来说是非阻塞赋值(<=)的赋值动作被调度到仿真时间步的末尾才真正执行。
例子:
always @(posedge clk) begin
a <= b;
c <= a;
end
执行流程如下:
1.在 posedge clk 触发后,进入 always 块。
2.
计算 a <= b 的右边值(即 b 的当前值)。
计算 c <= a 的右边值(注意:这里用的是 a 的当前值,不是刚要被赋的新值)。
这些右边的值被暂存起来,但不立即更新左边变量。
当整个 always 块中的所有语句都处理完(即“块结束”),仿真器进入 NBA Region。
3.
在 NBA Region 中,同时将暂存的值赋给左边变量:
a 被更新为 b 的旧值,
c 被更新为 a 的旧值。
对比阻塞赋值
always @(posedge clk) begin
a = b;
c = a; // 这里 a 已经是新值!
end
第二行看到的 a 是第一行刚刚更新后的值。
不明白就记住吧:
“组合用 =,时序用 <=”。
思路二:
`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q
);
//*************code***********//
reg t;
always @(posedge clk , negedge rst) begin
if(!rst) begin t <= 0; q <= 0; end
else
// t <= (data) ? (~t) : t;
// q <= t ? (~q) : q;
if(data) t <= ~t;
if(t) q <= (~q);
end
//*************code***********//
endmodule
推荐使用
if(data) t <= ~t;
if(t) q <= (~q);
最好是写两个always块
`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q
);
//*************code***********//
reg t;
always @(posedge clk , negedge rst) begin
if(!rst) t <= 0;
else
if(data) t <= ~t;
end
always @(posedge clk , negedge rst) begin
if(!rst) q <= 0;
else
if(t) q <= ~q;
end
//*************code***********//
endmodule
5582

被折叠的 条评论
为什么被折叠?



