k0b0's record.

Computer Engineering, Arts and Books

SystemVrilogでレジスタファイルを記述してみる

SystemVerilogで2種類のレジスタファイル(アドレス長:2ビット、レジスタ数:4、データ長:32ビット)を記述してみる。

レジスタファイル(レジスタとMUXで構成)

個人的にはこちらの記述の方が読みやすいかなぁ。
(レジスタ数が増えると、コードの行数が長くなるけど。。。)

/* regfile.v */
module regfile #(parameter A_WIDTH = 2, D_WIDTH = 32)
                (input                clk,
		 input  [A_WIDTH-1:0] readaddr1,
		 input  [A_WIDTH-1:0] readaddr2,
		 input  [A_WIDTH-1:0] writeaddr,
		 input                we,
		 input  [D_WIDTH-1:0] writedata,
		 output [D_WIDTH-1:0] readdata1,
	         output [D_WIDTH-1:0] readdata2);


logic [D_WIDTH-1:0] r0 = 0;
logic [D_WIDTH-1:0] r1 = 0;
logic [D_WIDTH-1:0] r2 = 0;
logic [D_WIDTH-1:0] r3 = 0;

/* Reading Register 1 */
assign readdata1 = (readaddr1 == 0) ? r0 :
		   (readaddr1 == 1) ? r1 :
		   (readaddr1 == 2) ? r2 : r3;

/* Reading Register 2 */
assign readdata2 = (readaddr2 == 0) ? r0 :
		   (readaddr2 == 1) ? r1 :
		   (readaddr2 == 2) ? r2 : r3;

/* Writing data */
always_ff @(posedge clk) 
begin
    if(we) 
    begin
	case(writeaddr) 
	    0: r0  <= writedata;
	    1: r1  <= writedata;
	    2: r2  <= writedata;
	    3: r3  <= writedata;
	   default : r0 <= 32'd0;
	endcase
    end
end

endmodule

レジスタファイル(RAMで構成)

こちらの記述は↑の記述よりコード数が少ない。

/* regfile_ram.sv */
module regfile_ram #(parameter A_WIDTH = 2, D_WIDTH=32)
                    (input clk,
	             input [A_WIDTH-1:0] readaddr1, readaddr2,
	             input [A_WIDTH-1:0] writeaddr,
	             input               we,
		     input [D_WIDTH-1:0] writedata,
		     output [D_WIDTH-1:0] readdata1,
		     output [D_WIDTH-1:0] readdata2);
	             

logic [D_WIDTH-1:0] dmem [0:2**A_WIDTH-1] ;

always_ff @(posedge clk)
begin
    if(we) 
	dmem[writeaddr] <= writedata;
end

assign readdata1 = dmem[readaddr1];
assign readdata2 = dmem[readaddr2];

endmodule