HDLBits中文版,标准参考答案 | 3.2.1 Latches and Flip-Flops | 锁存器和触发器

关注 望森FPGA  查看更多FPGA资讯

这是望森的第 12 期分享

作者 | 望森
来源 | 望森FPGA

目录

1 D fip-flop | D触发器

2 D fip-flops | D 触发器

3 DFF with reset | 带复位的 D 触发器

4 DFF with reset value | 带复位值的 D 触发器

5 DFF with asynchronous reset | 具有异步复位的 D 触发器

6 DFF with byte enable | 带字节使能的 D 触发器

7 D Latch | D 锁存器

8 DFF | D 触发器

9 DFF| D 触发器

10 DFF+gate | D 触发器 + 门电路

11 Mux and DFF | 多路复用器和 D 触发器

12 Mux and DFF | 多路复用器和 D 触发器

13 DFFs and gates | D 触发器与门电路的组合

14 Create circuit from truth table | 根据真值表设计电路

15 Detect an edge | 正边沿检测

16 Detect both edges | 双边沿检测

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.真值表:

JKQnQn+1
0000
0011
0100
0110
1001
1011
1101
1110

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资讯~

相关推荐文章,点击跳转:

望森FPGA的HDLBits专栏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望森FPGA

谢谢你的支持,这对我很重要~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值