HDLBits 刷题(Latches and Flip-Flops)

image.png

D触发器是一种存储位并定期更新的电路,在时钟信号的(通常)上升沿。创建一个D触发器

module top_module (
    input clk,    // Clocks are used in sequential circuits
    input d,
    output reg q );//

    // Use a clocked always block
    always@(posedge clk)
        q <= d;
    //   copy d to q at every positive edge of clk
    //   Clocked always blocks should use non-blocking assignments
/*时序逻辑电路中通常采用非阻塞型赋值形式*/ 
endmodule

  • Create 8 D flip-flops. All DFFs should be triggered by the positive edge of clk. 创建 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

  • Create 8 D flip-flops with active high synchronous reset. All DFFs should be triggered by the positive edge of clk
    创建 8 个具有高电平有效同步复位的 D 触发器。所有触发器都应由clk的上升沿触发。
module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output [7:0] q
);
    always @(posedge clk)
        if(reset)
            q <= 8'h0;
        else
            q <= d;

endmodule
  • 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.
    创建 8 个具有高电平有效同步复位的 D 触发器。触发器必须重置为 0x34 而不是零。所有触发器都应由clk的下降沿触发。
module top_module (
    input clk,
    input reset,
    input [7:0] d,
    output [7:0] q
);
    always@(negedge clk)
        if(reset)
            q <= 8'h0x34;
        else
            q <= d; 

endmodule
  • Create 8 D flip-flops with active high asynchronous reset. All DFFs should be triggered by the positive edge of clk.
    创建 8 个具有高电平有效异步复位的 D 触发器。所有 触发器 都应由clk的上升沿触发。
module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output [7:0] q
);
    always@(posedge clk, posedge areset)
        if(areset)
            q <= 8'h0;
        else
            q <= d;

endmodule
=----------------------官网答案-----------------------------------
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


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.
创建 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 <= 16'h0;
        else begin
            case(byteena) 
            2'd0 : q <= q;   // 这里注意是将q原值赋给原值
            2'd1 : q[7:0] <= d[7:0];
            2'd2 : q[15:8] <= d[15:8];
            2'd3 : q <= d;    
            endcase
        end
    end
             

endmodule
锁存器.png
module top_module (
    input d, 
    input ena,
    output q);

    always @(*)
        if (ena)
            q <= d;

endmodule
image.png

这里ar的复位信号是高有效形式表达的;因为要求异步复位,所以将其写入敏感事件列表

module top_module (
    input clk,
    input d, 
    input ar,   // asynchronous reset
    output q);
    
    always@(posedge clk,posedge ar)
        if(ar)
            q <= 0;
        else
            q <= d;
        
endmodule
image.png

本题要求同步复位,即复位信号不写入敏感时间列表

module top_module (
    input clk,
    input d, 
    input r,   // synchronous reset
    output q);
    
    always@(posedge clk)
        if(r)
            q <= 0;
        else
            q <= d;
endmodule
image.png

实现上述电路,代码如下:

module top_module (
    input clk,
    input in, 
    output out);
    
    always@(posedge clk)
        out <= out ^in;

endmodule

image.png
  • 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.
    假设您要为此电路实现分层 Verilog 代码,使用其中具有触发器和多路复用器的子模块的三个实例化。为此子模块编写一个名为top_module的 Verilog 模块(包含一个触发器和多路复用器)。
    本题要求给子模块编写程序
