2.5 Verilog Language - More Verilog Features

Kiwoong Nam·2025년 4월 12일

HDLBits

목록 보기
5/11

Last update: 25-04-12

Conditional ternary operator

Conditional

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

    assign min = (a < b ? a : b) < (c < d ? c : d) ? (a < b ? a : b) : (c < d ? c : d);

endmodule

앞 문제에서 ? : 구문을 안 쓰던 이유가 있었다. 이제 나온다.

always @(posedge clk)         // A T-flip-flop.
  q <= toggle ? ~q : q;

? : 구문을 이용한 T-FF 구현.

assign out = ena ? q : 1'bz;  // A tri-state buffer

tri-state buffer의 구현.

((sel[1:0] == 2'h0) ? a :     // A 3-to-1 mux
 (sel[1:0] == 2'h1) ? b :
                      c )

중첩을 통한 3-to-1 mux의 구현.

Reduction operators

Reduction

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

endmodule

&, |, ^는 원래 binary operator지만, unary operator로도 사용할 수 있으며 그 경우 reduction operator로서 동작한다. 연산자 뒤에 오는 벡터의 모든 비트에 대해 AND, OR, XOR 연산을 수행하는 역할을 한다.
예제에서는 1의 개수가 홀수인지 짝수인지를 패리티로 사용하는 상황을 가정해 reduction operator를 사용했다.

Reduction: Even wider gates

Gates100

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

endmodule

input이 매우 많은 논리 게이트도 reduction operator면 뚝딱이다.

Combinational for-loop: Vector reversal 2

Vector100r

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

endmodule

always @(*) 구문과 for문을 적절히 사용해서, vector reversal을 수행한다. combinational이므로 blocking assignment를 사용한다.

for (int i=0;i<$bits(out);i++)		// $bits() is a system function that returns the width of a signal.
	out[i] = in[$bits(out)-i-1];	// $bits(out) is 100 because out is 100 bits wide.

Solution은 이런 구문을 사용했는데 솔직히 알 필요는 없을 것 같다.

Combinational for-loop: 255-bit population count

Popcount255

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

endmodule

for loop를 사용해, in의 각 비트를 검사해 1인 비트의 수를 세는 문제다. 복잡하게 ? : 구문을 사용했는데, 어차피 비트라서 in[i]를 바로 더하면 된다는 것을 간과했다.

Generate for-loop: 100-bit binary adder 2

Adder100i

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

100개의 full adder를 사용해 100비트 덧셈기를 만드는 문제다. 힌트에서는 instance array를 사용하라고 했는데, 난 그냥 for문 안에서 다 해결해 버렸다. 그래서 다시 풀었다.

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    integer i;
	// wire [99:0] ci
	// wire [99:0] co;
	// assign ci = {cout[98:0], cin};
	// assign co = cout;
    add1 adder [99:0] (a, b, {cout[98:0], cin}, cout, sum);
    
endmodule

module add1(input a, b, cin, output cout, sum);
    assign {cout, sum} = a + b + cin;
    
endmodule

처음에 instance array를 벡터처럼 add1 [99:0] adder 이따위로 적어서 에러가 났는데, 이것저것 시도하다가 주석처리된 wire, assign 문을 만들어버렸다. 근데 저렇게 하면 컴파일 에러가 났고, 처음에 짰던 코드에서 array 선언문만 고쳐주니 정답 처리되었다.
output을 wire에다가 assign하면 에러가 나는 걸까?
어 근데 이러면 for-loop도 안 쓰는데?

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    integer i;
    wire [99:0] ci, co;
    assign ci[0] = cin;
    add1 adder [99:0] (a, b, ci, cout, sum);
    always @(*)
        for (i = 0; i < 99; i++) ci[i+1] = cout[i];

endmodule
        
module add1(input a, b, cin, output cout, sum);
    assign {cout, sum} = a + b + cin;
    
endmodule

아래 문제를 풀었던 걸 보고 오니 이 문제는 이렇게 푸는 게 의도가 아니었을까...

Generate for-loop: 100-digit BCD adder

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    integer i;
    wire [99:0] ci, co;
    assign ci[0] = cin;
    assign cout = co[99];
    bcd_fadd inst [99:0] (a, b, ci, co, sum);
    always @(*) begin
        for (i = 0; i < 99; i++) ci[i+1] = co[i];
    end

endmodule

bcd_fadd 모듈을 사용하는 문제다. 이렇게 푸니까 for-loop를 쓸 수가 있구나 와

0개의 댓글