CPU设计笔记2-存储器读写模块

设计一个存储器读写模块,模块功能如下:

      

存储模块总容量4KB,位宽32bit,考虑到节省功耗,将存储空间划分为4块memory实现,每块存储器1KB即256*32大小的存储块。4块memory依次编址

地址空间(字对齐地址)

 

0x300  ~  0x3ff

Mem3

0x200  ~  0x2ff

Mem2

0x100  ~  0x1ff

Mem1

0x000  ~  0x0ff

Mem0

 

存储器读写模块需要实现的功能如下:

序号

操作名称

功能说明

1

Load Byte

Byte数据装载,根据byte地址读取出相应8bit字节,经过符号位扩展后形成一个32bit数输出

2

Load half word

半字数据装载,根据半字地址(地址最低位为0)读取出相应16bit半字,经过符号位扩展后形成一个32bit数输出

3

Load word

整字数据装载,根据字地址(地址最低2bit为0)读取出一个32bit数输出

4

Store Byte

Byte数据存储,将输入32bit数据的低8位根据byte地址存入存储器

5

Store half word

半字数据存储,将输入32bit数据的低16位根据半字地址存入存储器

6

Store word

整字数据装载,将输入32bit数据存入存储器

 

存储器读写模块的接口如下:

信号名

位宽

I/O

描述

clk

1

I

时钟

nrst

1

I

全局异步时钟,低电平有效,有效时所有寄存器清零

stall

1

I

暂停信号,该信号为1时,不进行任何读写操作

op_code

3

I

读写操作类型,对应功能表格各个功能

RWaddr

14

I

Byte对齐地址

wdata

32

I

写端口数据

rdata

32

O

从memory读出的32bit数据

 

请用verilog搭建memory模型后进行模块例化调用,1KB存储器规模为256*32bit,其接口及功能定义如下:

信号名

位宽

I/O

描述

CLK

1

I

时钟

CEN

1

I

mem使能信号,低电平有效

WEN

1

I

写使能信号,低电平有效

BWEN

32

I

Bit-write enable,按bit写使能

A

8

I

读写地址

D

32

I

写数据

Q

32

O

读数据

 

mem的读写波形如下:

dmem.v

module memory #(
// --------------------------------------------------------------------------
// Parameter Declarations
// --------------------------------------------------------------------------
  parameter AW = 8
)
(
    input CLK,
    input CEN,
    input WEN,
    input [31:0]BWEN,
    input [AW-1:0]A,
    input [31:0]D,
    output reg [31:0]Q
    );

// -----------------------------------------------------------------------------
// Constant Declarations
// -----------------------------------------------------------------------------
//localparam AWT = ((1<<AW)-1);

    // Memory Array
    reg [31:0]mem[255:0];

   initial $readmemh("D:/workspace/verilog/EDA/RISC-V_CPU_2019/RISC-V_CPU_2019.srcs/sources_1/new/dmem.hex", mem);

always @ (posedge CLK)
    begin
        if(CEN)
            Q <= 32'h0;
        else
            Q <= mem[A];
    end

 always @ (posedge CLK)
    begin
        if(~CEN & ~WEN )
            begin
                if (~BWEN[0])
                    mem[A][0] <= D[0];
                if (~BWEN[1])
                    mem[A][1] <= D[1];
                if (~BWEN[2])
                    mem[A][2] <= D[2];
                if (~BWEN[3])
                    mem[A][3] <= D[3];
                if (~BWEN[4])
                    mem[A][4] <= D[4];
                if (~BWEN[5])
                    mem[A][5] <= D[5];
                if (~BWEN[6])
                    mem[A][6] <= D[6];
                if (~BWEN[7])
                    mem[A][7] <= D[7];
                
                if (~BWEN[8])
                    mem[A][8] <= D[8];
                if (~BWEN[9])
                    mem[A][9] <= D[9];
                if (~BWEN[10])
                    mem[A][10] <= D[10];
                if (~BWEN[11])
                    mem[A][11] <= D[11];
                if (~BWEN[12])
                    mem[A][12] <= D[12];
                if (~BWEN[13])
                    mem[A][13] <= D[13];
                if (~BWEN[14])
                    mem[A][14] <= D[14];
                if (~BWEN[15])
                    mem[A][15] <= D[15];
                
                if (~BWEN[16])
                    mem[A][16] <= D[16];
                if (~BWEN[17])
                    mem[A][17] <= D[17];
                if (~BWEN[18])
                    mem[A][18] <= D[18];
                if (~BWEN[19])
                    mem[A][19] <= D[19];
                if (~BWEN[20])
                    mem[A][20] <= D[20];
                if (~BWEN[21])
                    mem[A][21] <= D[21];
                if (~BWEN[22])
                    mem[A][22] <= D[22];
                if (~BWEN[23])
                    mem[A][23] <= D[23];
                
                if (~BWEN[24])
                    mem[A][24] <= D[24];
                if (~BWEN[25])
                    mem[A][25] <= D[25];
                if (~BWEN[26])
                    mem[A][26] <= D[26];
                if (~BWEN[27])
                    mem[A][27] <= D[27];
                if (~BWEN[28])
                    mem[A][28] <= D[28];
                if (~BWEN[29])
                    mem[A][29] <= D[29];
                if (~BWEN[30])
                    mem[A][30] <= D[30];
                if (~BWEN[31])
                    mem[A][31] <= D[31];
                
            end
    end

