HDLBits More Verilog Features편

강정윤·2024년 9월 25일

안녕하세요 오늘은 Verilog의 다른 특징들에 살펴보는 편입니다.
그리고 이제 Verilog Language가 끝나는 편이기도 합니다.

아마 다음편부터는 간단한 Circuit을 작성하는 것으로 할텐데요, 마음 같으면 빠르게 끝내고 SystemVerilog편으로 찾아뵙고 싶습니다!

하지만 SystemVerilog는 Verilog를 확장한 버전이기에... Verilog Language부터 확실하게 알아야 추가적인 SystemVerilog를 배울 때, 혼동이 없겠지요?

그럼 문제로 들어보도록 합시다.

Conditional ternary operator

이 문제는 삼항 연산자를 소개하면서 시작하고 있습니다.
?:로 작성하는 건 C언어에서도 봤지요?
Verilog에서도 가능하다는 것을 말해주고 있습니다.

(condition) ? if true : if false

이런식으로 작성하시면 되고요 ? 바로 뒤에 오는 녀석이 condition문이 참일 경우에 assign되고 거짓이라면 뒤에 있는 녀석이 assign됩니다.
어떤가요 if-else부터 case문까지 다루고 온 우리들에게는 어렵지 않을 것이라 생각합니다.

자 이건 assign statement말고도 always block 내에서도 사용가능합니다.
그리고 이 삼항연산자는 항상 true일 때, false일 때를 명확하게 나타내므로 latch가 생성될 여지도 없습니다.

문제를 보도록 합시다!!

그림1 : Conditional ternary operator

문제에서는 conditional operator를 사용해서 2개의 값을 비교하는 비교기를 생성하고, 이걸 묶어서 4개를 비교하는 회로를 만들라고 하고 있군요

그림을 제가 그려서 이해를 도와드리겠습니다.

그림2 : min comparator

자 a,b를 비교하는 mux의 결과를 r1이라고 하고 c,d를 비교하는 mux의 결과를 r2라고 합시다.

그러면 mux로 최소값이 나오겠지요?
이걸 이제 verilog로 작성하면 됩니다.

`default_nettype none
module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//

    // assign intermediate_result1 = compare? true: false;
    
    wire [7:0]	r1,r2;
    
    assign r1 = (a>b) ? b : a;
    assign r2 = (c>d) ? d : c;
    assign min = (r1>r2) ? r2 : r1;

endmodule

네 이렇게 작성하시면 됩니다!
제가 위에 `default_nettype none이라고 쓴 것은 미리 선언되지 않은 wire를 암시적으로 만드는 것을 방지하기 위해 작성한 것입니다.

후...어제 제가 assign해야하는 출력 포트를 오타로 잘못 입력해서...
계속해서 오작동이 일어나서 디버기하는데...정말로 힘들었답니다...
오타도 정말 찾기 힘든 정도로 헷갈리게....

