Verilog Guide 2

허가은·2022년 9월 15일
0

Verilog Guide

목록 보기
3/3
  • verilog의 제어문
  • mux, decoder with Behavioral level

본 글에서는 verilog의 제어문 문법에 대해 알아보고, 이 지식을 이용하여 multiflexer와 decoder를 Behavioral modeling으로 구현해보고자 한다.

1. verilog의 제어문

verilog의 제어문은 if, else, case문이 많이 사용된다. c에서는 case문의 사용이 그다지 추천되지 않을지 몰라도, 베릴로그에선 굉장히 잘 사용된다.

if-else 구문

if(expression)
    statements;
else if(expression)
    statements;
else
    statements;

의 형태로 사용하면 되며, always begin-end 구문 안에서 사용해야 한다.
따라서 statements의 왼쪽 할당받는 변수는 reg로 선언되어야함에 주의하자.

또한, verilog는 Hardware Description Language이다. 소프트웨어적 환경에서 우리가 코드를 짤 경우 어떤 경우에 대하여 if의 행동만 지정해주고, else의 경우는 지정하지 않아도 되는 경우가 많다.
그러나 verilog는 하드웨어를 설명하는 코드이기 때문에, 어떤 경우에 대한 지정을 빼놓는 경우 컴파일러가 코드를 자의적으로 해석하여 원치 않는 동작을 하게끔 하거나, 코드가 돌아가지 않는 경우가 발생할 수 있다.
따라서 if-else구문을 사용할때는 반드시 모든 이벤트에 대한 행동을 지정하였는지 확인하여야 한다.

case 구문

case(expression)
    condition : statements;
    condition : statements;
    condition : statements;
    default   : statements;
endcase

if문과 같이 always begin-end 구문 안에서 사용해야 한다.
마찬가지로 statements의 왼쪽 할당받는 변수는 reg로 선언되어야함에 주의하자. 감지되는 모든 case에 대해 행동을 지정해주거나, 지정해주지 않는 case에 대해서 컴파일러가 이해할 수 있도록 default를 작성해주어야 한다.

if문과 case문에 대해 간략하게 알아본 채로 바로 multiflexer와 decoder를 제작해보자.

2. Multiflexer

모두가 알다시피 mux는 n-bit의 selector를 이용해서 2^n개의 입력중 하나의 입력을 선택해서 출력해주는 시스템이다.

4-to-1mux를 gate level로 작성한다면, 위의 그림과 같이 7개의 gate가 필요하며 그 값이 직관적이지 않겠지만, behavioral modeling으로 작성한다면 굉장히 직관적인 코드가 된다.

code

module 4_to_1mux (
    input a, b, c, d,
    input [1:0] sel,
    output reg out
);
    always @(a, b, c, d, sel) begin
        case(sel)
            2'b00 : out = a;
            2'b01 : out = b;
            2'b10 : out = c;
            2'b11 : out = d;
        endcase
    end
endmodule

설명

case문을 이용한 mux의 코드이다. mux는 case문을 가장 잘 사용할 수 있는 대표적인 예이다. wire와 port 선언시 [n-1:0]을 사용하여 c언어의 array와 비슷한 모양으로 선언해주면 n-bit의 wire/port를 사용할 수 있다.(reg도 사용할 수 있다.)

3. decoder

decoder는 n-bit의 입력을 2^n개의 1-bit 출력으로 만들어준다. case문을 이용하여 작성해보자.

code

module 3_to_8dec (
    input [3-1:0] in,
    output reg [8-1:0] out
);
    always @(*) begin
        case(in)
			3'b000: out = 8'b0000_0001;
			3'b001: out = 8'b0000_0010;
			3'b010: out = 8'b0000_0100;
			3'b011: out = 8'b0000_1000;

			3'b100: out = 8'b0001_0000;
			3'b101: out = 8'b0010_0000;
			3'b110: out = 8'b0100_0000;
			3'b111: out = 8'b1000_0000;
        endcase
    end
endmodule

설명

[n-1:0]과 같이 []안쪽에 연산자를 넣어도 작동한다.
always구문의 @()에 *을 넣어주면 모든 input에 대하여 이벤트가 감지된다.
제어문의 statement에서 우측에서 숫자를 직접 넣어줄 수 있으며 binary 외에도 decimal, hexadecimal이 사용가능하다.
숫자 사이에 4bit마다 _를 넣어주면 가독성이 높아지며 코드의 동작에는 영향을 주지 않는다.

0개의 댓글