endmodule

dmem_ctrl.v

module mem_ctrl(
    input clk,
    input nrst,
    input stall,
    input [2:0]op_code,
    input [11:0]RWaddr,
    input [31:0]wdata,
    output rdata
    );
    
    reg [31:0]rdata = 32'h0;
    wire CEN1;
    wire CEN2;
    wire CEN3;
    wire CEN4;
    
    wire WEN;
    wire [31:0]BWEN;
    
    wire [31:0] Q1;
    wire [31:0] Q2;
    wire [31:0] Q3;
    wire [31:0] Q4;
    wire [31:0] Q;
    
    assign CEN1 = RWaddr[11] | RWaddr[10];
    assign CEN2 = RWaddr[11] | ~RWaddr[10];
    assign CEN3 = ~RWaddr[11] | RWaddr[10];
    assign CEN4 = ~RWaddr[11] | ~RWaddr[10];
    
    assign WEN = ~op_code[2];
    
    assign BWEN[7:0] = op_code[2]?8'h00:8'hff;
    assign BWEN[15:8] = (op_code[2] & (op_code[1] ^ op_code[0]))?8'h00:8'hff;
    assign BWEN[31:16] = (op_code[2] & op_code[1] & ~op_code[0])?16'h0000:16'hffff;
    
    
    memory mem1(.CLK(clk), .CEN(CEN1), .WEN(WEN), .BWEN(BWEN), .A(RWaddr[9:2]), .D(wdata), .Q(Q1));
    memory mem2(.CLK(clk), .CEN(CEN2), .WEN(WEN), .BWEN(BWEN), .A(RWaddr[9:2]), .D(wdata), .Q(Q2));
    memory mem3(.CLK(clk), .CEN(CEN3), .WEN(WEN), .BWEN(BWEN), .A(RWaddr[9:2]), .D(wdata), .Q(Q3));
    memory mem4(.CLK(clk), .CEN(CEN4), .WEN(WEN), .BWEN(BWEN), .A(RWaddr[9:2]), .D(wdata), .Q(Q4));
  
    wire [31:0]out1;
    wire [31:0]out2;
    
    assign out1 = RWaddr[10]?Q2:Q1;
    assign out2 = RWaddr[10]?Q4:Q3;
    assign Q    = RWaddr[11]?out2:out1; 
    
always @ (posedge clk)
begin
    case(op_code)
    	3'b000://load_byte
        		case(RWaddr[1:0])
        			2'b00:rdata = {{24{Q[7]}},Q[7:0]};
        			2'b01:rdata = {{24{Q[15]}},Q[15:8]};
        			2'b10:rdata = {{24{Q[23]}},Q[23:16]};
        			2'b11:rdata = {{24{Q[31]}},Q[31:24]};
        		endcase
    	3'b001://load_halfword
        		if (RWaddr[1]) 
                    rdata = {{16{Q[31]}},Q[31:16]};
        		else 		
			         rdata = {{16{Q[15]}},Q[15:0]};	
    	3'b010://load word
        	rdata = Q;
//	   default:rdata = 32'hffffffff;
	endcase
end
    
endmodule

mem_ctrl_tb.v

`timescale 1ns / 1ps


module mem_ctrl_tb(

    );

reg clk;
reg nrst;
reg stall;
reg [2:0]  	op_code;
reg [11:0] 	RWaddr;
reg [31:0] 	wdata;
wire [31:0] 	rdata;

mem_ctrl ram0(
	clk,
	nrst,
	stall,
	op_code,
	RWaddr,
	wdata,
	rdata
);

always begin
    #10 clk = ~clk;
end

initial begin
        clk = 1'b1;
        nrst = 1'b1;
        stall = 1'b0;
        op_code = 3'b110;
        RWaddr = 12'b0000_0000_0100;
        wdata = 32'hff00ff00;
        #30 begin
            op_code = 3'b110;
            RWaddr = 12'b0000_0000_1000;
            wdata = 32'hf000000f;
             end
        #60 begin
            op_code = 3'b110;
            RWaddr = 12'b0000_0000_0100;
            wdata = 32'hff0000ff;
             end
        #60 begin
            op_code = 3'b010;
            RWaddr = 14'b0000_0000_1000;
             end		
             
         #60 begin
             op_code = 3'b010;
                RWaddr = 14'b0000_0000_0100;
            end				 
    end

endmodule

猜你喜欢

转载自blog.csdn.net/qq_24815615/article/details/92805202
今日推荐