通过risc-v访问rom。
input wire clk ,
input wire rst
);
// open_risc_v to rom
wire[31:0] open_risc_v_inst_addr_o;
//rom to open_risc_v
wire[31:0] rom_inst_o;
open_risc_v open_risc_v_inst(
.clk (clk ),
.rst (rst ),
.inst_i (rom_inst_o ),
.inst_addr_o (open_risc_v_inst_addr_o)
);
rom rom_inst(
.inst_addr_i (open_risc_v_inst_addr_o),
.inst_o (rom_inst_o )
);
endmodule
进行测试
1 第一条指令
MOV x27,12'd26 : 将寄存器x7填充,立即数38
ADDI x27,x0,imm
000000100110_00000_000_11011_0010011
rs1为0,0010011为操作码I型指令操作码
2 第二条指令
MOV x28,12'd54 :将x28寄存器填充立即数54
ADDI x28,x0,immm
000000110110_00000_000_11011_0010011
3 第三条指令 0110011 为R型指令操作码
ADD X29,X28,x27
0000000_11100_11011_000_rd_0110011
testbench
指令通过txt文件写入。
inst_data_ADD.txt:
00000010011000000000110110010011 00000111100000000000111000010011 00000001110011011000111010110011
应该去打印x27 x28 x29寄存器的值,去查看。
通过while循环。while(1),
reg clk;
reg rst;
// 延时后生成时钟
always #10 clk = ~clk;
initial begin
clk <= 1'b1;
rst <= 1'b0;
#30; // 延时后取消复位
rst <= 1'b1;
end
//rom 初始值 仿真开始就加入
initial begin
//系统函数写入。 文件名和写入地址。 写入地址通过例化名. 的形式获取将数据吸入rom_mem中 $readmemb("inst_data_ADD.txt",tb.open_risc_v_soc_inst.rom_inst.rom_mem);
end
//打印寄存器输出。 第一个为格式,第二个为寄存器变量名regs[27],regs[28],regs[29]
initial begin
while(1)begin
@(posedge clk)
$display("x27 register value is %d",tb.open_risc_v_soc_inst.open_risc_v_inst.regs_inst.regs[27]);
$display("x28 register value is %d",tb.open_risc_v_soc_inst.open_risc_v_inst.regs_inst.regs[28]);
$display("x29 register value is %d",tb.open_risc_v_soc_inst.open_risc_v_inst.regs_inst.regs[29]);
//分隔线
$display("---------------------------");
$display("---------------------------");
end
end
// 例化处理器
open_risc_v_soc open_risc_v_soc_inst(
.clk (clk),
.rst (rst)
);
endmodule
verilog中的write
$display(p1,p2, …,pn);
$write(p1,p2, …,pn);
这两个函数和系统任务的作用都是用来输出信息,即将参数p2到pn按参数p1给定的格式输出。参数p1通常称为:“格式控制”,参数p2至pn通常称为“输出列表”。
write则不是这样。如果想在一行里输出多个信息,可以使用display(“%d”,10) 和 $display(“%d\n”,10) 效果相同
verilog系统函数 readmemh
作用:把文本文件中的数据赋值到存储器中。
$readmemb(“File”,MemoryName[, StartAddr[, FinishAddr]]);
$readmemh(“File”,MemoryName[, StartAddr[, FinishAddr]]);
起始地址可以省略。
readmemh(“File”,MemoryName);
readmemh要求文本中的每个数字是十六进制值。
modelsim仿真
change directory - new library - new project - 导入工程
compel all
宏定义文件,需要包含文件的绝对路径。且/ 分隔符。
双击tb文件,只仿真测试文件即可。
vsim命令行进行仿真
run # 执行仿真(默认执行100ns,-all 执行到结束)
txt文件的读取也要加上路径。
流水线输出,第一条指令完成后,下一个周期第二条指令,也完成了
,再一下个周期完成第三条指令
第一个时钟上升沿开始,第一个周期为不定态,因为未复位,第二个周期开始复位。
第三个周期开始为cpu的第一个周期取指, 依次译码,执行。
即在第五个周期到来时,完成第一条指令。 第一条指令有效耗时,三个周期,第六个周期完成第二条指令,第七个周期完成执行第三条指令
与下图仿真结果完全一致。