본문 바로가기

실전! Verilog HDL RTL Design

[Verilog HDL] 19. 제어 가능한 ALU IP 만들기 - register file 수정

반응형

레지스터 map을 정의했으면 이에 맞게 register file을 만들어 주어야 한다. 이전에 만든 register file은 일반적인 register file이었고 이번에는 SFR의 목적에 맞게 수정해 주어야 한다. 전 장에서 만든 레지스터 맵을 보면 CPU가 read/write 할 수 있는 레지스터도 있고 ALU의 동작 상태에 따라 ALU에서 write하는 레지스터도 있다. 이러한 레지스터는 status와 result에 해당한다. 이런 특수한 목적에 맞게 수정된 register file은 아래와 같다.

module regfile #(
	parameter ADDR_WIDTH=8,
	parameter DATA_WIDTH=16
	)
	(
    input wire CLK,
    input wire RSTn,
    input wire [ADDR_WIDTH-1:0] ADDR,
    input wire WE,
    input wire [DATA_WIDTH-1:0] DIN,
    output reg [DATA_WIDTH-1:0] DOUT,

    output wire         start,
    output wire [ 7: 0] opA,
    output wire [ 7: 0] opB,
    output wire [ 1: 0] op,
    output wire         shift_dir,
    output wire [ 2: 0] shift_num,
    input wire [ 1: 0] result_op,
    input wire [ 7: 0] result
	);
 
integer  i;

reg [DATA_WIDTH-1:0]  mem [0:5];

parameter CONTROL   = 8'h0;
parameter OPERAND   = 8'h1;
parameter OPCODE    = 8'h2;
parameter SHIFTCON  = 8'h3;
parameter STATUS    = 8'h4;
parameter RESULT    = 8'h5;

assign start        = mem[CONTROL ][0];
assign opA          = mem[OPERAND ][15:8];
assign opB          = mem[OPERAND ][7:0];
assign op           = mem[OPCODE  ][1:0];
assign shift_dir    = op[0];
assign shift_num    = mem[SHIFTCON][2:0];
 
always @(posedge CLK or negedge RSTn)
begin
    if (!RSTn)
	begin
        for (i = 0; i<4; i=i+1)
            mem[i] <= 0;
    end
   	else if (WE)
	begin
        if (ADDR != RESULT || ADDR != STATUS)
            mem[ADDR] <= DIN;
	end
end

always @(posedge CLK or negedge RSTn)
begin
    if (!RSTn)
    begin
        mem[STATUS] <= 0;
        mem[RESULT] <= 0;
    end
    else if (start)
    begin
        mem[RESULT] <= result;
        mem[STATUS][1:0] <= result_op;	
    end
end

always @(*)
    DOUT = mem[ADDR];
 
endmodule

13-20 line:

ALU 제어에 필요한 신호를 입출력 포트로 선언한다. 이는 18장의 테이블을 참조하면 된다.

27-32 line:

table 18-2의 레지스터 맵에 기술한 주소를 파라메터로 정의 한다. 이렇게 하면 주소를 숫자로 입력하는 대신에 각 레지스터의 이름과 같이 의미있는 단어를 주소로 사용할 수 있다.

34-39 line:

레지스터 맵을 참조하여 입출력 신호를 레지스터의 해당 bit로 할당한다.

예를 들어start 포트는 register map의 0번 주소 0번 bit에 해당하므로 메모리 배열을  참조하는 방식으로 해당 bit를 할당할 수 있다. 

41-53 line:

CPU가 APB interface를 통해 read/write하는 레지스터들만 따로 코딩한다. 여기서는 status와 result 레지스터를 제외한 레지스터가 해당되므로 이는 주소 0번에서 3번에 해당한다. for loop를 사용하여 reset구간에서 초기화를 하였고 reset이 아닌 구간에서는 WE신호에 따라 해당 주소에 값을 쓰도록 코딩하였다.

55-67 line:

ALU IP에 의해 써지는 레지스터를 따로 코딩하였다. 여기서는 status와 result 레지스터가 해당 된다.

start가 '1'인 경우에만 써지고 아닌 경우에는 이전 값을 유지하도록 하였다.

 

이렇게 만든 register file은 ALU IP가 사용하는 SFR로써의 역할을 하게 된다.

 

이 레지스터파일을 APB interface로 제어하기 위한 apb_regfile.v는아래와 같이 입출력 포트를 연결하는 것으로 수정할 수  있다.

module apb_regfile #(
	parameter ADDR_WIDTH=8,
	parameter DATA_WIDTH=16
	)
	(
    input wire PCLK,
    input wire PRESETn,
    input wire [ADDR_WIDTH-1:0] PADDR,
    input wire PSEL,
    input wire PENABLE,
    input wire PWRITE,
    input wire [DATA_WIDTH-1:0] PWDATA,
    output reg [DATA_WIDTH-1:0] PRDATA,
    output wire PREADY,
    output wire         start,
    output wire [ 7: 0] opA,
    output wire [ 7: 0] opB,
    output wire [ 1: 0] op,
    output wire         shift_dir,
    output wire [ 2: 0] shift_num,
    output wire [ 1: 0] result_op,
    output wire [ 7: 0] result
	);

	wire [ADDR_WIDTH-1:0] ADDR;
	wire [DATA_WIDTH-1:0] DIN;
	wire [DATA_WIDTH-1:0] DOUT;
	wire                  WE;

	assign ADDR    = PADDR;
	assign DIN     = PWDATA;
	assign PREADY  = 1;
	assign WE      = PSEL & PENABLE & PWRITE;

	always @(*) PRDATA  = DOUT;

	regfile #(
     	.ADDR_WIDTH(ADDR_WIDTH),
     	.DATA_WIDTH(DATA_WIDTH)
     	) u_regfile (
    	.CLK          (PCLK        ),
    	.RSTn         (PRESETn     ),
    	.ADDR         (ADDR        ),
    	.DIN          (DIN         ),
    	.DOUT         (DOUT        ),
    	.WE           (WE          ),
        .start        (start       ),
        .opA          (opA         ),
        .opB          (opB         ),
        .op           (op          ),
        .shift_dir    (shift_dir   ),
        .shift_num    (shift_num   ),
        .result_op    (result_op   ),
        .result       (result      )
    	);
 
endmodule
반응형