当前位置:   article > 正文

刷完这套题,我才发现Verilog原来如此简单----HDLBits答案系列---- Latches and Flip-Flops_verilog 多驱动

verilog 多驱动

写在前面

全部答案汇总:刷完这套题,我才发现Verilog原来如此简单----HDLBits答案汇总

今天更新Circuits章节中Sequential Logic的1个小节:Latches and Flip-Flops


D flip-flop

        题目:创建一个D触发器。

        个人思路:

                这个题目是时序电路最基本的模块之一,在always块中使用非阻塞赋值即可。

  1. module top_module (
  2. input clk, // Clocks are used in sequential circuits
  3. input d,
  4. output reg q );//
  5. always @(posedge clk)begin
  6. q <= d;
  7. end
  8. endmodule

D flip-flops

        题目:创建8个D触发器,每个都由时钟的上升沿触发。

        个人思路:

                方法同上题目,不过输入输出位宽变成了8bit,编译器会综合成8个D触发器。

  1. module top_module (
  2. input clk,
  3. input [7:0] d,
  4. output [7:0] q
  5. );
  6. always @(posedge clk)begin
  7. q <= d;
  8. end
  9. endmodule

DFF with reset

        题目:创建8个d触发器与主动同步复位(高电平有效);所有D触发器由clk的上升沿触发。

        个人思路:

                在上题的基础上增加了同步复位。同步复位就是必须在时钟边沿才能被触发复位,而异步复位是一旦复位有效即复位,与时钟无关。

                关于同步复位、异步复位的相关内容可以参考我这篇博文:同步复位、异步复位、异步复位同步释放

  1. module top_module (
  2. input clk,
  3. input reset, // Synchronous reset
  4. input [7:0] d,
  5. output [7:0] q
  6. );
  7. always @(posedge clk)begin
  8. if(reset)
  9. q <= 0;
  10. else
  11. q <= d;
  12. end
  13. endmodule

DFF with reset value

         题目:创建8个D触发器与主动同步复位(高电平有效)。触发器必须被重置为0x34,而不是0。所有D触发器应由clk的下降沿触发。

        个人思路:

                在上题的基础上把复位值改成了0x34,触发方式变成了下降沿触发。

  1. module top_module (
  2. input clk,
  3. input reset,
  4. input [7:0] d,
  5. output [7:0] q
  6. );
  7. always @(negedge clk)begin
  8. if(reset)
  9. q <= 8'h34;
  10. else
  11. q <= d;
  12. end
  13. endmodule

DFF with asynchronous reset 

         题目:创建8个D触发器与主动异步复位(高电平有效),所有D触发器应由clk的上升沿触发。

        个人思路:

                在上上题的基础上把同步复位改成了异步复位,方法在上上题已经说了。

  1. module top_module (
  2. input clk,
  3. input areset, // active high asynchronous reset
  4. input [7:0] d,
  5. output [7:0] q
  6. );
  7. always @(posedge clk or posedge areset)begin
  8. if(areset)
  9. q <= 0;
  10. else
  11. q <= d;
  12. end
  13. endmodule

DFF with byte enable

         题目:创建一个16D触发器,有时我们仅需要修改部分触发器中的值。字节使能信号控制当前时钟周期中16个寄存器中哪个字节需被修改。byteena[1]控制高字节d[15:8],而byteena[0]控制低字节d[7:0]。resetn是一个同步的,低电平有效的复位信号。所有的D触发器由时钟的上升沿触发。

        个人思路:

                byteena[1]控制高8字节,byteena[0]控制8低字节.可以使用case语句根据使能信号byteena的值来输出不同的值,实现一个4选一选择器。

  1. module top_module (
  2. input clk,
  3. input resetn,
  4. input [1:0] byteena,
  5. input [15:0] d,
  6. output [15:0] q
  7. );
  8. always@(posedge clk )begin
  9. if(!resetn)
  10. q <= 16'd0;
  11. else
  12. case(byteena)
  13. 2'b00: q <= q;
  14. 2'b01: q <= {q[15:8],d[7:0]};
  15. 2'b10: q <= {d[15:8],q[7:0]};
  16. 2'b11: q <= d;
  17. default:;
  18. endcase
  19. end
  20. endmodule