module top_module (
    input clk,
    input L,
    input r_in,
    input q_in,
    output reg Q);
    
    reg sel1;
    assign sel1 = (L==1'b1) ? r_in : q_in;
    
    always@(posedge clk)
        Q <= sel1;
               
endmodule
image.png
module top_module (
    input clk,
    input w, R, E, L,
    output Q
);  
    reg sel1,sel2;
    assign sel1 = (E==0)? Q: w;
    assign sel2 = (L==0)? sel1 : R;
    
    always@(posedge clk)
        Q <= sel2;
    
endmodule

  • Given the finite state machine circuit as shown, assume that the D flip-flops are initially reset to zero before the machine begins.Build this circuit.


    image.png

    首先需要构造一个触发器模块dff1

module top_module (
    input clk,
    input x,
    output z
); 
    reg q0;
    reg q1;
    reg q2;
 
    
    dff1 UO (.clk(clk),.d(q0 ^ x),.q(q0));
    dff1 U1 (.clk(clk),.d(~q1 & x),.q(q1));
    dff1 U2 (.clk(clk),.d(~q2 | x),.q(q2));
            
    assign  z = ~(q0|q1|q2);
    
endmodule

module dff1(
    input clk,
    input d,
    output q
 );
    always @(posedge clk) begin
        q <= d;
    end
    
endmodule
  • 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.
    image.png

    本题考察的就是JK触发器的代码写法;所以要对JK触发器的特征方程要牢牢掌握:

module top_module (
    input clk,
    input j,
    input k,
    output Q); 
    
    always@(posedge clk) begin
        
        Q <= j&(~Q)|(~k&Q);
    end
endmodule
  • 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 位向量中的每一位,检测输入信号何时从一个时钟周期的 0 变为下一个时钟周期的 1(类似于上升沿检测)。输出位应在发生 0 到 1 转换后的周期设置。
    这里有些例子。为清楚起见,in[1] 和 pedge[1] 分别显示


    image.png

    老实说,这一题我实在是没看懂这是啥意思:
    参考网友们的分析:
    题目分析:这里是想要获取输入信号的上升沿,采用的方式是对输入信号进行打一拍的操作,然后将输入信号与打拍后的信号进行与非就抓取到了输入信号的上升沿。


    image.png

打拍后的信号存放到in_reg中如图所示,然后进行与非的操作,“与非”是“有0出1”
当检测到输入信号有上升沿时即对应输入信号的状态为“1”
而对于打拍的输入信号此时对应的状态是“0”
所以它俩一与非就表示了输入信号有上升沿

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);
    reg [7:0]in_last;
    always@(posedge clk)begin
        in_last <= in;
        pedge <= in&(~in_last);
    end
     
endmodule
--------------------------------------------官网解答--------------------------------------
module top_module(
    input clk,
    input [7:0] in,
    output reg [7:0] pedge);
    
    reg [7:0] d_last;   
            
    always @(posedge clk) begin
        d_last <= in;           // Remember the state of the previous cycle
        pedge <= in & ~d_last;  // A positive edge occurred if input was 0 and is now 1.
    end
    
endmodule
  • 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.
    Here are some examples. For clarity, in[1] and anyedge[1] are shown separately:


    image.png

    参考网友分析:

  • 题目分析:这里是想要获取输入信号的双升沿,采用的方式是对输入信号进行打一拍的操作,然后将输入信号与打拍后的信号进行异或就抓取到了输入信号的双升沿,如下图所示


    image.png

    异或是二者不同就为1,基于这个特点,对输入信号进行打拍后,对于打拍的信号来说它是输入信号的前一个状态,所以只要当输入信号出现沿的变化,和打拍的信号的状态肯定是不同的,对它们进行异或就表示每当有一个沿出现输出就置1,也就采集到了双边沿。

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
    reg [7:0] in_last;
    
    always@(posedge clk)begin
        in_last <= in;
        anyedge <=  in ^ in_last;
    end
    
endmodule
  • 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.
    In the example waveform below, reset, in[1] and out[1] are shown again separately for clarity.
    对于 32 位向量中的每一位,在输入信号从一个时钟周期的 1 变为下一个时钟周期的 0 时进行捕捉。“捕获”表示输出将保持为 1,直到寄存器复位(同步复位)。
    每个输出位的行为类似于 SR 触发器:输出位应在 1 到 0 转换发生后的周期设置(为 1)。当复位为高电平时,输出位应在正时钟沿复位(为 0)。如果上述两个事件同时发生,则重置优先。在下面示例波形的最后 4 个周期中,“reset”事件比“set”事件早一个周期发生,因此这里不存在冲突。
    在下面的示例波形中,为清楚起见,reset、in[1] 和 out[1] 再次分别显示。


    image.png

    本题也是不会做系列,Troke博主解题思路:
    其实做法和采集输入信号上升沿的操作非常的类似,先要对输入信号进行打拍,接着也是进行与非的操作,与采集上升沿不同的是,采集下降沿时需要将非号加到输入信号上,其实就是与非左右操作数进行一下交换,这样就可以采集到下降沿。
    接着将采集到的下降沿,存到一个临时变量里,然后用for遍历每一位,出现1表示输入信号出现下降沿,此时将数据输出。


    image.png
