计算机组成原理——寄存器堆

  • Post author:
  • Post category:其他


MIPS有个32寄存器,每个寄存器32位

由display编写可知input_sel控制输入情况

input_sel=

00:读地址1,01:读地址2

10:写地址,11写数据

读寄存器不需要时钟控制,但写寄存器需时钟控制。

声明模块的时候,输入一定是wire型变量,输出可以是wire也可以是reg



regfilg.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/10/05 15:22:20
// Design Name: 
// Module Name: regfile
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module regfile(
    input clk,
    input wen,//写使能
    input  [4 :0] raddr1,//读操作
    input  [4 :0] raddr2,
    output reg[31:0] rdata1,
    output reg[31:0] rdata2,

    input  [4 :0] waddr,//写操作
    input  [31:0] wdata,
    
    input [4 :0] test_addr,
    output reg[31:0] test_data
    );
    //实验要求,读寄存器不需要时钟控制,写需要
reg [31:0] memory[31:0];
integer i;
initial begin
    for(i=0;i<=31;i=i+1)
    begin
        memory[i]=0;
    end
end
always@(*)
begin
     rdata1<=memory[raddr1];
end
always@(*)
 begin
    rdata2<=memory[raddr2]; 
 end
always@(*)
begin
    test_data<=memory[test_addr]; 
end
 always@(posedge clk)
 begin
     if(wen==1)
     begin
          memory[waddr]<=wdata;
     end 
 end

endmodule



regfile_display