D Latch

        题目:实现下面的电路(锁存器)。

        

         个人思路:

                使用组合逻辑但不补全else就会生成一个锁存器,锁存器与时钟无关,无法进行时序分析与约束,对时序电路危害很大,平常建议不要轻易使用锁存器。

  1. module top_module (
  2. input d,
  3. input ena,
  4. output q);
  5. always@(*)begin
  6. if(ena)
  7. q = d;
  8. end
  9. endmodule

DFF

        题目:实现下面的电路。

        

          个人思路:

                这是一个异步复位(高电平有效)的D触发器。

  1. module top_module (
  2. input clk,
  3. input d,
  4. input ar, // asynchronous reset
  5. output q);
  6. always @(posedge clk or posedge ar)begin
  7. if(ar)
  8. q <= 0;
  9. else
  10. q <= d;
  11. end
  12. endmodule

DFF

        题目:实现下面的电路。   ​​​​​

        

 个人思路:

                这是一个同步复位(高电平有效)的D触发器。

  1. module top_module (
  2. input clk,
  3. input d,
  4. input r, // synchronous reset
  5. output q);
  6. always @(posedge clk)begin
  7. if(r)
  8. q <= 0;
  9. else
  10. q <= d;
  11. end
  12. endmodule

DFF+gate

        题目:实现下面的电路。   ​​​​​

        

                

        个人思路:

                D触发器的输出与输入进行了一个异或操作后作为输入。

  1. module top_module (
  2. input clk,
  3. input in,
  4. output reg out);
  5. always @(posedge clk)begin
  6. out <= out ^ in;
  7. end
  8. endmodule

MUX+DFF

        题目:

                考虑下图的电路:

                假设要为这个电路实现分层的Verilog代码,使用一个子模块的三个实例,该子模块中有一个触发器和多路选择器。为这个子模块编写一个名为top_module的Verilog模块(包含一个触发器和多路选择器)。

        个人思路:

                可以看到,这个子模块就是一个D触发器,它的输入为L控制的输入为r_in和q_in的二选一输出。

  1. module top_module (
  2. input clk,
  3. input L,
  4. input r_in,
  5. input q_in,
  6. output reg Q);
  7. always @(posedge clk) begin
  8. Q <= L?r_in:q_in;
  9. end
  10. endmodule

 MUX+DFF

        题目:

                考虑下图的n-bit移位寄存器。

        

             为该电路的一个阶段编写一个Verilog模块顶层模块,包括触发器和多路选择器。    

        个人思路:

                可以看到,这个子模块在上一题的基础上多了一级二选一选择器。

  1. module top_module (
  2. input clk,
  3. input w, R, E, L,
  4. output Q
  5. );
  6. always@(posedge clk)begin
  7. Q <= L ? R : (E ? w : Q);
  8. end
  9. endmodule

DFFS and gates

        题目:给定如图所示的有限状态机电路,假设D触发器在机器开始之前被初始重置为零。

        个人思路:

                D触发器的输出与3个输入进行了异或、与、或操作,输出再做一个或非操作。

  1. module top_module (
  2. input clk,
  3. input x,
  4. output z
  5. );
  6. reg [2:0] q;
  7. always@(posedge clk)begin
  8. q[2] <= q[2] ^ x;
  9. q[1] <= ~q[1] & x;
  10. q[0] <= ~q[0] | x;
  11. end
  12. assign z = ~(|q);
  13. endmodule

