3.2.1 Sequential Logic - Latches and Flip-Flops

Kiwoong Nam·2025년 6월 6일

HDLBits

목록 보기
8/11

Synchronous vs Asynchronous reset

  • Syncrhonous
always @(posedge clk) q <= reset ? 8'b0 : d;
  • Asynchronous
always @(posedge clk or posedge areset) q <= areset ? 8'b0 : d;

DFFs and gates

Exams/ece241 2014 q4

module top_module (
    input clk,
    input x,
    output z
); 
    wire q1, q2, q2b, q3, q3b;
    mydff d1(clk, x^q1, q1);
    mydff d2(clk, x&q2b, q2, q2b);
    mydff d3(clk, x|q3b, q3, q3b);
    nor (z, q1, q2, q3);

endmodule

// 통과한 모듈
module mydff(input clk, d, output q, qb);
    assign qb = ~q;
    always @(posedge clk) q<=d;
endmodule

// 실패한 모듈
module mydff(input clk, d, output reg q, output reg qb);
    always @(posedge clk) begin q<=d; qb<=~d; end
endmodule

두 번째 구현의 경우 첫 클럭 이전 reset state에서 q와 qb가 complementary가 되지 않아서 오답이라고 한다...장난까나

Detect an edge

Edgedetect

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);
    reg [7:0] previn;
    integer i;
    
    always @(posedge clk) begin
        for (i = 0; i < 8; i += 1) pedge[i] <= (previn[i] == 0 && in[i] == 1) ? 1 : 0;
        previn <= in;
    end

endmodule

뭔가 되게 고생했었는데 생각보다 간단한 문제였다
문제 조건에 '한 사이클에 0에서 1로 변하는' 이라는 조건이 있는데 사이클 안에서 올라왔다 내려오면 어쩌지??같은 고민을 했으니 어렵지
매 사이클마다 이전 상태를 기록해 두고, 이전 상태가 0이고 현재 상태가 1인 경우에만 pedge를 1로 출력하면 해결할 수 있다.

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

근데 솔루션은 더 간단하게 풀었다
논리식으로 하니까 for문이 필요가 없군

Detect both edges

Edgedetect2

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
    reg [7:0] previn;
    always @(posedge clk) begin
        previn <= in;
        anyedge <= previn ^ in;
    end

endmodule

그래서 이번엔 나도 스마트하게 풀었다

Edge capture register

Edgecapture

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    reg [31:0] previn;
    always @(posedge clk) begin
        previn <= in;
        if (reset) out <= 32'b0;
        else out <= out | (previn & ~in);
    end    

endmodule

앞의 문제들과 달리 리셋 이전까지 출력이 1에서 안 내려간다. 기존 out과의 or 연산으로 해결했다.

Dual-edge triggered flip-flop

Dualedge

module top_module (
    input clk,
    input d,
    output reg q
);
    // why does not works with prevclk??
    reg qp, qn;
    always @(posedge clk) qp <= d;
    always @(negedge clk) qn <= d;
    always @(clk) q <= clk ? qp : qn;

endmodule

하나의 레지스터 q에 두 개의 always 구문에서 접근할 수 없고, 하나의 신호 clk를 두 엣지 모두 감지하는 것 또한 불가능하므로 이런 구조를 사용해야 한다.
솔루션의 경우 좀 다른 방식을 취했다.

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 d^p. Thus q = (p^n) = (p^d^p) = 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;
    
endmodule

0개의 댓글