存储器设计:存储器设计课程设计
计算机组成原理实验
实验五 存储器设计
专业班级:计算机科学与技术
学号: 0936008 姓名:冯帆
学号: 0936036 姓名:张琪
实验地点: 理工楼901
实验五 存储器设计
一、实验目的
1、 掌握RAM 和ROM 的Verilog 语言描述方法;
2、 学习用宏模块的方法定制RAM 和ROM 。
二、实验内容
1、设计并实现一个8*8 的单端口的RAM ;
2、设计并实现一个128*16的ROM ;
3、设计并实现一个双端口的128*16的RAM 。
4、设计并实现正弦信号发生器,参考“正弦信号发生器实验指南”。
三、实验仪器及设备:
PC 机+ Quartus Ⅱ 9.0 + DE2-70
四、实验步骤
1. 打开Quartus 软件,新建工程。
2.分析单端口,双端口,ROM,RAM 的含义。
3.Verilog 程序如下,并简单注释。
①/*单端口的RAM*/
module SingleRamTest(read_data, read_address, write_data, write_address, memwrite, clock, reset);
output [7:0] read_data; //数据的输出
input [2:0] read_address; //读数据地址的输入
input [7:0] write_data; //写数据地址的输入
input [2:0] write_address; //写数据地址的输入
input memwrite; //若该信号为1,进行写操作,反之,写操作 input clock;
input reset; //复位和时钟信号
reg [7:0] read_data, mem0, mem1,mem2,mem3,mem4,mem5,mem6,mem7; //设置存储器存储单元
/* Block for memory read */
always @(read_address or mem0 or mem1 or mem2 or mem3 or mem4 or mem5 or mem6 or mem7) //若上述信号有一个发生变化,则启动该模块 begin
case(read_address) //读地址确定唯一的存储单元并将数据存储到readdata 中
3"b 000: read_data = mem0;
3"b 001: read_data = mem1;
3"b 010: read_data = mem2;
3"b 011: read_data = mem3;
3"b 100: read_data = mem4;
3"b 101: read_data = mem5;
3"b 110: read_data = mem6;
3"b 111: read_data = mem7;
/* Unimplemented memory */
default: read_data = 8"h FF;
endcase
end
/* Block for memory write */
always @(posedge clock or posedge reset) //在时钟或者复位信号的控制下 begin
if (reset) //如果复位,则所有存储单元都设置为初始化值 begin
/* Initial values for memory (optional) */
mem0 = 8"h 55;
mem1 = 8"h 55;
mem2 = 8"h 55;
mem3 = 8"h 55;
mem4 = 8"h 55;
mem5 = 8"h 55;
mem6 = 8"h 55;
mem7 = 8"h 55;
end
else if (memwrite) //若不复位,且写信号有效,则将writedata 的值写到mem 存储单元里
/* write new value to memory */
case (write_address)
3"b 000 : mem0 = write_data;
3"b 001 : mem1 = write_data;
3"b 010 : mem2 = write_data;
3"b 011 : mem3 = write_data;
3"b 100 : mem4 = write_data;
3"b 101 : mem5 = write_data;
3"b 110 : mem6 = write_data;
3"b 111 : mem7 = write_data;
endcase
end
endmodule
②设计并实现一个128*16的ROM 。
程序及注释如下:
module RomTest
#(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=7)
(
input [(ADDR_WIDTH-1):0] addr, //地址宽度为16位的addr
input clk,
output reg [(DATA_WIDTH-1):0] q //数据宽度为16位的q
);
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
// Initialize the ROM with $readmemb. Put the memory contents
// in the file single_port_rom_init.txt. Without this file,
// this design will not compile.
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
// format of this file.
Initial //读文件中对rom 的初始化值 begin
$readmemb("single_port_rom_init.txt", rom);
end
always @ (posedge clk) //q输出在addr 地址存储的值 begin
q
end
endmodule
③设计并实现一个双端口的128*16的RAM
利用宏模块对RAM 进行自定义,得到如下程序。
// megafunction wizard: %ALTSYNCRAM%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: altsyncram0.v
// Megafunction Name(s):
// altsyncram
//
// Simulation Lipary Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 9.0 Build 132 02/25/2009 SJ Full Version
// ************************************************************
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module altsyncram0 (
byteena_a,
data,
inclock,
inclocken,
out_aclr,
outclock,
outclocken,
rdaddress,
wraddress,
wren,
q);
input [1:0] byteena_a;
input [15:0] data;
input inclock;
input inclocken;
input out_aclr;
input outclock;
input outclocken;
input [6:0] rdaddress;
input [6:0] wraddress;
input wren;
output [15:0] q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 [1:0] byteena_a;
tri1 inclocken;
tri0 out_aclr;
tri1 outclocken;
tri1 wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [15:0] sub_wire0;
wire [15:0] q = sub_wire0[15:0];
altsyncram altsyncram_component (
.clocken1 (outclocken), .wren_a (wren), .clock0 (inclock), .aclr1 (out_aclr), .clock1 (outclock), .byteena_a (byteena_a), .address_a (wraddress), .address_b (rdaddress), .data_a (data), .q_b (sub_wire0), .aclr0 (1"b0), .addressstall_a (1"b0), .addressstall_b (1"b0), .byteena_b (1"b1), .clocken2 (1"b1), .clocken3 (1"b1), .data_b ({16{1"b1}}), .eccstatus (), .q_a (), .rden_a (1"b1), .rden_b (1"b1), .wren_b (1"b0)); defparam altsyncram_component.address_reg_b = "CLOCK0", altsyncram_component.byte_size = 8, altsyncram_component.clock_enable_input_a = "NORMAL", altsyncram_component.clock_enable_input_b = "NORMAL", altsyncram_component.clock_enable_output_a = "BYPASS", altsyncram_component.clock_enable_output_b = "NORMAL", altsyncram_component.init_file = "test", altsyncram_component.intended_device_family = "Cyclone II", altsyncram_component.lpm_type = "altsyncram", altsyncram_component.numwords_a = 128, altsyncram_component.numwords_b = 128, altsyncram_component.operation_mode = "DUAL_PORT", altsyncram_component.outdata_aclr_b = "CLEAR1", altsyncram_component.outdata_reg_b = "CLOCK1", altsyncram_component.power_up_uninitialized = "FALSE", altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", altsyncram_component.widthad_a = 7, altsyncram_component.widthad_b = 7, altsyncram_component.width_a = 16, altsyncram_component.width_b = 16,
altsyncram_component.width_byteena_a = 2;
endmodule
④设计并实现正弦信号发生器,参考“正弦信号发生器实验指南”
module sinwaveV
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input clk,
output reg [(DATA_WIDTH-1):0] q
);
reg [(ADDR_WIDTH-1):0] Q1;
wire newclk;
reg [4:0] clk_cnt;
assign newclk = clk_cnt[4];
always @(posedge clk)
begin
clk_cnt
end
always @(posedge newclk)
begin
Q1
end
lpm_rom0 lpm_rom0_inst ( .address ( Q1), .clock ( clk ), .q ( DOUT ) );
endmodule
函数图形如下:
六、实验思考题
1、分析存储器采用三态输出的原因是什么?
在第一个实验好中,读出数据的改变是在数据地址readaddress 或者存储器中存储数据发生变化时。这是数据改变的条件,设置成三态门更高效,更合理。
3、 单端口和双端口的区别是什么?
单端口存储器就是:存储器接受数据和输出数据,只能在同一时刻只能执行一项操作,这样
一来数据的写和传输就无法同时进行。双端口存储器是指同一个存储器具有两组相互独立的读写控制线路, 由于进行并行的独立操作,是一种高速工作的存储器。简单说来,就是增加了一个端口,可以同时读数据和写数据,提高了机器运行速度和带宽,可以实现无冲突的读写控制。
4、 什么情况下考虑采用双端口存储器?
主存的存取速度是影响计算机速度的关键,才用双端口存储器可是明显提高机器的利用率和效率。如果在对速度要求特别高的情况下,可以考虑采用双端口存储器。e
o d u l