Create circuit from truth table

         题目:JK触发器有下面的真值表。只使用D触发器和逻辑门实现JK触发器。注:Qold是时钟上升沿前的D触发器的输出。

        

        个人思路:

                可以使用case语句,根据J、K的值来进行一个4选1的输出。

  1. module top_module (
  2. input clk,
  3. input j,
  4. input k,
  5. output Q);
  6. always@(posedge clk)begin
  7. case({j,k})
  8. 2'b00: Q <= Q;
  9. 2'b01: Q <= 1'b0;
  10. 2'b10: Q <= 1'b1;
  11. 2'b11: Q <= ~Q;
  12. default:;
  13. endcase
  14. end
  15. endmodule

Detect an edge

         题目:对于8位向量中的每一位,检测输入信号何时从一个时钟周期的0变化到下一个时钟周期的1(上升沿检测)。输出位应该在发生0到1转换后的周期,如下示意图所示:

        

        个人思路:

                这里是要对输入信号做一个上升沿的检测。

                边沿检测是FPGA的一个基本功,在设计中基本都会遇到,请一定要掌握。

                可以参考我这篇博文:边沿检测电路(上升沿、下降沿)

  1. module top_module (
  2. input clk,
  3. input [7:0] in,
  4. output [7:0] pedge
  5. );
  6. reg [7:0] in_r;
  7. always@(posedge clk)begin
  8. in_r <= in;
  9. pedge <= in & ~in_r;
  10. end
  11. endmodule

Detect both edge

         题目:于8位向量中的每一位,检测输入信号何时从一个时钟周期变化到下一个时钟周期(检测脉冲边沿)。输出位应该在发生转换后的周期,如下示意图所示:

  

        个人思路:

                这里是要对输入信号做一个上升沿及下降沿的检测,可以参考上一题。

Edge capture register

         题目:

                对于32位向量中的每一位,当输入信号从一个时钟周期的1变化到下一个时钟周期的0时捕获(捕捉下降沿),“捕获”意味着输出将保持1直到被reset(同步重置)。

                每个输出位的行为就像一个SR触发器:输出位应该在发生1到0转换后的周期被设置(为1)。当复位为高时,输出位应该在正时钟边缘复位(为0)。如果上述两个事件同时发生,则reset具有优先级。

                在下面示例波形的最后4个周期中,“reset”事件比“set”事件早一个周期发生,因此这里不存在冲突。

        个人思路:

                这题还是要做一个下降沿检测,不过输出不再是脉冲信号,而是保持高电平不变。

  1. module top_module (
  2. input clk,
  3. input reset,
  4. input [31:0] in,
  5. output [31:0] out
  6. );
  7. reg [31:0] temp_in;
  8. always @(posedge clk) begin
  9. temp_in <= in;
  10. end
  11. always @(posedge clk) begin
  12. if(reset)begin
  13. out<=32'b0;
  14. end
  15. else begin
  16. out<=temp_in & ~in | out;
  17. end
  18. end
  19. endmodule

Dual-edge triggered flip-flop

        题目:你很熟悉在时钟的正边缘或负边缘触发的触发器。双边缘触发触发器在时钟的两端触发。然而fpga并没有双边触发触发器,always @(posedge clk或negedge clk)不是能被综合的语句。构建一个功能类似于双边缘触发触发器的电路:

        个人思路:

                首先 always @(posedge clk或negedge clk)这种语句肯定是不能综合的;其次也不能用两个always块分别在时钟上升沿、时钟下降沿进行操作,这涉及到多驱动问题。

                比较合适的方法是设计两个中间变量,分别在时钟上升沿、时钟下降沿进行赋值,最后使用组合逻辑输出。

  1. module top_module (
  2. input clk,
  3. input d,
  4. output q
  5. );
  6. reg p,n;
  7. always@(posedge clk)begin
  8. p <= d ^ n; //q = p ^ n = d ^ n ^ n = d
  9. end
  10. always@(negedge clk)begin
  11. n <= d ^ p; //q = p ^ n = p ^ d ^ p = d
  12. end
  13. assign q = p ^ n;
  14. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/648825
推荐阅读
相关标签
  

闽ICP备14008679号