实验四 存储器实现
本实验旨在掌握ROM和RAM的工作原理及Verilog实现方法。通过Xilinx Vivado平台,设计了一个32位异步数据存储器(data_ram.v)和一个指令存储器(inst_rom.v)。数据存储器支持同步写、异步读,采用寄存器堆结构实现32×32位存储;指令存储器预置20条MIPS指令,实现异步读取功能。实验成功验证了存储器功能:向地址00000444写入12345678后正确读出,指令
一.实验目的
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`)支持同时监测不同地址数据,调试便捷。拨码控制下数据逐段写入并正确显示,证明地址索引与数据传输逻辑无误。
更多推荐
所有评论(0)