寄存器堆-个人记录

 异步读,所以只要是输入寄存器的地址,应能够立刻得到寄存器的内容。

wen是写使能端,写进去的数是0AAH,raddr1,raddr2,test_addr地址与写的地址同,故存的数为0AAH。

 MIPS有个32寄存器,每个寄存器32位
由display编写可知input_sel控制输入情况
input_sel=
00:读地址1,01:读地址2
10:写地址,11写数据
读寄存器不需要时钟控制,但写寄存器需时钟控制。
声明模块的时候,输入一定是wire型变量,输出可以是wire也可以是reg

assign rdata1 = REG_Files[raddr1] ;
assign rdata2 = REG_Files[raddr2];
assign test_data  = REG_Files[test_addr];

//32个寄存器显示在7~38号的显示块,故读地址为(display_number-7)
    assign test_addr = display_number-5'd7;  

 radd1为12H时,对应的第18个寄存器 (18+7就是触摸屏的第25个块)


wire赋值用assign         reg b<=a非阻塞  b=a阻塞立刻改变


`timescale 1ns / 1ps
module regfile(
    input             clk,
    input             wen,//写使能信号
    input      [4 :0] raddr1,
    input      [4 :0] raddr2,
    input      [4 :0] waddr,
    input      [31:0] wdata,
    output  [31:0] rdata1,
    output [31:0] rdata2,
    input      [4 :0] test_addr,
    output [31:0] test_data
    );
integer i = 0;
    reg [31:0] REG_Files[31:0];
        initial//初始化32个寄存器,全为0
            for(i = 0;i < 32;i = i + 1) 
            REG_Files[i]<=0;
        always @ (posedge clk)
        begin
           if(wen)
           REG_Files[waddr] <= wdata;
        end
        assign rdata1 = REG_Files[raddr1] ;
        assign rdata2 = REG_Files[raddr2];
        assign test_data  = REG_Files[test_addr];

endmodule
//   > 描述  :寄存器堆显示模块,调用FPGA板上的IO接口和触摸屏

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-7)
    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
`timescale 1ns / 1ps
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;

    // Instantiate the Unit Under Test (UUT)
    regfile rf(
    .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
        // Initialize Inputs
        clk = 0;
        wen = 0;
        raddr1 = 0;
        raddr2 = 0;
		waddr = 0;
		wdata = 0;
		test_addr = 0;

        // Wait 100 ns for global reset to finish
        #100;
		waddr = 5'h10;;
		wdata = 32'h0AA;
        #400;
        wen = 1'b1;
        #500;
        wen = 1'b0;
        #400;
        raddr1 = 5'h10;
        #500;
        raddr2 = 5'h10;
        #400;
        test_addr = 5'h10;
        // Add stimulus here
    end
   always #5 clk = ~clk;
endmodule


左起三个按钮,第一个写使能1的时候有效,接下来两个

00:读地址1       01:读地址2
10:写地址        11:写数据

比如我先10 11把地址确定好 数据也确定了  读的地址若与写的地址一样,则对应的RDAT1/2 会有数据,且对应的寄存器也有数据,若不一样,则只有寄存器有数据。


 

 仿真文件不太懂 这是三个实验的xdc

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值