imem.v 使用$readmemh函数初始化存储器 注意$readmemh和$readmemb的区别
module imem(
input CLK,
input CEN,
input WEN,
input [7:0]A,
input [31:0]D,
output reg [31:0]Q
);
reg[31:0]mem[255:0];
initial $readmemh("D:/workspace/verilog/EDA/RISC-V_CPU_2019/RISC-V_CPU_2019.srcs/sources_1/new/riscv.hex",mem);
always@(posedge CLK)
if(~CEN & ~WEN)
mem[A] <= D;//读入
always@(posedge CLK)
if(~CEN)//读请求
Q <= mem[A];//读出 (延迟一个时钟输出)
endmodule
IF.v
module IF(
input clk,
input nrst,
input stall,
input br_en,
input [31:0 ] br_addr,
output [31:0] PC,
output [31:0] ins_out
);
reg CEN = 1'b0;
reg WEN = 1'b1;;
reg [31:0] D = 32'h0;
reg [31:0] PC_reg = 32'h0;
imem imem0(
.CLK(clk),
.CEN(CEN),
.WEN(WEN),
.A(PC[9:2]),
.D(D),
.Q(ins_out)
);
always @ (posedge clk)
begin
if(~nrst)
begin
PC_reg = 32'h0;
end
else if(~stall)
PC_reg <= PC + 32'd4;
end
assign PC = br_en ? br_addr:PC_reg;
endmodule
IF_tb.v
module IF_tb(
);
reg clk;
reg nrst;
reg stall;
reg br_en;
reg [31:0 ] br_addr;
wire [31:0] PC;
wire [31:0] ins_out;
IF IF1 (
.clk(clk),
.nrst(nrst),
.stall(stall),
.br_en(br_en),
.br_addr(br_addr),
.PC(PC),
.ins_out(ins_out)
);
initial
begin
clk = 0;
nrst = 1;
stall = 0;
br_en = 0;
br_addr = 32'h2;
#100 stall = 1;
#100 stall = 0;
#50 br_en = 1;
#50 br_en = 0;
end
always #5 clk = ~clk;
endmodule
仿真结果如下图: