一.实验目的

1. 了解只读存储器 ROM 和随机存取存储器 RAM 的原理。

2. 理解 ROM 读取数据及 RAM 读取、写入数据的过程。

3. 理解计算机中存储器地址编址和数据索引方法。

4. 理解同步 RAM 和异步 RAM 的区别。

5. 掌握调用 Xilinx 库 IP 实例化 RAM 的设计方法。

6. 熟悉并运用 verilog 语言进行电路设计。

7. 为后续设计 cpu 的实验打下基础。

二.实验设备

1. 装有 Xilinx Vivado 的计算机一台。

2. LSCPUEXB002 教学系统实验箱一套。

. 实验内容与步骤

1.设计框图

2.核心代码

`timescale 1ns / 1ps

//

//   > 文件名: data_mem.v

//   > 描述  :异步数据存储器模块,采用寄存器搭建而成,类似寄存器堆

//   >         同步写,异步读

//   > 作者  : LOONGSON

//   > 日期  : 20160414

//

module data_ram(

    input         clk,         // 时钟

    input  [3:0]  wen,         // 字节写使能

    input  [4:0] addr,        // 地址

    input  [31:0] wdata,       // 写数据

    output reg [31:0] rdata,       // 读数据

   

    //调试端口,用于读出数据显示

    input  [4 :0] test_addr,

    output reg [31:0] test_data

);

    reg [31:0] DM[31:0];  //数据存储器,字节地址7'b000_0000~7'b111_1111

    //写数据

    always @(posedge clk)    // 当写控制信号为1,数据写入内存

    begin

        if (wen[3])

        begin

            DM[addr][31:24] <= wdata[31:24];

        end

    end

    always @(posedge clk)

    begin

        if (wen[2])

        begin

            DM[addr][23:16] <= wdata[23:16];

        end

    end

    always @(posedge clk)

    begin

        if (wen[1])

        begin

            DM[addr][15: 8] <= wdata[15: 8];

        end

    end

    always @(posedge clk)

    begin

        if (wen[0])

        begin

            DM[addr][7 : 0] <= wdata[7 : 0];

        end

    end

   

    //读数据,取4字节

    always @()

    begin

        case (addr)

            5'd0 : rdata <= DM[0 ];

            5'd1 : rdata <= DM[1 ];

            5'd2 : rdata <= DM[2 ];

            5'd3 : rdata <= DM[3 ];

            5'd4 : rdata <= DM[4 ];

            5'd5 : rdata <= DM[5 ];

            5'd6 : rdata <= DM[6 ];

            5'd7 : rdata <= DM[7 ];

            5'd8 : rdata <= DM[8 ];

            5'd9 : rdata <= DM[9 ];

            5'd10: rdata <= DM[10];

            5'd11: rdata <= DM[11];

            5'd12: rdata <= DM[12];

            5'd13: rdata <= DM[13];

            5'd14: rdata <= DM[14];

            5'd15: rdata <= DM[15];

            5'd16: rdata <= DM[16];

            5'd17: rdata <= DM[17];

            5'd18: rdata <= DM[18];

            5'd19: rdata <= DM[19];

            5'd20: rdata <= DM[20];

            5'd21: rdata <= DM[21];

            5'd22: rdata <= DM[22];

            5'd23: rdata <= DM[23];

            5'd24: rdata <= DM[24];

            5'd25: rdata <= DM[25];

            5'd26: rdata <= DM[26];

            5'd27: rdata <= DM[27];

            5'd28: rdata <= DM[28];

            5'd29: rdata <= DM[29];

            5'd30: rdata <= DM[30];

            5'd31: rdata <= DM[31];

        endcase

    end

    //调试端口,读出特定内存的数据

    always @()

    begin

        case (test_addr)

            5'd0 : test_data <= DM[0 ];

            5'd1 : test_data <= DM[1 ];

            5'd2 : test_data <= DM[2 ];

            5'd3 : test_data <= DM[3 ];

            5'd4 : test_data <= DM[4 ];

            5'd5 : test_data <= DM[5 ];

            5'd6 : test_data <= DM[6 ];

            5'd7 : test_data <= DM[7 ];

            5'd8 : test_data <= DM[8 ];

            5'd9 : test_data <= DM[9 ];

            5'd10: test_data <= DM[10];

            5'd11: test_data <= DM[11];

            5'd12: test_data <= DM[12];

            5'd13: test_data <= DM[13];

            5'd14: test_data <= DM[14];

            5'd15: test_data <= DM[15];

            5'd16: test_data <= DM[16];

            5'd17: test_data <= DM[17];

            5'd18: test_data <= DM[18];

            5'd19: test_data <= DM[19];

            5'd20: test_data <= DM[20];

            5'd21: test_data <= DM[21];

            5'd22: test_data <= DM[22];

            5'd23: test_data <= DM[23];

            5'd24: test_data <= DM[24];

            5'd25: test_data <= DM[25];

            5'd26: test_data <= DM[26];

            5'd27: test_data <= DM[27];

            5'd28: test_data <= DM[28];

            5'd29: test_data <= DM[29];

            5'd30: test_data <= DM[30];

            5'd31: test_data <= DM[31];

        endcase

    end

endmodule

`timescale 1ns / 1ps

//

//   > 文件名: inst_rom.v

