https://hdlbits.01xz.net/wiki/Circuits/Sequential Logic/Latches and Flip and Flop答案

1.DFF

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.dff8

module top_module (
    input clk,
    input [7:0] d,
    output [7:0] q
);
    always@(posedge clk)
        begin
            q <= d;
        end
endmodule

3.DFF8r

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

注意,这是一个同步置位/复位电路。
这里稍微回忆一下相关知识,同步复位要求复位信号必须存续至少一个时钟周期才能被触发。这是他的缺点。
优点在于,同步置位让信号不会和时钟产生相位差,避免了冒险。
3.Dff8p

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

这里有两个问题:1.使用了下降沿触发;2.ox是十六进制(8'h34),hex是十六进制,octal是八进制,不要混淆。
再回忆一下边沿的知识:一般对于时钟而言,只有一个边沿的skew和delay都比较好,所以推荐只使用单边,一定要使用双边建议倍频后使用单边。
4.Dff8ar

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

这是一个异步复位的电路,注意复位也要边沿触发。
5.Dff16e

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 <= 0;
            else 
                begin
                    case(byteena)
                        2'b11: q <= d;
                        2'b10: q[15:8] <= d[15:8];
                        2'b01: q[7:0] <= d[7:0];
                        default:;
                    endcase
                end
        end
endmodule

6.DLatch

module top_module (
    input d, 
    input ena,
    output q);
    
    always@(ena or d)
        begin
            if(ena)
               q <= d; 
        end      
endmodule

本来就是锁存器就忽略latch警告。
7.DFF

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

8.DFF

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

9.DFF+gate

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

10.Mt2015 muxdff
这题只要写子模块,不要像某人那样傻乎乎的去写全部的。

module top_module (
	input clk,
	input L,
	input r_in,
	input q_in,
	output reg Q);
    
    wire d;
    assign d = (L)? r_in : q_in;
    always@(posedge clk)
        begin
            Q <= d;
        end
endmodule

11.Mux and DFF

module top_module (
    input clk,
    input w, R, E, L,
    output Q
);
    wire res1;
    wire d;
    assign res1 = (E)? w : Q;
    assign d = (L)? R : res1;
    always@(posedge clk)
        begin
            Q <= d;
        end
endmodule

12.DFFs and gates

module top_module (
    input clk,
    input x,
    output z
); 
    reg q0;
    reg q1;
    reg q2;
    wire d0;
    wire d1;
    wire d2;
    assign d0 = x ^ q0;
    assign d1 = x & (~q1);
    assign d2 = x | (~q2);
    
    always@(posedge clk)
        begin
            q0 <= d0;
            q1 <= d1;
            q2 <= d2;
        end
    assign z = ~(q0 | q1 | q2);
endmodule

13.JKFF

module top_module (
    input clk,
    input j,
    input k,
    output Q); 

    always@(posedge clk)
        begin
            if(j^k)
                Q <= j;
            else if(j)
                Q <= ~Q;
            else
                Q <= Q;
        end
endmodule

虽然else不写也会默认保持原样,但是最好还是写一下吧。
14.edge detect

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);

    reg[7:0] temp;
    integer i;
    always@(posedge clk)
        begin 
            for(i=0; i<8; i++)
                begin
                    if(temp[i]==0 && in[i]==1)
                        pedge[i] <= 1'b1;
                    else
                        pedge[i] <= 1'b0;
                    temp[i] = in[i];
                end
        end
endmodule

15.detect both edges

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
    reg[7:0] temp;
    integer i;
    always@(posedge clk)
        begin
            for(i=0; i<8; i++)
                begin
                    if(temp[i]^in[i])
                        anyedge[i] = 1'b1;
                    else
                        anyedge[i] = 1'b0;
                    temp[i] = in[i];
                end
        end
endmodule

注意本意是立马检测边沿的变化,但反映在波形图上则滞后了一个clk,实际上发生变化的那个上升沿才刚开始变化,因而处理不出来结果。等到下一个上升沿才处理。
16.edge capture

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    reg[31:0] temp;
    integer i;
    always@(posedge clk)
		begin
            for(i=0; i<32; i++)
                begin
                    if(reset)
                        out[i] <= 1'b0;
                    else if(temp[i]==1 && in[i]==0)
                        out[i] <= 1'b1;                    
                    temp[i] = in[i];
                end            
        end
endmodule

需要注意的是,if...else判断中,reset始终都是最优先的判断,所以应该放在第一个if后。
17.DUal edge

module top_module (
    input clk,
    input d,
    output q
);
    reg temp1;
    reg temp2;
    always@(posedge clk)
        begin
            temp1 <= d;
        end
    
    always@(negedge clk)
        begin
            temp2 <= d;
        end
    assign q = (clk)? temp1:temp2;
endmodule

正常来说不推荐使用双边,同时在一个always块的判断条件中加一个时钟的两个沿也会报错!
而且必须通过一个数据选择器引出来否则必然出现数据竞争冒险!!!
这个题应该是这一篇最难的一个了。同时注意题目最后的说明:在一个触发器中这样用可能还好,但是大规模的电路中这样使用必然会出问题。

posted @ 2021-03-25 20:04  黑衣の甘铃儿  阅读(77)  评论(0)    收藏  举报