【verilog】寄存器文件


一、    实验目的

设计一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部分的逻辑要清晰。


猜你喜欢

转载自blog.csdn.net/saber_jk/article/details/80923164
今日推荐