module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    /*获取信号的下降沿*/
    reg [31:0] in_reg;             
    always @(posedge clk) begin
        in_reg <= in;
    end
    
    /*将结果寄存到临时的寄存器中*/
    reg     [31:0]  temp_reg;
    assign temp_reg = ~in&in_reg;
    
    //对每一位进行一个判断,这里需要用到for循环
    always @(posedge clk) begin
        if(reset == 1'b1) 
            out <= 0;
        else begin
            for(int i=0;i<32;i=i+1) begin
                if(temp_reg[i]==1'b1)   //有哪位出现了下降沿,哪位数据发生改变
                    out[i] <= 1'b1;
                else                   //没出现下降沿的保持不变
                    out[i] <= out[i];
            end
        end
    end
endmodule

————————————————
版权声明:本文为CSDN博主「枫晚渔火」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52159079/article/details/119026507

  • 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.
    Build a circuit that functionally behaves like a dual-edge triggered flip-flop:
    熟悉在时钟上升沿或时钟下降沿触发的触发器。在时钟的两个边沿触发双边触发触发器。但是,FPGA 没有双边触发触发器,并且始终不接受 @(posedge clk 或 negedge clk)作为合法的敏感度列表。
    构建一个功能类似于双边触发触发器的电路:


    image.png

    (注意:不一定完全等效:触发器的输出没有毛刺,但模拟这种行为的更大组合电路可能。但我们将在这里忽略这个细节。)

module top_module (
    input clk,
    input d,
    output q
);
    reg q0;
    reg q1;
    always@(posedge clk)
        q0 <= d ^ q1;
    always@(negedge clk)
        q1 <= d ^ q0;
    
    assign q = q0 ^ q1;
    
endmodule
--------------------------------官网解答----------------------------------------
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;
    
    // Why does this work? 
    // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d.
    // After negedge clk, n changes to p^n. Thus q = (p^n) = (p^p^d) = d.
    // At each (positive or negative) clock edge, p and n FFs alternately
    // load a value that will cancel out the other and cause the new value of d to remain.
    assign q = p ^ n;
    
    
    // Can't synthesize this.
    /*always @(posedge clk, negedge clk) begin
        q <= d;
    end*/
    
    endmodule

这一题其实还挺难这样想到:任何与0异或的值都是其本身
这样的话,将分为两个边沿信号进行分析,分别是时钟信号上升沿和下降沿。

1.如何获取信号的沿
首先对想要采集沿的信号(假设是in)进行打一拍的操作存放到临时寄存器中,假设是in_reg 则:
获取上升沿:in &~ in_reg
获取下降沿:in_reg &~ in
获取双边沿:in ^ in_reg
2.同步复位与异步复位
同步复位:指复位信号在时钟信号触发时,复位才有效
异步复位:指复位信号不管时钟信号是否有触发,只有复位有效,输出立刻变为0
写法:
/同步复位/
always @(posedge clk) begin
if (rst == 1'b? )
...
end
/异步复位/
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0)
...
end
3.构建一个在功能上表现为双边缘触发触发器的电路
// After posedge clk, p changes to d^n. Thus q = (p^n) = (dnn) = d.
// After negedge clk, n changes to p^n. Thus q = (p^n) = (ppn) = d.
// At each (positive or negative) clock edge, p and n FFs alternately
// load a value that will cancel out the other and cause the new value of d to

参考鸣谢:
[FPGA学习: Verilog刷题记录(10)_Troke的博客-CSDN博客_fpga刷题]

你可能感兴趣的:(HDLBits 刷题(Latches and Flip-Flops))