앞으로 어제의 일을 교훈으로 삼아서 `default_nettype none을 적극적으로 사용해야할 것 같습니다..!

Reduction operators

이번 문제에서 다루는 것은 vector 안에 있는 bitwise operation을 하고 싶을 때에 대한 내용입니다.

자 우리가 다음과 같은 연산을 한다고 생각해봅시다.

assign x = a[15]&a[14]&a[13]&a[12]& ....... a[1]&a[0];

하나하나 전부 작성해주면 힘들겠지요?
위의 경우는 16bit인데도 힘들고 귀찮아서 제가 ...으로 생략했습니다

이런 귀차니즘을 위해 이번 문제를 잘 보시면 좋을 듯합니다.

assign x = &a;

이러게 하면 위에서 하나하나 &해준 것과 동일한 결과입니다.
어떤가요?
저는 너무 좋습니다

자 문제로 들어가봅시다

그림3 : Redution operators

문제에서는 Parity checking하는 circuit을 만들라고 합니다.
parity bit에 대해 간단하게 설명만 하고 문제를 풀도록 합시다.

Parity bit

Parity bit란 오류 검출을 위해 사용하는 bit인데, 우리가 Serial 통신을 하다보면 이런 화면을 본 적이 있을 겁니다.

그림4 : Parity bit 설명자료

위의 화면은 MobaXterm의 화면이고요, Parity bit을 Odd로 하냐 Even으로 하냐 Mark, Space 이렇게 4개가 있군요.

Parity bit를 설정하는 방식이 한가지로 고정적이지 않다는 것을 미리 말씀드립니다.

Parity bit를 짝수 패리티로 설정한다면?

짝수 패티리는 실제 전송하고자 하는 데이터의 bit들 중 1의 개수가 짝수가 되도록 parity bit를 정하는 방식입니다

Parity bit를 홀수 패리티로 설정한다면?

홀수 패리티는 실제 전송하고자 하는 데이터의 bit들 중 1의 개수가 홀수가 되도록 parity bit를 정하는 방식입니다.

다시 문제로 돌아가봅시다
문제에서는 Even parity bit 생성하는 circuit을 만들라고 하는 군요
XOR gate를 사용하면 간단하게 작성할 수 있습니다.

module top_module (
    input [7:0] in,
    output parity); 
	
    assign parity = ^in;
endmodule

이론 설명이 코드보다 훨씬 길군요....^^
이런 경우가 많긴 합니다...
이론을 이해하고 나면 코드는 정말로 간결하게 나오는 경우도 많으니..
시간이 괜찮다면 이런 circuit관련 이론을 공부해보는 것도 좋을 것 같습니다!

Reduction : Even wider gates

이번 문제는 위의 문제의 확장판인데, 가볍게 코드만 보여드리고 넘어가도록 하겠습니다.

module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    
    assign out_and = ∈
    assign out_or = |in;
    assign out_xor = ^in;

endmodule

Combinational for-loop : Vector reversal2

우리 이전에 Vector reversal하는 문제를 다룬 적이 있습니다.
그 때는 하나하나 bit를 반전시켜주었지요.
이번에는 for-loop를 사용해서 간단하게 작성해보도록 합시다.
이 때 for-loop는 합성되는 것이 아니라 합성되는 과정 중에서 circuit을 기술하는 방법입니다!(당연한 소리지요...)

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    integer i;
    
    always@(*)begin
        for(i=0;i<100;i=i+1) begin
            out[99-i] = in[i]; 
        end
    end
    

endmodule

아 참고로 assign 문을 for-loop로 사용할 수는 없답니다.

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    integer i;
    
   
   for(i=0;i<100;i=i+1) begin
   		assign out[99-i] = in[i]; 
   end
   
endmodule

이런식으로 할 수 없다 이말입니다.

이 점 참고하길 바랍니다.

Combinational for-loop : 255-bit population count

이번문제는 이진수에서 1의 개수를 세는 연산을 하는 circuit을 for-loop를 사용해서 작성해봐라는 문제입니다.
pop count는 다양한 곳에서 쓰이는데, 이걸 구현하는 것을 이번에 알아두면 좋을 것 같습니다

module top_module( 
    input [254:0] in,
    output [7:0] out );
    
    integer i;
    
    always@(*) begin
        out = 0;
        for(i=0;i<255;i=i+1)begin
            out =out + in[i];  
        end
            
	end

endmodule

이런식으로 작성해주시면 되겠습니다.
이건 out에 대한 초기값을 작성해주는 것이 중요합니다.
for-loop의 처음에 오른쪽에 있는 out에 어떤 값이 있는지 모르니까요.

Generate for-loop : 100-bit binary adder2

우리 adder를 만들어본 적이 있습니다.
이번에는 for-loop를 이용해서 100bit binary ripple-carry adder를 작성해보라고 합니다.

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    
    integer i ;
	
    assign {cout[0],sum[0]} = a[0]+b[0]+cin;
    
    always@(*)begin
        for(i=1;i<100;i=i+1)begin
            {cout[i],sum[i]} = a[i]+b[i]+cout[i-1];
        end
    end

endmodule

초기에 0번째 bit를 계산해주는 부분만 for-loop 외부에서 작성해주시고(cin때문에)
나머지 99bit들은 for-loop를 이용해서 작성해주시면 되겠습니다

Generate for-loop:100-digit BCD adder

자 BCD라는 용어가 나왔습니다.
BCD란 Binary-Coded Decimal의 약자로 10진수 0~9를 2진화한 코드로 작성한 것입니다

1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
11~15 unused

이렇게 사용합니다.

123을 표현해보면 0001_0010_0011으로 표현할 수 있습니다.

문제로 들어가봅시다
문제에서는 BCD module은 이미 주어졌다고 합니다.
따라서 이 모듈을 instantiation 해줘야겠지요.
그걸 for-loop을 이용해서 해보도록 합시다.

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    
    genvar i;
    wire cout0[98:0];
    
    bcd_fadd inst0(
        .a(a[3:0]),
        .b(b[3:0]),
        .cin(cin),
        .cout(cout0[0]),
        .sum(sum[3:0])
    );
             
    bcd_fadd inst99(
        .a(a[399:396]),
        .b(b[399:396]),
        .cin(cout0[98]),
        .cout(cout),
        .sum(sum[399:396])
    );
     
             
      
    
    generate
        for(i=1;i<99;i=i+1)begin : gen_block
        bcd_fadd inst(
            .a(a[4*(i+1)-1 : 4*i]),
            .b(b[4*(i+1)-1 : 4*i]),
            .cin(cout0[i-1]),
            .cout(cout0[i]),
            .sum(sum[4*(i+1)-1 : 4*i])
        );
    end
    endgenerate

endmodule

이렇게 작성하시면 됩니다.

module의 인스턴스를 생성할 때는 generate block을 사용하시면 되고, 이 때 내부에 for-loop i는 genvar type으로 선언해주면 됩니다!

이렇게 오늘은 Verilog Language의 마지막 편인 More Verilog Features에 대해 문제를 풀고, 그 개념들에 대해 다루어 봤는데요, 다음 시간에는 circuit에 대한 포스팅으로 찾아오겠습니다.

감사합니다~

profile
muscle brain

0개의 댓글