//*************************************************************************
//   > 文件名: regfile_display.v
//   > 描述  :寄存器堆显示模块,调用FPGA板上的IO接口和触摸屏
//   > 作者  : LOONGSON
//   > 日期  : 2016-04-14
//*************************************************************************
module regfile_display(
    //时钟与复位信号
    input clk,
    input resetn,    //后缀"n"代表低电平有效

    //拨码开关,用于产生写使能和选择输入数
    input wen,
    input [1:0] input_sel,

    //led灯,用于指示写使能信号,和正在输入什么数据
    output led_wen,
    output led_waddr,    //指示输入写地址
    output led_wdata,    //指示输入写数据
    output led_raddr1,   //指示输入读地址1
    output led_raddr2,   //指示输入读地址2

    //触摸屏相关接口,不需要更改
    output lcd_rst,
    output lcd_cs,
    output lcd_rs,
    output lcd_wr,
    output lcd_rd,
    inout[15:0] lcd_data_io,
    output lcd_bl_ctr,
    inout ct_int,
    inout ct_sda,
    output ct_scl,
    output ct_rstn
);
//-----{LED显示}begin
    assign led_wen    = wen;
    assign led_raddr1 = (input_sel==2'd0);
    assign led_raddr2 = (input_sel==2'd1);
    assign led_waddr  = (input_sel==2'd2);
    assign led_wdata  = (input_sel==2'd3);
//-----{LED显示}end

//-----{调用寄存器堆模块}begin
    //寄存器堆多增加一个读端口,用于在触摸屏上显示32个寄存器值
    wire [31:0] test_data;  
    wire [4 :0] test_addr;

    reg  [4 :0] raddr1;
    reg  [4 :0] raddr2;
    reg  [4 :0] waddr;
    reg  [31:0] wdata;
    wire [31:0] rdata1;
    wire [31:0] rdata2;
    regfile rf_module(
        .clk   (clk   ),
        .wen   (wen   ),
        .raddr1(raddr1),
        .raddr2(raddr2),
        .waddr (waddr ),
        .wdata (wdata ),
        .rdata1(rdata1),
        .rdata2(rdata2),
        .test_addr(test_addr),
        .test_data(test_data)
    );
//-----{调用寄存器堆模块}end

//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改
    reg         display_valid;
    reg  [39:0] display_name;
    reg  [31:0] display_value;
    wire [5 :0] display_number;
    wire        input_valid;
    wire [31:0] input_value;

    lcd_module lcd_module(
        .clk            (clk           ),   //10Mhz
        .resetn         (resetn        ),

        //调用触摸屏的接口
        .display_valid  (display_valid ),
        .display_name   (display_name  ),
        .display_value  (display_value ),
        .display_number (display_number),
        .input_valid    (input_valid   ),
        .input_value    (input_value   ),

        //lcd触摸屏相关接口,不需要更改
        .lcd_rst        (lcd_rst       ),
        .lcd_cs         (lcd_cs        ),
        .lcd_rs         (lcd_rs        ),
        .lcd_wr         (lcd_wr        ),
        .lcd_rd         (lcd_rd        ),
        .lcd_data_io    (lcd_data_io   ),
        .lcd_bl_ctr     (lcd_bl_ctr    ),
        .ct_int         (ct_int        ),
        .ct_sda         (ct_sda        ),
        .ct_scl         (ct_scl        ),
        .ct_rstn        (ct_rstn       )
    ); 
//-----{实例化触摸屏}end

//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块
    //32个寄存器显示在7~38号的显示块,故读地址为(display_number-1)
    assign test_addr = display_number-5'd7; 
    //当input_sel为2'b00时,表示输入数为读地址1,即raddr1
    always @(posedge clk)
    begin
        if (!resetn)
        begin
            raddr1 <= 5'd0;
        end
        else if (input_valid &&  input_sel==2'd0)
        begin
            raddr1 <= input_value[4:0];
        end
    end
    
    //当input_sel为2'b01时,表示输入数为读地址2,即raddr2
    always @(posedge clk)
    begin
        if (!resetn)
        begin
            raddr2 <= 5'd0;
        end
        else if (input_valid && input_sel==2'd1)
        begin
            raddr2 <= input_value[4:0];
        end
    end
    
    //当input_sel为2'b10时,表示输入数为写地址,即waddr
    always @(posedge clk)
    begin
        if (!resetn)
        begin
            waddr  <= 5'd0;
        end
        else if (input_valid && input_sel==2'd2)
        begin
            waddr  <= input_value[4:0];
        end
    end
    
    //当input_sel为2'b11时,表示输入数为写数据,即wdata
    always @(posedge clk)
    begin
        if (!resetn)
        begin
            wdata  <= 32'd0;
        end
        else if (input_valid && input_sel==2'd3)
        begin
            wdata  <= input_value;     
        end
    end
//-----{从触摸屏获取输入}end

//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,
    always @(posedge clk)
    begin
        if (display_number >6'd6 && display_number <6'd39 )
        begin //块号7~38显示32个通用寄存器的值
            display_valid <= 1'b1;
            display_name[39:16] <= "REG";
            display_name[15: 8] <= {4'b0011,3'b000,test_addr[4]};
            display_name[7 : 0] <= {4'b0011,test_addr[3:0]}; 
            display_value       <= test_data;
          end
        else
        begin
            case(display_number)
                6'd1 : //显示读端口1的地址
                begin
                    display_valid <= 1'b1;
                    display_name  <= "RADD1";
                    display_value <= raddr1;
                end
                6'd2 : //显示读端口1读出的数据
                begin
                    display_valid <= 1'b1;
                    display_name  <= "RDAT1";
                    display_value <= rdata1;
                end
                6'd3 : //显示读端口2的地址
                begin
                    display_valid <= 1'b1;
                    display_name  <= "RADD2";
                    display_value <= raddr2;
                end
                6'd4 : //显示读端口2读出的数据
                begin
                    display_valid <= 1'b1;
                    display_name  <= "RDAT2";
                    display_value <= rdata2;
                end
                6'd5 : //显示写端口的地址
                begin
                    display_valid <= 1'b1;
                    display_name  <= "WADDR";
                    display_value <= waddr;
                end
                6'd6 : //显示写端口写入的数据
                begin
                    display_valid <= 1'b1;
                    display_name  <= "WDATA";
                    display_value <= wdata;
                end
                default :
                begin
                    display_valid <= 1'b0;
                    display_name  <= 40'd0;
                    display_value <= 32'd0;
                end
            endcase
        end
    end
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule



tb.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/10/05 22:19:41
// Design Name: 
// Module Name: tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb;
    //inputs
    reg clk;
    reg wen;//写使能
    reg  [4 :0] raddr1;//读操作,读地址
    reg  [4 :0] raddr2;
    reg  [4 :0] waddr;
    reg  [31:0] wdata;
    reg  [4 :0] test_addr;
    //outputs
    wire [31:0] rdata1;//读出数据
    wire [31:0] rdata2;    
    wire  [31:0] test_data;
    regfile uut (//调用regfile模块,自定义名字uut
        .clk   (clk   ),
        .wen   (wen   ),
        .raddr1(raddr1),
        .raddr2(raddr2),
        .waddr (waddr ),
        .wdata (wdata ),
        .rdata1(rdata1),
        .rdata2(rdata2),
        .test_addr(test_addr),
        .test_data(test_data)
    );
    initial begin
    clk = 0;
    wen=0;
    raddr1=0;
    raddr2=0;
    waddr=0;
    wdata=0;
    test_addr=0;
    #100;
    wen=1;
    waddr=1'H1;
    wdata=32'H00001111;
    #200;
    wen=0;
    raddr1=1'H1;
    #400;
       
    end
   always #5 clk = ~clk;

endmodule



版权声明:本文为m0_46314779原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。