关注 望森FPGA 查看更多FPGA资讯
这是望森的第 12 期分享
作者 | 望森
来源 | 望森FPGA
目录
4 DFF with reset value | 带复位值的 D 触发器
5 DFF with asynchronous reset | 具有异步复位的 D 触发器
6 DFF with byte enable | 带字节使能的 D 触发器
13 DFFs and gates | D 触发器与门电路的组合
14 Create circuit from truth table | 根据真值表设计电路
17 Edge capture register | 边沿捕获寄存器
18 Dual-edge triggered fip-fop | 双沿触发的触发器
本文中的代码都能够正常运行,请放心食用😋~
练习的官方网站是:https://hdlbits.01xz.net/
注:作者将每个练习的知识点都放在了题目和答案之后
1 D fip-flop | D触发器
题目:
D 触发器是一种存储位并定期更新的电路,更新时间通常是在时钟信号的正边沿。
当使用时序always块时,逻辑合成器会创建 D 触发器(请参阅 alwaysblock2)。D 触发器是“组合逻辑块后跟触发器”的最简单形式,其中组合逻辑部分只是一条线。
创建单个 D 触发器。
答案:
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q );//
// Use a clocked always block
// copy d to q at every positive edge of clk
// Clocked always blocks should use non-blocking assignments
always@(posedge clk)begin
q <= d;
end
endmodule
知识点:
注意时序电路设计中的赋值语句要使用非阻塞赋值“<=”。
2 D fip-flops | D 触发器
题目:
创建 8 个 D 触发器。所有 D触发器 都应由 clk 的正沿触发。
答案:
module top_module(
input clk,
input [7:0] d,
output reg [7:0] q);
// Because q is a vector, this creates multiple DFFs.
always @(posedge clk)
q <= d;
endmodule
3 DFF with reset | 带复位的 D 触发器
题目:
创建 8 个具有高电平有效同步复位的 D 触发器。所有D 触发器都应由 clk 的正沿触发。
答案:
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output [7:0] q
);
always @(posedge clk)begin
if (reset) begin
q <= 8'd0;
end
else begin
q <= d;
end
end
endmodule
知识点:
同步复位需要根据时钟触发沿进行触发。
4 DFF with reset value | 带复位值的 D 触发器
题目:
创建 8 个具有高电平有效同步复位的 D 触发器。触发器必须复位为 0x34,而不是零。所有 DFF 都应由 clk 的负沿触发。
答案:
module top_module (
input clk,
input reset,
input [7:0] d,
output [7:0] q
);
always @(negedge clk)begin
if (reset) begin
q <= 8'h34;
end
else begin
q <= d;
end
end
endmodule
知识点:
正沿触发用“posedge”,负沿触发用“negedge”。
5 DFF with asynchronous reset | 具有异步复位的 D 触发器
题目:
创建 8 个具有高电平有效异步复位的 D 触发器。所有 D 触发器 都应由 clk 的正沿触发。
答案:
module top_module(
input clk,
input [7:0] d,
input areset,
output reg [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 <= 0;
else
q <= d;
// In Verilog, the sensitivity list looks strange. The FF's reset is sensitive to the
// *level* of areset, so why does using "posedge areset" work?
// To see why it works, consider the truth table for all events that change the input
// signals, assuming clk and areset do not switch at precisely the same time:
// clk areset output
// x 0->1 q <= 0; (because areset = 1)
// x 1->0 no change (always block not triggered)
// 0->1 0 q <= d; (not resetting)
// 0->1 1 q <= 0; (still resetting, q was 0 before too)
// 1->0 x no change (always block not triggered)
endmodule
知识点:
异步复位需要将复位信号写入敏感列表中。
6 DFF with byte enable | 带字节使能的 D 触发器
题目:
创建 16 个 D 触发器。有时仅修改一组触发器的部分内容很有用。字节启用输入控制是否应在该周期写入 16 个寄存器中的每个字节。byteena[1] 控制高字节 d[15:8],而 byteena[0] 控制低字节 d[7:0]。
resetn 是同步、低电平有效复位。
所有 DFF 都应由 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[15:8] <= 8'd0;
else if (byteena[1])
q[15:8] <= d[15:8];
else
q[15:8] <= q[15:8];
end
always @(posedge clk)begin
if (!resetn)
q[7:0] <= 8'd0;
else if (byteena[0])
q[7:0] <= d[7:0];
else
q[7:0] <= q[7:0];
end
endmodule
知识点:
低电平有效的信号在声明时一般在结尾加上"n"。
7 D Latch | D 锁存器
题目:
实现以下电路:
请注意:这是一个闩锁,因此预计会出现有关推断闩锁的 Quartus 警告。
答案:
module top_module (
input d,
input ena,
output q);
always@(*)begin
if(ena)
q = d;
else
q = q;
end
endmodule
8 DFF | D 触发器
题目:
实现以下电路:
答案:
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output q);
always@(posedge clk or posedge ar)begin
if (ar)
q = 1'b0;
else
q = d;
end
endmodule
9 DFF| D 触发器
题目:
实现以下电路:
答案:
module top_module (
input clk,
input d,
input r, // synchronous reset
output q);
always@(posedge clk)begin
if (r)
q = 1'b0;
else
q = d;
end
endmodule
10 DFF+gate | D 触发器 + 门电路
题目:
实现以下电路:
答案:
module top_module (
input clk,
input in,
output out);
always@(posedge clk)begin
out = out ^ in;
end
endmodule
11 Mux and DFF | 多路复用器和 D 触发器
题目:
考虑下面的顺序电路:
如果您想要为该电路实现分层 Verilog 代码,可以使用包含触发器和多路复用器的子模块的三个实例。为该子模块编写一个名为 top_module 的 Verilog 模块(包含一个触发器和多路复用器)。
注意:本题要求是写一个“包含一个触发器和多路复用器”的子模块
答案:
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
reg mux_2to1;
always@(*)begin
if (L)begin
mux_2to1 = r_in;
end
else begin
mux_2to1 = q_in;
end
end
always@(posedge clk)begin
Q <= mux_2to1;
end
endmodule
知识点:
组合逻辑always块中被赋值的信号需要被声明为"reg"类型。
12 Mux and DFF | 多路复用器和 D 触发器
题目:
考虑如下所示的 n 位移位寄存器电路:
为该电路的一个阶段编写一个名为 top_module 的 Verilog 模块,包括触发器和多路复用器。
答案:
module top_module (
input clk,
input w, R, E, L,
output Q
);
reg mux1;
always@(*)begin
if (E) begin
mux1 = w;
end
else begin
mux1 = Q;
end
end
reg mux2;
always@(*)begin
if (L) begin
mux2 = R;
end
else begin
mux2 = mux1;
end
end
always@(posedge clk)begin
Q <= mux2;
end
endmodule
13 DFFs and gates | D 触发器与门电路的组合
题目:
给定如图所示的有限状态机电路,假设 D 触发器在机器启动之前最初重置为零。
构建此电路。
答案:
module top_module (
input clk,
input x,
output z
);
wire out_xor,out_and,out_or;
reg q1,q2,q3;
assign out_xor = x ^ q1;
assign out_and = x & ~q2;
assign out_or = x | ~q3;
always@(posedge clk)begin
q1 <= out_xor;
q2 <= out_and;
q3 <= out_or;
end
always@(*)begin
z = ~(q1 | q2 | q3);
end
endmodule
14 Create circuit from truth table | 根据真值表设计电路
题目:
JK 触发器具有以下真值表。仅使用 D 型触发器和门电路来实现 JK 触发器。注意:Qold 是正时钟沿之前 D 触发器的输出。
答案:
方法一:
1.真值表:
J | K | Qn | Qn+1 |
0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 0 | 1 |
1 | 0 | 1 | 1 |
1 | 1 | 0 | 1 |
1 | 1 | 1 | 0 |
2.卡诺图化简:
3.逻辑表达式:
Qn+1 = J~Qn | ~KQn;
4.代码:
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk)begin
Q <= (j & ~Q) | (~k & Q);
end
endmodule
方法二:
1.画电路图:
2.代码:
module top_module (
input clk,
input j,
input k,
output Q);
reg mux_4to1;
always@(*)begin
case({j,k})
2'b00 : mux_4to1 = Q;
2'b01 : mux_4to1 = 1'b0;
2'b10 : mux_4to1 = 1'b1;
2'b11 : mux_4to1 = ~Q;
default mux_4to1 = mux_4to1;
endcase
end
always@(posedge clk)begin
Q <= mux_4to1;
end
endmodule
15 Detect an edge | 正边沿检测
题目:
对于 8 位向量中的每个位,检测输入信号何时在一个时钟周期内从 0 变为下一个时钟周期内的 1(类似于正边沿检测)。输出位应在 0 到 1 转换发生后的周期内设置。
以下是一些示例。为清楚起见,in[1] 和 pedge[1] 分别显示。
答案:
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] in_d;
always@(posedge clk)begin
in_d <= in;// 记住上一次循环的状态
end
always@(posedge clk)begin
pedge <= in & ~in_d;// 如果输入为 0 而现在为 1,则出现正边沿。
end
endmodule
16 Detect both edges | 双边沿检测
题目:
对于 8 位向量中的每个位,检测输入信号从一个时钟周期到下一个时钟周期的变化(检测任何边缘)。输出位应在 0 到 1 转换发生后的周期内设置。
以下是一些示例。为清楚起见,in[1] 和 anyedge[1] 分别显示
答案:
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0] in_d;
always@(posedge clk)begin
in_d <= in;
end
always@(posedge clk)begin
anyedge <= in ^ in_d;
end
endmodule
17 Edge capture register | 边沿捕获寄存器
题目:
对于 32 位向量中的每个位,当输入信号在一个时钟周期内从 1 变为下一个时钟周期内的 0 时捕获。“捕获”意味着输出将保持为 1,直到寄存器被复位(同步复位)。
每个输出位的行为类似于 SR 触发器:在发生 1 到 0 的转换后的周期内,应将输出位设置为(1)。当复位为高电平时,应在正时钟沿将输出位复位为(0)。如果上述两个事件同时发生,则复位优先。在下面的示例波形的最后 4 个周期中,“复位”事件比“设置”事件早一个周期发生,因此这里没有冲突。
在下面的示例波形中,为了清晰起见,再次分别显示了复位、in[1] 和 out[1]。
答案:
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_d;
always@(posedge clk)begin
in_d <= in;
end
always@(posedge clk)begin
if (reset)begin
out <= 32'd0;
end
else begin
out <= ~in & in_d | out;
end
end
endmodule
18 Dual-edge triggered fip-fop | 双沿触发的触发器
题目:
您熟悉在时钟正沿或负沿触发的触发器。双边沿触发器在时钟的两个边沿触发。但是,FPGA 没有双边沿触发器,并且始终 @(posedge clk 或 negedge clk) 不被接受为合法敏感度列表。
构建一个功能上表现得像双边沿触发器的电路:
(注意:它不一定完全等效:触发器的输出没有故障,但模拟此行为的较大组合电路可能会有故障。但我们将在此处忽略此细节。)
答案:
方法一:
module top_module(
input clk,
input d,
output q);
reg p, n;
// clk的上升沿
always @(posedge clk)
p <= d ^ n;
// clk的下降沿
always @(negedge clk)
n <= d ^ p;
//在上升沿时候,p=d^n, 则q=d^n^n=d;
//在下降沿时候,n=d^p, 则q=p^d^p=d;
//加载一个新值时会取消旧值。
assign q = p ^ n;
endmodule
方法二:
module top_module (
input clk,
input d,
output q
);
reg q1, q0;
always @(posedge clk)
q1 <= d;
always @(negedge clk)
q0 <= d;
assign q = clk ? q1 : q0;
endmodule
- END -
公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转: