赞
踩
全部答案汇总:刷完这套题,我才发现Verilog原来如此简单----HDLBits答案汇总
今天更新Circuits章节中Sequential Logic的1个小节:Latches and Flip-Flops。
题目:创建一个D触发器。
个人思路:
这个题目是时序电路最基本的模块之一,在always块中使用非阻塞赋值即可。
- module top_module (
- input clk, // Clocks are used in sequential circuits
- input d,
- output reg q );//
-
- always @(posedge clk)begin
- q <= d;
- end
-
- endmodule
题目:创建8个D触发器,每个都由时钟的上升沿触发。
个人思路:
方法同上题目,不过输入输出位宽变成了8bit,编译器会综合成8个D触发器。
- module top_module (
- input clk,
- input [7:0] d,
- output [7:0] q
- );
-
- always @(posedge clk)begin
- q <= d;
- end
-
- endmodule
题目:创建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)
- q <= 0;
- else
- q <= d;
- end
-
- endmodule
题目:创建8个D触发器与主动同步复位(高电平有效)。触发器必须被重置为0x34,而不是0。所有D触发器应由clk的下降沿触发。
个人思路:
在上题的基础上把复位值改成了0x34,触发方式变成了下降沿触发。
- module top_module (
- input clk,
- input reset,
- input [7:0] d,
- output [7:0] q
- );
-
- always @(negedge clk)begin
- if(reset)
- q <= 8'h34;
- else
- q <= d;
- end
- endmodule
题目:创建8个D触发器与主动异步复位(高电平有效),所有D触发器应由clk的上升沿触发。
个人思路:
在上上题的基础上把同步复位改成了异步复位,方法在上上题已经说了。
- module top_module (
- input clk,
- input areset, // active high asynchronous reset
- input [7:0] d,
- output [7:0] q
- );
- always @(posedge clk or posedge areset)begin
- if(areset)
- q <= 0;
- else
- q <= d;
- end
-
- endmodule
题目:创建一个16D触发器,有时我们仅需要修改部分触发器中的值。字节使能信号控制当前时钟周期中16个寄存器中哪个字节需被修改。byteena[1]控制高字节d[15:8],而byteena[0]控制低字节d[7:0]。resetn是一个同步的,低电平有效的复位信号。所有的D触发器由时钟的上升沿触发。
个人思路:
byteena[1]控制高8字节,byteena[0]控制8低字节.可以使用case语句根据使能信号byteena的值来输出不同的值,实现一个4选一选择器。
- 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
- case(byteena)
- 2'b00: q <= q;
- 2'b01: q <= {q[15:8],d[7:0]};
- 2'b10: q <= {d[15:8],q[7:0]};
- 2'b11: q <= d;
- default:;
- endcase
- end
- endmodule
题目:实现下面的电路(锁存器)。
个人思路:
使用组合逻辑但不补全else就会生成一个锁存器,锁存器与时钟无关,无法进行时序分析与约束,对时序电路危害很大,平常建议不要轻易使用锁存器。
- module top_module (
- input d,
- input ena,
- output q);
-
- always@(*)begin
- if(ena)
- q = d;
- end
- endmodule
题目:实现下面的电路。
个人思路:
这是一个异步复位(高电平有效)的D触发器。
- module top_module (
- input clk,
- input d,
- input ar, // asynchronous reset
- output q);
-
- always @(posedge clk or posedge ar)begin
- if(ar)
- q <= 0;
- else
- q <= d;
- end
- endmodule
题目:实现下面的电路。
个人思路:
这是一个同步复位(高电平有效)的D触发器。
- 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
题目:实现下面的电路。
个人思路:
D触发器的输出与输入进行了一个异或操作后作为输入。
- module top_module (
- input clk,
- input in,
- output reg out);
-
- always @(posedge clk)begin
- out <= out ^ in;
- end
-
- endmodule
题目:
考虑下图的电路:
假设要为这个电路实现分层的Verilog代码,使用一个子模块的三个实例,该子模块中有一个触发器和多路选择器。为这个子模块编写一个名为top_module的Verilog模块(包含一个触发器和多路选择器)。
个人思路:
可以看到,这个子模块就是一个D触发器,它的输入为L控制的输入为r_in和q_in的二选一输出。
- module top_module (
- input clk,
- input L,
- input r_in,
- input q_in,
- output reg Q);
-
- always @(posedge clk) begin
- Q <= L?r_in:q_in;
- end
-
- endmodule
题目:
考虑下图的n-bit移位寄存器。
为该电路的一个阶段编写一个Verilog模块顶层模块,包括触发器和多路选择器。
个人思路:
可以看到,这个子模块在上一题的基础上多了一级二选一选择器。
- module top_module (
- input clk,
- input w, R, E, L,
- output Q
- );
- always@(posedge clk)begin
- Q <= L ? R : (E ? w : Q);
- end
-
- endmodule
题目:给定如图所示的有限状态机电路,假设D触发器在机器开始之前被初始重置为零。
个人思路:
D触发器的输出与3个输入进行了异或、与、或操作,输出再做一个或非操作。
- module top_module (
- input clk,
- input x,
- output z
- );
- reg [2:0] q;
- always@(posedge clk)begin
- q[2] <= q[2] ^ x;
- q[1] <= ~q[1] & x;
- q[0] <= ~q[0] | x;
- end
-
- assign z = ~(|q);
-
- endmodule
题目:JK触发器有下面的真值表。只使用D触发器和逻辑门实现JK触发器。注:Qold是时钟上升沿前的D触发器的输出。
个人思路:
可以使用case语句,根据J、K的值来进行一个4选1的输出。
- module top_module (
- input clk,
- input j,
- input k,
- output Q);
-
- always@(posedge clk)begin
- case({j,k})
- 2'b00: Q <= Q;
- 2'b01: Q <= 1'b0;
- 2'b10: Q <= 1'b1;
- 2'b11: Q <= ~Q;
- default:;
- endcase
- end
-
- endmodule
题目:对于8位向量中的每一位,检测输入信号何时从一个时钟周期的0变化到下一个时钟周期的1(上升沿检测)。输出位应该在发生0到1转换后的周期,如下示意图所示:
个人思路:
这里是要对输入信号做一个上升沿的检测。
边沿检测是FPGA的一个基本功,在设计中基本都会遇到,请一定要掌握。
可以参考我这篇博文:边沿检测电路(上升沿、下降沿)
- module top_module (
- input clk,
- input [7:0] in,
- output [7:0] pedge
- );
- reg [7:0] in_r;
- always@(posedge clk)begin
- in_r <= in;
- pedge <= in & ~in_r;
- end
-
- endmodule
题目:于8位向量中的每一位,检测输入信号何时从一个时钟周期变化到下一个时钟周期(检测脉冲边沿)。输出位应该在发生转换后的周期,如下示意图所示:
个人思路:
这里是要对输入信号做一个上升沿及下降沿的检测,可以参考上一题。
题目:
对于32位向量中的每一位,当输入信号从一个时钟周期的1变化到下一个时钟周期的0时捕获(捕捉下降沿),“捕获”意味着输出将保持1直到被reset(同步重置)。
每个输出位的行为就像一个SR触发器:输出位应该在发生1到0转换后的周期被设置(为1)。当复位为高时,输出位应该在正时钟边缘复位(为0)。如果上述两个事件同时发生,则reset具有优先级。
在下面示例波形的最后4个周期中,“reset”事件比“set”事件早一个周期发生,因此这里不存在冲突。
个人思路:
这题还是要做一个下降沿检测,不过输出不再是脉冲信号,而是保持高电平不变。
- module top_module (
- input clk,
- input reset,
- input [31:0] in,
- output [31:0] out
- );
-
- reg [31:0] temp_in;
-
- always @(posedge clk) begin
- temp_in <= in;
- end
-
- always @(posedge clk) begin
- if(reset)begin
- out<=32'b0;
- end
- else begin
- out<=temp_in & ~in | out;
- end
- end
-
- endmodule
题目:你很熟悉在时钟的正边缘或负边缘触发的触发器。双边缘触发触发器在时钟的两端触发。然而fpga并没有双边触发触发器,always @(posedge clk或negedge clk)不是能被综合的语句。构建一个功能类似于双边缘触发触发器的电路:
个人思路:
首先 always @(posedge clk或negedge clk)这种语句肯定是不能综合的;其次也不能用两个always块分别在时钟上升沿、时钟下降沿进行操作,这涉及到多驱动问题。
比较合适的方法是设计两个中间变量,分别在时钟上升沿、时钟下降沿进行赋值,最后使用组合逻辑输出。
- module top_module (
- input clk,
- input d,
- output q
- );
- reg p,n;
-
- always@(posedge clk)begin
- p <= d ^ n; //q = p ^ n = d ^ n ^ n = d
- end
- always@(negedge clk)begin
- n <= d ^ p; //q = p ^ n = p ^ d ^ p = d
- end
- assign q = p ^ n;
-
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。