杭电计算机组成原理课程设计-实验八-存储器设计实验
程序员文章站
2022-07-05 23:14:51
...
实验内容
1.生成一个RAM_B存储器模块,关联文件中输入64个32位数据,用16进制表示。
2.调用寄存器堆模块和存储器模块,编写一个顶层模块,完成寄存器和存储器之间数据的传送。
3.调用基本ALU 模块、寄存器堆模块和存储器模块,编写一个顶层模块,完成
lw rt, offset(rs); //取数:(rs+offset) -> rt
sw rt, offset(rs); //存数:rt -> (rs+offset)
16位的偏移地址offset从input输入,扩展为32位。仿真调试通过
.coe文件内容
memory_initialization_radix=16;
memory_initialization_vector=00000010,00632020,00010fff,00000008,ffff0000,0000ffff,88888888,99999999,aaaaaaaa,bbbbbbbb,12345678,23456789,3456789a,456789ab,56789abc,6789abcd,00000820,00632020,00010fff,20006789,ffff0000,0000ffff,88888888,99999999,aaaaaaaa,bbbbbbbb,12345678,23456789,3456789a,456789ab,56789abc,6789abcd,00000820,00632020,00010fff,20006789,ffff0000,0000ffff,88888888,99999999,aaaaaaaa,bbbbbbbb,12345678,23456789,3456789a,456789ab,56789abc,6789abcd,00000820,00632020,00010fff,20006789,ffff0000,0000ffff,88888888,99999999,aaaaaaaa,bbbbbbbb,12345678,23456789,3456789a,456789ab,56789abc,6789abcd;
如何生成IP核详见ISE-IP核创建教程.
MEM模块代码
module Mem(clk_m,Mem_Write,
R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk,
ALU_OP,offset,
Mem_Addr,M_R_Data,R_data_A,R_data_B,ALU_F,B);
input clk_m,Mem_Write;
input [4:0]R_Addr_A;//A端口读寄存器地址
input [4:0]R_Addr_B;//B端口读寄存器地址
input [4:0]W_Addr;//写寄存器地址
input Write_Reg;
input [2:0]ALU_OP;
input rst,clk;
input [15:0]offset;
output [31:0]M_R_Data;
output [31:0]R_data_A;
output [31:0]R_data_B;
wire ZF,OF;
output [31:0]B;
output [31:0] ALU_F;
output [7:0] Mem_Addr;
RAM_B Data_RAM (
.clka(clk_m), // input clka
.wea(Mem_Write), // input [0 : 0] wea
.addra(Mem_Addr[7:2]), // input [5 : 0] addra
.dina(R_data_B), // input [31 : 0] dina
.douta(M_R_Data) // output [31 : 0] douta
);
assign B={{16{1'b0}},offset}; //扩展
REGS REGS_1(R_data_A,R_data_B,M_R_Data,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
ALU ALU_1(ALU_OP,R_data_A,B,ALU_F,ZF,OF);
assign Mem_Addr=ALU_F[7:0];
endmodule
module REGS(R_Data_A,R_Data_B,W_Data,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
input clk;//写入时钟信号
input rst;//清零信号
input Write_Reg;//写控制信号
input [4:0]R_Addr_A;//A端口读寄存器地址
input [4:0]R_Addr_B;//B端口读寄存器地址
input [4:0]W_Addr;//写寄存器地址
input [31:0]W_Data;//写入数据
output [31:0]R_Data_A;//A端口读出数据
output [31:0]R_Data_B;//B端口读出数据
integer i;
reg [31:0] REG_Files[0:31];
initial
for(i=0;i<32;i=i+1) REG_Files[i]<=0;
aaa@qq.com(posedge clk or posedge rst)
begin
if(rst)
for(i=0;i<32;i=i+1) REG_Files[i]<=0;
else
if(Write_Reg) REG_Files[W_Addr]<=W_Data;
end
assign R_Data_A=REG_Files[R_Addr_A];
assign R_Data_B=REG_Files[R_Addr_B];
endmodule
module ALU(ALU_OP,A,B,F,ZF,OF);
input [2:0] ALU_OP;
input [31:0] A;
input [31:0] B;
output [31:0] F;
output ZF;
output OF;
reg [31:0] F;
reg C,ZF,OF;
aaa@qq.com(*)
begin
C=0;
OF=0;
case(ALU_OP)
3'b000:begin F=A&B; end
3'b001:begin F=A|B; end
3'b010:begin F=A^B; end
3'b011:begin F=~(A|B); end
3'b100:begin {C,F}=A+B;OF = A[31]^B[31]^F[31]^C; end
3'b101:begin {C,F}=A-B;OF = A[31]^B[31]^F[31]^C; end
3'b110:begin F=A<B; end
3'b111:begin F=B<<A; end
endcase
ZF = F==0;
end
endmodule
测试用例
always #33 clk=~clk;
always #23 clk_m=~clk_m;
initial begin
clk= 0; clk_m = 0;
ALU_OP = 3'b100;
rst = 0;
// lw $1,4($0)
offset = 16'd4;
W_Addr = 5'b00001;
Mem_Write = 0;
Write_Reg = 0;
R_Addr_A = 5'b00000;
R_Addr_B = 5'b00000;
#100
Write_Reg = 1; #100
// lw $2,12($0)
offset = 16'd12;
W_Addr = 5'b00010;
R_Addr_A = 5'b00000;
R_Addr_B = 5'b00000;
Write_Reg = 1; #100
// lw $3,4($2)
offset = 16'd8;
W_Addr = 5'b00011;
R_Addr_A = 5'b00010;
R_Addr_B = 5'b00010;
Write_Reg = 1; #100
//sw $3,24[$0]
offset = 24'd24;
R_Addr_A=5'b00000;
R_Addr_B=5'b00011;
Write_Reg = 0;
Mem_Write = 1;
#100;
// lw $4,24($0)
offset = 16'd24;
W_Addr = 5'b00100;
R_Addr_A = 5'b00000;
R_Addr_B = 5'b00000;
Mem_Write = 0;
Write_Reg = 1; #100;
end
endmodule