본문 바로가기

실전! Verilog HDL RTL Design

[Verilog HDL] 10. task를 이용한 shifter 설계

반응형

이번 장에서 배울 것

  • task
  • barrel shifter

앞장에서 배운 function과 비슷한 기능을 하는 것이 task이다. function과 마찬가지로 여러개의 code를 묶어서 함수 호출하듯이 불러 쓸 수 있다. 그러나 task문에서는 delay문을 기술할 수 있다. 

우선 이번 장에서 설계할 shiter에 대해서 알아보자.

shifter는 여러 bit로 구성 된 입력을 원하는 bit 수 만큼 좌/우로 이동 시키는 것을 말한다.

예를 들어 4'b0100을 입력으로 받아 오른 쪽으로 2bit 이동 시키면 4'b0001이 된다. 또는 왼쪽으로 2bit 이동 시키면 4'b0000이 된다. bit 수를 넘어가면 그 값은 사라지게 된다. verilog에서 이런 기능을 하는 shift 연산자가 있는데 오른 쪽 shift는 '>>' , 왼쪽 shift는 '<<' 기호를 사용한다. 예를 들어 A변수를 오른 쪽으로 2bit이동 시키는 것은 A >> 2; 라는 문장으로 표현할 수 있고 왼쪽으로 2bit shift하는 것은 A << 2; 라고 표현 할 수 있다. 그리고 이렇게 한번에 여러 bit를 shift할 수 있는 shifter를 barrael shifter라고 한다.

 

이런 기능을 task로 표현하면 아래와 같다.

task shifter (input [7:0] a, input [2:0] num, input left_right, output [7:0] y);
begin
    if (left_right == 0) // shift right
    	y = #1 a >> num;
    else
    	y = #1 a << num;
end
endtask

'task' keyword 다음에는 task 이름이 오고 뒤에 오는 괄호안에 입력과 출력 파라메터를 정의한다.

여기서 'a'는 shift할 값 즉 오퍼랜드(operand)이고 num은 shift할 bit 수, 그리고 left_right는 좌/우 shift를 명시하는 파라메터로 여기서 '0'은 right shift, '1'은 left shift를 의미하는 것으로 약속한다. 그리고 출력 변수는 y로 정의한다.   또한 task문에서 delay 문을 기술할 수 있는 것을 보여 주기 위해 'y'변수 대입 문에 #1 과 같은 delay문을 사용하였다. 이는 a를 shift한 값을 1ns 이후에 y에 대입한다는 의미이다.

 

이 task를 이용한 barrel shifter는 아래와 같이 코딩할 수 있다.

module barrel_shifter (
	input clock,
    input resetn,
	input [7:0] a,
    input [2:0] num,
    input left_right,
    output reg [7:0] y
    );
    
reg [7:0] result;
 
task shifter (input [7:0] a, input [2:0] num, input left_right, output [7:0] y);
begin
    if (left_right == 0) // shift right
    	y = #1 a >> num;
    else
    	y = #1 a << num;
end
endtask
 
always @(posedge clock or negedge resetn)
begin
    if (~resetn)
    	y <= 0;
    else
    begin
    	shifter(a, num, left_right, result);
    	y <= result;
    end
end
    
endmodule

시뮬레이션을 수행하기 위한 테스트 벤치는 아래와 같다. 앞장의 테스트 벤치와 형태는 거의 동일하다.

입력 변수들은 모두 non-blocking assignment로 값을 대입해 주었다.

`timescale 1ns/1ns
 
module test;
 
// delare variables
reg clock;
reg resetn;
reg [7:0] a;
reg [2:0] num;
reg left_right;
 
wire [7:0] y;
 
// clock generation
always #10 clock = ~clock;
 
// shifter instantiation
barrel_shifter u_shifter (
    .clock  (clock),
    .resetn (resetn),
	.a      (a),
    .num    (num),
    .left_right (left_right),
    .y      (y)
);
 
 
// create wave dump file
initial
begin
    $dumpfile("shifter.vcd");
    $dumpvars(0, test);
end
 
// input stimulus
initial
begin
    a <= 0;
    num <= 0;
    left_right <= 0;
    clock <= 0;
    resetn <= 0;
    #100;
    resetn <= 1;
    a <= 2;
    num <= 1;
    @(posedge clock);
    left_right <= 1;
    a <= 4;
    num <= 2;
    @(posedge clock);
    #100;
    $finish();
end
 
endmodule

아래와 같이 컴파일하고 시뮬레이션 및 wave form 확인 할 수 있다.

>>iverilog test.v shifter.v
>>./a.out
>>gtkwave shifter.vcd&

아래는 결과 wave form이다.

clock의 positive edge 부분을 확대해서 보면 아래 그림과 같이 출력 y가 1ns 지연되어 출력되는 것을 알 수 있다.

반응형