Verilog 코딩으로 Flip-Flop 파형 확인하기

dewdew·2023년 7월 5일
0

Verilog

목록 보기
2/4

오늘은 지난 포스팅에 이어 Flip-Flop 에 대한 모듈 정의와 testbench 를 통한 파형 분석까지 학습하도록 하겠다. Flip-Flop 의 종류는 다양하지만, 많이 사용되는 D-FF 과 SR-FF 의 동작을 확인해보자.

- D Flip-Flop

1. module 정의하기

positive edge triggered D Flip-Flop 의 동작을 이행하는 모듈을 생성하는 것이 첫번째 단계이다. 모듈 이름은 D_FF 로 정의하고 if 문을 통해 transparent 한 특성을 가지는 D-FF 의 특성을 구현시켜준다.

module D_FF(q,qbar,clk,rst,d);
	output reg q;
	output qbar;
	input clk, rst;
	input d;

	assign qbar = ~q;

	always @(posedge clk)
	begin
		if (rst)
			q <= 0;
		else
			q <= d;
	end
endmodule

2. testbench 생성하기

다음으로는 생성된 모듈을 포함한 testbench 파일에 타이밍 정보를 입력하여 생명을 불어넣어줘야한다. wire 는 Data 를 연결, reg 는 Data 를 저장하는 변수이며 always 문 내에서 사용되는 변수는 앞에서 'reg' 로 선언되어야한다. 해당 코드를 확인해보면 현재 변수 d, rst, clk 이 always 문에서 사용되고 있기 때문에 변수들이 reg 로 선언된 것을 확인할 수 있다.

`include "D_FF.v"
`timescale 1ns/1ps

module D_FF_TB;
	wire q, qbar;
	reg clk,rst;
	reg d;

	D_FF d_ff(q,qbar,clk,rst,d);
	always #5 clk = ~clk;

	initial
	begin
        clk = 1'b0;
		rst = 1; # 10; rst = 0; #10; 
		$display("RSLT\td\tq\tqbar");
                d = 0; # 10; // Another value
                if ( q === 1'b0 ) // Test for inversion
                        $display ("PASS\t%d\t%d\t%d",d,q,qbar);
                else
                        $display ("FAIL\t%d\t%d\t%d",d,q,qbar);
		
                d = 1; # 10; // Another value
                if ( q === 1'b1 ) // Test for inversion
                        $display ("PASS\t%d\t%d\t%d",d,q,qbar);
                else
                        $display ("FAIL\t%d\t%d\t%d",d,q,qbar);

		#10;
		$finish;		
	end
  
  //enabling the wave dump
  initial begin 
    $dumpfile("D_FF_TB.vcd"); 
    $dumpvars(0, D_FF_TB);
  end
endmodule

3. 컴파일 및 파형 확인하기

생성된 testbench 파일을 터미널에서 컴파일링 한 후 gtkwave 로 파형을 확인하면 다음과 같이 rst 이 1 일 때, q = 1, rst = 0 일 때 d = q 로 정상적인 동작을 하는 것을 확인할 수 있다.

- SR Flip-Flop

1. module 정의하기

첫번째로 SR-FF 의 동작 방식을 참고하여 2-bit 로 정의된 sr(Set/Reset) 의 값에 따른 output 변화를 case 문을 통해 분류해준다.

module SR_FF(q, qbar, clk, rst, sr);
    output q;
    reg q;
    output qbar;
    input clk, rst;
    input [1:0] sr;

    assign qbar = ~q;

    always @(posedge clk)
    begin
        if (rst)
            q <= 0;
        else
            case(sr)
                2'b00: q <= q;
                2'b01: q <= 0;
                2'b10: q <= 1;
                2'b11: q <= 1'bx;
            endcase
    end
endmodule

2. testbench 생성하기

`include "SR_FF.v"
`timescale 1ns/1ps

module SR_FF_TB;

reg clk, rst;
reg [1:0] sr;

wire q;
wire qbar;

SR_FF sr_ff(.clk(clk), .rst(rst), .sr(sr), .q(q), .qbar(qbar));

always #5 clk = ~clk;

initial begin
    clk = 1'b0; rst = 1; #10; 
    rst = 0; sr = 0; #10;
    sr = 0; #10;
    sr = 1; #10;
    sr = 2; #10;
    sr = 3; #10;

end

initial begin
    $dumpfile("SR_FF_TB.vcd");
    $dumpvars(0, SR_FF_TB);
end

endmodule

3. 컴파일 및 파형 확인하기

마치며

오늘까지가 기본적인 logic circuit 에 관한 내용이었다. 앞으로 Adder, Counter, Multiplier, Comparator 가 남았고... 비록 소스코드가 돌아다니고 있고 복사 붙여넣기만 하면 되는 일이지만 코드 분석이라도 열심히 해서 래퍼런스 없이도 코드를 능숙하게 짤 수 있는 정도로 연습해보려고 한다. 느리지만 정확하게!
To be continued...🫠

profile
연습장

0개의 댓글