文章目录
- 1 D flip-flop基础知识
- 2 D flip-flops
- 3 DFF with synchronous reset
- 4 DFF with reset value(synchronous reset)
- 5 DFF with asynchronous reset
- 6 DFF with byte enable
- 7 D Latch
- 8 DFF
- 9 DFF
- 10 DFF+gate
- 11 Mux and DFF
- 12 Mux and DFF
- 13 DFFs and gates
- 14 Create circuits from truth table
- 15 Detect an edge
- 16 Detect both edges
- 17 Edge capture register
- 18 Dual-edge triggered flip-flop
1 D flip-flop基础知识
A D flip-flop is a circuit that stores a bit and is updated periodically, at the (usually) positive edge of a clock signal.
对于边沿触发的D触发器,具有两个稳定状态(“0"和"1”),D触发器在时钟脉冲CP的前沿(正跳变0→1)发生翻转。
D flip-flops are created by the logic synthesizer when a clocked always block is used(always @ (posedge clk)).
A D flip-flop is the simplest form of “blob of combinational logic followed by a flip-flop” where the combinational logic portion is just a wire.
练习Dff: 创建一个简单的D flip-flop
module top_module(
input clk,
input d,
output reg q);
// Use non-blocking assignment for edge-triggered always blocks
always @(posedge clk)
q <= d;
endmodule
2 D flip-flops
Create 8 D flip-flops. All DFFs should be triggered by the positive edge of clk.
module top_module (
input clk,
input [7:0] d,
output [7:0] q
);
always @(posedge clk)
q <=d;
endmodule
3 DFF with synchronous reset
Create 8 D flip-flops with active high synchronous reset. All DFFs should be triggered by the positive edge of clk.
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output [7:0] q
);
always @(posedge clk)begin
if(reset) //高电平复位
q <= 8'b0;
else
q <= d;
end
endmodule
4 DFF with reset value(synchronous reset)
Create 8 D flip-flops with active high synchronous reset. The flip-flops must be reset to 0x34 rather than zero. All DFFs should be triggered by the negative edge of clk.
module top_module (
input clk,
input reset,
input [7:0] d,
output [7:0] q
);
always @(negedge clk)begin
if(reset)
q <= 8'h0x34;
else
q <= d;
end
endmodule
5 DFF with asynchronous reset
Create 8 D flip-flops with active high asynchronous reset. All DFFs should be triggered by the positive edge of clk.
module top_module (
input clk,
input areset, // active high asynchronous reset
input [7:0] d,
output [7:0] q
);
// The only difference in code compared to synchronous reset is in the sensitivity list.
always @(posedge clk, posedge areset)
if (areset)
q <= 8'b0;
else
q <= d;
endmodule
Synchronous同步逻辑 vs Asynchronous异步逻辑
Synchronous control signals are sampled with respect to clock
• If reset is asserted, it will not be effective until the next active clock edge
Asynchronous control signals are sampled independently of clock
signal
• If reset is asserted, it will be effective immediately. It will not wait for the next
active clock edge
更详细的解释可以去看这个博客:https://blog.csdn.net/weixin_45746372/article/details/126009537
6 DFF with byte enable
Create 16 D flip-flops. It’s sometimes useful to only modify parts of a group of flip-flops. The byte-enable inputs control whether each byte of the 16 registers should be written to on that cycle. byteena[1] controls the upper byte d[15:8], while byteena[0] controls the lower byte d[7:0].
resetn is a synchronous, active-low reset.
All DFFs should be triggered by the positive edge of clk.
module top_module (
input clk,
input resetn,
input [1:0] byteena,
input [15:0] d,
output [15:0] q
);
always @(posedge clk) begin
if(!resetn)
q <= 16'd0;
else begin
case(byteena)
2'b01: q[7:0] <= d[7:0];
2'b10: q[15:8] <= d[15:8];
2'b11: q <= d;
default: q <= q;
endcase
end
end
endmodule
7 D Latch
module top_module (
input d,
input ena,
output q);
always @(*)
if (ena)
q <=d;
endmodule
8 DFF
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output q);
always @(posedge clk, posedge ar)begin
if(ar)
q <= 0;
else
q <= d;
end
endmodule
9 DFF
module top_module (
input clk,
input d,
input r, // synchronous reset
output q);
always @(posedge clk)begin
if(r)
q <= 0;
else
q <= d;
end
endmodule
10 DFF+gate
module top_module (
input clk,
input in,
output out);
always @(posedge clk)
out <= in ^ out;
endmodule
11 Mux and DFF
Assume that you want to implement hierarchical Verilog code for this circuit, using three instantiations of a submodule that has a flip-flop and multiplexer in it. Write a Verilog module (containing one flip-flop and multiplexer) named top_module for this submodule.
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
wire q1;
Mux2_1 mux(r_in, q_in, L, q1);
flipflop ff(q1, clk, Q);
endmodule
module flipflop(input d, input clk, output q);
always @(posedge clk)
q <= d;
endmodule
module Mux2_1(input a,input b, input L, output c);
assign c = (L)?a:b;
endmodule
12 Mux and DFF
module top_module (
input clk,
input w, R, E, L,
output reg Q
);
wire out1,out2;
Mux2_1 inst1(w, Q, E, out1);
Mux2_1 inst2(R, out1, L, out2);
flipflop inst3(out2, clk, Q);
endmodule
module Mux2_1(input a, input b, input choose, output c);
assign c = (choose)?a:b;
endmodule
module flipflop(input d, input clk, output q);
always @(posedge clk)
q <= d;
endmodule
13 DFFs and gates
module top_module (
input clk,
input x,
output z
);
reg q1 = 0, q2 = 0, q3 = 0; //D flip-flops are initially reset to zero before the machine begins.一定要初始化为0,不然是错的
wire d1,d2,d3;
assign d1 = x ^ q1;
dff inst1(d1, clk, q1);
assign d2 = x & (~q2);
dff inst2(d2, clk, q2);
assign d3 = x | (~q3);
dff inst3(d3, clk, q3);
assign z = ~(q1 | q2 | q3);
endmodule
module dff(input d, input clk, output q);
always @(posedge clk)
q <= d;
endmodule
14 Create circuits from truth table
A JK flip-flop has the below truth table. Implement a JK flip-flop with only a D-type flip-flop and gates. Note: Qold is the output of the D flip-flop before the positive clock edge.
module top_module (
input clk,
input j,
input k,
output Q);
always @(posedge clk)
Q <= ((~j)&(~k)&Q) | (j&(~k)) | (j&k&(~Q));
endmodule
15 Detect an edge
For each bit in an 8-bit vector, detect when the input signal changes from 0 in one clock cycle to 1 the next (similar to positive edge detection). The output bit should be set the cycle after a 0 to 1 transition occurs.检测到上升沿之后,延迟一个周期拉高输出
Here are some examples. For clarity, in[1] and pedge[1] are shown separately.
这里是一个博主详细的解题过程:~ 边沿检测
我的理解:
目的是检测 8 位输入信号 in 中每个位的上升沿(从 0 变为 1 的跳变),并在跳变发生后的下一个时钟周期将对应的输出位 pedge 置为 1。
代码解析:
寄存器 temp_reg:
temp_reg 用于存储 in 在上一个时钟周期的值,这样可以将当前值 in 与上一个时钟周期的值 temp_reg 进行比较。
时序逻辑:
always @ (posedge clk) 表示该逻辑块在每个时钟的上升沿触发。
temp_reg <= in; 将当前的 in 值保存到 temp_reg 中,这样在下个时钟周期时,temp_reg 就是 in 的前一个值。
pedge <= ~temp_reg & in; 是上升沿检测的核心逻辑。
上升沿检测逻辑:
~temp_reg & in 是一个位操作,对每个位独立进行以下判断:
~temp_reg 是 temp_reg 的按位取反,即如果 temp_reg 的某一位为 0,取反后为 1。
& in 表示只有当 temp_reg 的某一位为 0(取反后为 1)且当前 in 的对应位为 1 时,结果的该位才为 1。
这正好对应“上升沿”的定义:上一个周期为 0(temp_reg 的对应位为 0),当前周期为 1(in 的对应位为 1)。
这种写法利用了寄存器的特性:
temp_reg 存储了 in 的历史值(上一个时钟周期的值)。
通过 ~temp_reg & in,可以检测出哪些位从 0 变为了 1。
由于 temp_reg 和 pedge 的更新是在同一个 always 块中,且是非阻塞赋值(<=),因此 pedge 的计算使用的是 temp_reg 的旧值(即上一个时钟周期的 in 值),而 temp_reg 的新值(当前 in)会在下一个时钟周期生效。
补充:为什么temp_reg 存储 in 在上一个时钟周期的值?
这是由时序逻辑的非阻塞赋值(<=)和时钟边沿触发的特性决定的
- 非阻塞赋值特性(<=)
在时钟上升沿触发时:
- 先计算所有 <= 右侧的表达式(此时使用的是当前 temp_reg 和 in 的值)。
- 然后 同时更新 所有 <= 左侧的寄存器(temp_reg 和 pedge)。
因此:
temp_reg <= in; 并不会立即更新 temp_reg,而是等到时钟边沿结束后才更新。
在计算 pedge <= ~temp_reg & in; 时,temp_reg 仍然是 上一个时钟周期的值,而 in 是当前的新值。
2. 时序逻辑的“延迟一拍”效果
由于 temp_reg 的更新是在时钟边沿之后才生效,它的值总是比 in 慢一个时钟周期。
在周期 1:
temp_reg 还未更新,仍为初始值(假设为 0)。
pedge 计算为 ~0 & A = A(即如果 A 的某位为 1,则 pedge 对应位为 1)。
时钟边沿结束后,temp_reg 更新为 A。
在周期 2:
temp_reg 已经是周期 1 的 in 值(A)。
pedge 计算为 ~A & B(检测从 A 到 B 的上升沿)。
时钟边沿结束后,temp_reg 更新为 B。
因此,temp_reg 始终存储的是 in 在上一个时钟周期的值。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg[7:0] temp_pedge;
always @(posedge clk)begin
temp_pedge <= in;
pedge <= ~temp_pedge & in;
end
endmodule
16 Detect both edges
For each bit in an 8-bit vector, detect when the input signal changes from one clock cycle to the next (detect any edge). The output bit should be set the cycle after a 0 to 1 transition occurs. 检测输入信号的所有跳变(0到1,1到0)
上图源自:图片
从波形分析可得,anyedge 和前两者的关系是异或。
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0] temp_anyedge;
always @(posedge clk)begin
temp_anyedge <= in;
anyedge <= temp_anyedge ^ in;
end
endmodule
17 Edge capture register
For each bit in a 32-bit vector, capture when the input signal changes from 1 in one clock cycle to 0 the next. “Capture” means that the output will remain 1 until the register is reset (synchronous reset).
Each output bit behaves like a SR flip-flop:
- The output bit should be set (to 1) the cycle after a 1 to 0 transition occurs.
- The output bit should be reset (to 0) at the positive clock edge when reset is high.
- If both of the above events occur at the same time, reset has precedence.
In the last 4 cycles of the example waveform below, the ‘reset’ event occurs one cycle earlier than the ‘set’ event, so there is no conflict here.
对于32bits向量中的每一位,当输入信号由1变为0时进行检测(即下降沿检测)。其中检测表示在复位信号(同步)到达前,输出将保持1。 每一个输出位就像一个RS触发器,即当对应位出现1 to 0的变化时,输出位将置1;而当reset信号为高电平,输出位将在下一个时钟的上升沿被复位。如果信号的下降沿和reset事件在同一时刻发生,将优先执行复位操作。在下图示例波形的最后4个时钟周期中,reset事件比‘set’事件早一个周期出现,因此这里没有前述冲突。 为清楚起见,in[1]和out[1]在波形中分别单独显示。
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_last;
always@(posedge clk) //D Flip-Flop
in_last <= in;
always@(posedge clk)
if(reset)
out <= 0;
else
out <= out | in_last & ~in;
endmodule
首先电路需要检测下降沿,其次在检测到的下降沿所在位进行置位操作,同时还不能影响到其他已置位的输出位。因此,代码核心部分"out <= out | in_last & ~in;",在下降沿检测的基础上,采用或逻辑,使得无论是新检测到的下降沿,还是先前已被置位的下降沿,都能使输出保持1状态。
18 Dual-edge triggered flip-flop
You’re familiar with flip-flops that are triggered on the positive edge of the clock, or negative edge of the clock. A dual-edge triggered flip-flop is triggered on both edges of the clock. However, FPGAs don’t have dual-edge triggered flip-flops, and always @(posedge clk or negedge clk) is not accepted as a legal sensitivity list.
FPGA中没有双边沿触发器,因此不能在always块中直接使用"posedge clk or negedge clk"的写法。因此,构造两个触发器(上升沿触发和下降沿触发)。
Build a circuit that functionally behaves like a dual-edge triggered flip-flop:
module top_module (
input clk,
input d,
output q
);
reg p, n;
// A positive-edge triggered flip-flop
always @(posedge clk)
p <= d ^ n;
// A negative-edge triggered flip-flop
always @(negedge clk)
n <= d ^ p;
assign q = p ^ n;
endmodule
这里不要用for语句,因为for循环语句在Verilog中属于不可综合语言,一般只用来编写TestBench测试文件,而不能用来设计可综合电路。