博客地址转至https://xisynotz.xyz
一、 实验目的
设计一64*32bit的寄存器文件,即64个32位的寄存器文件(寄存器组)。
二、 实验要求
寄存器文件满足如下要求:
a) 具备一组读端口及一组写端口
b) 通过读端口可从0~31号的任意地址读取数据
c) 通过写端口可向0~31号的任意地址写入数据
d) 寄存器的复位值可自行指定
三、 实验内容
(1) 主要代码分析
module top(
input clk,
output[31:0] writein
);
reg[5:0] readaddr=5'd0;
reg[31:0] readout1;
reg[31:0] readout2;
wire[31:0] readout;
reg[31:0] writeaddr;
reg writeenable = 1'b0;
reg[2:0] count = 3'd0;
regfilere(clk,1'b1,readaddr,readout,writeaddr,writein,writeenable);
alu al(readout1,readout2,5'd1,writein);
always@(negedge clk) //control部分,利用标记数count来
//进行步骤的循环,每次循环里面有
//四个步骤,分别在下降沿执行,修改
//在上升沿的执行的regfile的参数
begin
if(count==3'd0)
begin
count<= count + 1'b1;
writeenable<=1'b0;
end
elseif(count==3'd1) // 修改操作数2读取寄存器地址
begin
count<= count + 1'b1;
readout1<= readout;
readaddr<= readaddr + 1'b1;
writeenable<=1'b0;
end
elseif(count==3'd2)
begin
count<= count + 1'b1;
readout2<= readout;
writeenable<=1'b0;
end
elseif(count==3'd3) //修改写入寄存器地和write使能
begin
writeenable<=1'b1;
writeaddr<= readaddr + 1'b1;
count<= 3'd0;
end
end
endmodule
*******************************************************
(省略号省去了省略代码)
module regfile(
input clk,
input rst_n,
input[4:0] rAddr,
output reg[31:0] rDout,
input[4:0] wAddr,
input[31:0] wDin,
input wEna
);
reg[31:0] r1 = 32'b10;reg[31:0] r17 =32'b0;reg[31:0] r33 = 32'b0;reg[31:0] r49 = 32'b0;
……
reg[31:0] r16 = 32'b0;reg[31:0] r32 =32'b0;reg[31:0] r48 = 32'b0;reg[31:0] r64 = 32'b0;
always@(posedge clk,negedge rst_n)
begin
if(~rst_n)
begin
r1= 32'b0;r17 = 32'b0;r33 = 32'b0;r49 = 32'b0;
……
r16= 32'b0;r32 = 32'b0;r48 = 32'b0;r64 = 32'b0;
end
else
begin
if(~wEna)
begin
case(rAddr)
5'd0:rDout= r1;5'd1:rDout = r2;
……
5'd62:rDout= r63;5'd63:rDout = r64;
endcase
end
else
begin
case(wAddr)
5'd0:r1 =wDin;
……
5'd63:r64 =wDin;
endcase
end
end
end
endmodule
然而这个写法无比之蠢,,,
verilog可以使用数组来定义
module REG_FILE(
input clk,
input rst_n,
input [4:0] rAddr1,
input [4:0] rAddr2,
output [31:0] rDout1,
output [31:0] rDout2,
input [4:0] wAddr,
input [31:0] wDin,
input wEna
);
reg [31:0] register[31:0];
assign rDout1=register[rAddr1];
assign rDout2=register[rAddr2];
always@(posedge clk or negedge rst_n)
if(~rst_n)
begin
register[0]=0; register[1]=0; register[2]=0; register[3]=0;
register[4]=0; register[5]=0; register[6]=0; register[7]=0;
register[8]=0; register[9]=0; register[10]=0; register[11]=0;
register[12]=0; register[13]=0; register[14]=0; register[15]=0;
register[16]=0; register[17]=0; register[18]=0; register[19]=0;
register[20]=0; register[21]=0; register[22]=0; register[23]=0;
register[24]=0; register[25]=0; register[26]=0; register[27]=0;
register[28]=0; register[29]=0; register[30]=0; register[31]=0;
end
else
begin
if(wEna)
begin
register[wAddr]=wDin;
end
else
register[wAddr]=register[wAddr];
end
endmodule
其实初始化好像也可以用循环语句来做,这里就不深入了
三、 分析和总结
Regfile模块中的寄存器较多,应当使用数组方式表示更为方便简洁。本人在最初实验编码的时候没有采用这种方法,导致代码冗余繁琐,不得不自己编写程序进行重复性输出。
在对regfile和ALU进行control时,考虑到regfile模块是时钟上升沿敏感的,所以在下降沿对实例化的参数进行修改,这样充分利用了每个时钟周期,而且不会导致冲突。
本实验regfile模块的编写较为简单,关键在于control部分的逻辑要清晰。