//   > 描述  :异步指令存储器模块,采用寄存器搭建而成,类似寄存器堆

//   >         内嵌好指令,只读,异步读

//   > 作者  : LOONGSON

//   > 日期  : 20160414

//

module inst_rom(

    input      [4 :0] addr, // 指令地址

    output reg [31:0] inst       // 指令

    );

    wire [31:0] inst_rom[19:0];  // 指令存储器,字节地址7'b000_0000~7'b111_1111

    // 指令编码 |指令地址| 汇编指令 | 指令结果 //

    assign inst_rom[ 0] = 32'h24010001; // 00H: addiu $1 ,$0,#1   | $1 = 0000_0001H

    assign inst_rom[ 1] = 32'h00011100; // 04H: sll   $2 ,$1,#4   | $2 = 0000_0010H

    assign inst_rom[ 2] = 32'h00411821; // 08H: addu  $3 ,$2,$1   | $3 = 0000_0011H

    assign inst_rom[ 3] = 32'h00022082; // 0CH: srl   $4 ,$2,#2   | $4 = 0000_0004H

    assign inst_rom[ 4] = 32'h00642823; // 10H: subu  $5 ,$3,$4   | $5 = 0000_000DH

    assign inst_rom[ 5] = 32'hAC250013; // 14H: sw    $5 ,#19($1) | Mem[0000_0014H] = 0000_000DH

    assign inst_rom[ 6] = 32'h00A23027; // 18H: nor   $6 ,$5,$2   | $6 = FFFF_FFE2H

    assign inst_rom[ 7] = 32'h00C33825; // 1CH: or    $7 ,$6,$3   | $7 = FFFF_FFF3H

    assign inst_rom[ 8] = 32'h00E64026; // 20H: xor   $8 ,$7,$6   | $8 = 0000_0011H

    assign inst_rom[ 9] = 32'hAC08001C; // 24H: sw    $8 ,#28($0) | Mem[0000_001CH] = 0000_0011H

    assign inst_rom[10] = 32'h00C7482A; // 28H: slt   $9 ,$6,$7   | $9 = 0000_0001H

    assign inst_rom[11] = 32'h11210002; // 2CH: beq   $9 ,$1,#2   | 跳转到指令34H

    assign inst_rom[12] = 32'h24010004; // 30H: addiu $1 ,$0,#4   | 不执行

    assign inst_rom[13] = 32'h8C2A0013; // 34H: lw    $10,#19($1) | $10 = 0000_000DH

    assign inst_rom[14] = 32'h15450003; // 38H: bne   $10,$5,#3   | 不跳转

    assign inst_rom[15] = 32'h00415824; // 3CH: and   $11,$2,$1   | $11 = 0000_0000H

    assign inst_rom[16] = 32'hAC0B001C; // 40H: sw    $11,#28($0) | Men[0000_001CH] = 0000_0000H

    assign inst_rom[17] = 32'hAC040010; // 44H: sw    $4 ,#16($0) | Mem[0000_0010H] = 0000_0004H

    assign inst_rom[18] = 32'h3C0C000C; // 48H: lui   $12,#12     | [R12] = 000C_0000H

    assign inst_rom[19] = 32'h08000000; // 4CH: j     00H         | 跳转指令00H

    //读指令,取4字节

    always @()

    begin

        case (addr)

            5'd0 : inst <= inst_rom[0 ];

            5'd1 : inst <= inst_rom[1 ];

            5'd2 : inst <= inst_rom[2 ];

            5'd3 : inst <= inst_rom[3 ];

            5'd4 : inst <= inst_rom[4 ];

            5'd5 : inst <= inst_rom[5 ];

            5'd6 : inst <= inst_rom[6 ];

            5'd7 : inst <= inst_rom[7 ];

            5'd8 : inst <= inst_rom[8 ];

            5'd9 : inst <= inst_rom[9 ];

            5'd10: inst <= inst_rom[10];

            5'd11: inst <= inst_rom[11];

            5'd12: inst <= inst_rom[12];

            5'd13: inst <= inst_rom[13];

            5'd14: inst <= inst_rom[14];

            5'd15: inst <= inst_rom[15];

            5'd16: inst <= inst_rom[16];

            5'd17: inst <= inst_rom[17];

            5'd18: inst <= inst_rom[18];

            5'd19: inst <= inst_rom[19];

            default: inst <= 32'd0;

        endcase

    end

endmodule

3.创新点说明

4.仿真曲线截图

本次实验无。

5.硬件实现照片

运行后如图所示

在00000444地址中写入数据12345678

通过拨码控制将WDATA移到RDATA中。

可以看到是两位两位地移过来的。

全部移动完了。

写入数据操作进行完后,读取00000444中的数据,与写入的相同,验证成功。

T_ADD和T_DAT一样也能读取指定地址中的数据。

6.实验结果分析 

成功向地址`00000444`写入数据`12345678`,读取结果与输入一致,证明数据存储器读写正常。指令存储器可按地址正确输出预设指令(如加法、移位等),异步读取特性满足设计要求。 

触摸屏显示数据与存储器操作同步,双端口读(`rdata`与`test_data`)支持同时监测不同地址数据,调试便捷。拨码控制下数据逐段写入并正确显示,证明地址索引与数据传输逻辑无误。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