Refine memory interface.
This commit is contained in:
parent
7f42e7f7a4
commit
dfc2c47327
399
picorv32.v
399
picorv32.v
|
@ -33,7 +33,6 @@
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`define assert(assert_expr) empty_statement
|
`define assert(assert_expr) empty_statement
|
||||||
`define FORMAL_KEEP
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
* picorv32
|
* picorv32
|
||||||
|
@ -44,22 +43,21 @@ module picorv32 #(
|
||||||
parameter [31:0] STACKADDR = 32'hffff_ffff
|
parameter [31:0] STACKADDR = 32'hffff_ffff
|
||||||
) (
|
) (
|
||||||
input clk,
|
input clk,
|
||||||
resetn,
|
input resetn,
|
||||||
output reg trap,
|
output reg trap,
|
||||||
|
|
||||||
output reg mem_valid,
|
output reg mem_valid,
|
||||||
output reg mem_instr,
|
|
||||||
input mem_ready,
|
input mem_ready,
|
||||||
|
|
||||||
output reg [31:0] mem_addr,
|
output [31:0] mem_addr,
|
||||||
output reg [31:0] mem_wdata,
|
output [31:0] mem_wdata,
|
||||||
output reg [ 3:0] mem_wstrb,
|
output [ 3:0] mem_wstrb,
|
||||||
input [31:0] mem_rdata,
|
input [31:0] mem_rdata,
|
||||||
|
|
||||||
// Look-Ahead Interface
|
// Look-Ahead Interface
|
||||||
output mem_la_read,
|
output mem_la_read,
|
||||||
output mem_la_write,
|
output mem_la_write,
|
||||||
output [31:0] mem_la_addr,
|
output reg [31:0] mem_la_addr,
|
||||||
output reg [31:0] mem_la_wdata,
|
output reg [31:0] mem_la_wdata,
|
||||||
output reg [ 3:0] mem_la_wstrb,
|
output reg [ 3:0] mem_la_wstrb,
|
||||||
|
|
||||||
|
@ -85,21 +83,90 @@ module picorv32 #(
|
||||||
|
|
||||||
reg [63:0] count_cycle, count_instr;
|
reg [63:0] count_cycle, count_instr;
|
||||||
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
||||||
reg [4:0] reg_sh;
|
wire [31:0] next_pc;
|
||||||
|
reg [ 4:0] reg_sh;
|
||||||
reg [31:0] next_insn_opcode;
|
|
||||||
|
|
||||||
assign pcpi_rs1 = reg_op1;
|
assign pcpi_rs1 = reg_op1;
|
||||||
assign pcpi_rs2 = reg_op2;
|
assign pcpi_rs2 = reg_op2;
|
||||||
|
|
||||||
wire [31:0] next_pc;
|
wire mem_xfer;
|
||||||
|
reg [31:0] mem_rdata_q;
|
||||||
|
|
||||||
task empty_statement;
|
reg [1:0] mem_wordsize;
|
||||||
// This task is used by the `assert directive in non-formal mode to
|
reg [31:0] mem_rdata_word;
|
||||||
// avoid empty statement (which are unsupported by plain Verilog syntax).
|
|
||||||
begin
|
assign mem_la_addr = (mem_do_prefetch || mem_do_r_inst) ? {next_pc[31:2], 2'b00} : {reg_op1[31:2], 2'b00};
|
||||||
|
|
||||||
|
wire [31:0] mem_rdata_latched;
|
||||||
|
assign mem_rdata_latched = mem_xfer ? mem_rdata : mem_rdata_q;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (mem_xfer) begin
|
||||||
|
mem_rdata_q <= mem_rdata;
|
||||||
end
|
end
|
||||||
endtask
|
end
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
(* full_case *)
|
||||||
|
case (mem_wordsize)
|
||||||
|
0: begin
|
||||||
|
mem_la_wdata = reg_op2;
|
||||||
|
mem_la_wstrb = 4'b1111;
|
||||||
|
mem_rdata_word = mem_rdata;
|
||||||
|
end
|
||||||
|
1: begin
|
||||||
|
mem_la_wdata = {2{reg_op2[15:0]}};
|
||||||
|
mem_la_wstrb = reg_op1[1] ? 4'b1100 : 4'b0011;
|
||||||
|
case (reg_op1[1])
|
||||||
|
1'b0: mem_rdata_word = {16'b0, mem_rdata[15:0]};
|
||||||
|
1'b1: mem_rdata_word = {16'b0, mem_rdata[31:16]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
mem_la_wdata = {4{reg_op2[7:0]}};
|
||||||
|
mem_la_wstrb = 4'b0001 << reg_op1[1:0];
|
||||||
|
case (reg_op1[1:0])
|
||||||
|
2'b00: mem_rdata_word = {24'b0, mem_rdata[7:0]};
|
||||||
|
2'b01: mem_rdata_word = {24'b0, mem_rdata[15:8]};
|
||||||
|
2'b10: mem_rdata_word = {24'b0, mem_rdata[23:16]};
|
||||||
|
2'b11: mem_rdata_word = {24'b0, mem_rdata[31:24]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
reg mem_do_prefetch;
|
||||||
|
reg mem_do_r_inst;
|
||||||
|
reg mem_do_rdata;
|
||||||
|
reg mem_do_wdata;
|
||||||
|
wire mem_done;
|
||||||
|
|
||||||
|
picorv32_memory memory (
|
||||||
|
.clk(clk),
|
||||||
|
.resetn(resetn),
|
||||||
|
.trap(trap),
|
||||||
|
|
||||||
|
.mem_valid(mem_valid),
|
||||||
|
.mem_ready(mem_ready),
|
||||||
|
.mem_xfer (mem_xfer),
|
||||||
|
|
||||||
|
.mem_addr (mem_addr),
|
||||||
|
.mem_wdata(mem_wdata),
|
||||||
|
.mem_wstrb(mem_wstrb),
|
||||||
|
.mem_rdata(mem_rdata),
|
||||||
|
|
||||||
|
.mem_la_read (mem_la_read),
|
||||||
|
.mem_la_write(mem_la_write),
|
||||||
|
.mem_la_addr (mem_la_addr),
|
||||||
|
.mem_la_wdata(mem_la_wdata),
|
||||||
|
.mem_la_wstrb(mem_la_wstrb),
|
||||||
|
|
||||||
|
.mem_do_prefetch(mem_do_prefetch),
|
||||||
|
.mem_do_r_inst(mem_do_r_inst),
|
||||||
|
.mem_do_rdata(mem_do_rdata),
|
||||||
|
.mem_do_wdata(mem_do_wdata),
|
||||||
|
.mem_done(mem_done)
|
||||||
|
);
|
||||||
|
|
||||||
// Internal PCPI Cores
|
// Internal PCPI Cores
|
||||||
|
|
||||||
|
@ -164,160 +231,6 @@ module picorv32 #(
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// Memory Interface
|
|
||||||
|
|
||||||
reg [1:0] mem_state;
|
|
||||||
reg [1:0] mem_wordsize;
|
|
||||||
reg [31:0] mem_rdata_word;
|
|
||||||
reg [31:0] mem_rdata_q;
|
|
||||||
reg mem_do_prefetch;
|
|
||||||
reg mem_do_r_inst;
|
|
||||||
reg mem_do_rdata;
|
|
||||||
reg mem_do_wdata;
|
|
||||||
|
|
||||||
wire mem_xfer;
|
|
||||||
reg last_mem_valid;
|
|
||||||
|
|
||||||
reg [15:0] mem_16bit_buffer;
|
|
||||||
|
|
||||||
wire [31:0] mem_rdata_latched_noshuffle;
|
|
||||||
wire [31:0] mem_rdata_latched;
|
|
||||||
|
|
||||||
assign mem_xfer = mem_valid && mem_ready;
|
|
||||||
|
|
||||||
wire mem_busy = |{mem_do_prefetch, mem_do_r_inst, mem_do_rdata, mem_do_wdata};
|
|
||||||
wire mem_done = resetn && ((mem_xfer && |mem_state && (mem_do_r_inst || mem_do_rdata || mem_do_wdata)) || (&mem_state && mem_do_r_inst));
|
|
||||||
|
|
||||||
assign mem_la_write = resetn && !mem_state && mem_do_wdata;
|
|
||||||
assign mem_la_read = resetn && ((!mem_state && (mem_do_r_inst || mem_do_prefetch || mem_do_rdata)));
|
|
||||||
assign mem_la_addr = (mem_do_prefetch || mem_do_r_inst) ? {next_pc[31:2], 2'b00} : {reg_op1[31:2], 2'b00};
|
|
||||||
|
|
||||||
assign mem_rdata_latched_noshuffle = mem_xfer ? mem_rdata : mem_rdata_q;
|
|
||||||
|
|
||||||
assign mem_rdata_latched = mem_rdata_latched_noshuffle;
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (!resetn) begin
|
|
||||||
last_mem_valid <= 0;
|
|
||||||
end else begin
|
|
||||||
if (!last_mem_valid) last_mem_valid <= mem_valid && !mem_ready;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @* begin
|
|
||||||
(* full_case *)
|
|
||||||
case (mem_wordsize)
|
|
||||||
0: begin
|
|
||||||
mem_la_wdata = reg_op2;
|
|
||||||
mem_la_wstrb = 4'b1111;
|
|
||||||
mem_rdata_word = mem_rdata;
|
|
||||||
end
|
|
||||||
1: begin
|
|
||||||
mem_la_wdata = {2{reg_op2[15:0]}};
|
|
||||||
mem_la_wstrb = reg_op1[1] ? 4'b1100 : 4'b0011;
|
|
||||||
case (reg_op1[1])
|
|
||||||
1'b0: mem_rdata_word = {16'b0, mem_rdata[15:0]};
|
|
||||||
1'b1: mem_rdata_word = {16'b0, mem_rdata[31:16]};
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
2: begin
|
|
||||||
mem_la_wdata = {4{reg_op2[7:0]}};
|
|
||||||
mem_la_wstrb = 4'b0001 << reg_op1[1:0];
|
|
||||||
case (reg_op1[1:0])
|
|
||||||
2'b00: mem_rdata_word = {24'b0, mem_rdata[7:0]};
|
|
||||||
2'b01: mem_rdata_word = {24'b0, mem_rdata[15:8]};
|
|
||||||
2'b10: mem_rdata_word = {24'b0, mem_rdata[23:16]};
|
|
||||||
2'b11: mem_rdata_word = {24'b0, mem_rdata[31:24]};
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (mem_xfer) begin
|
|
||||||
mem_rdata_q <= mem_rdata;
|
|
||||||
next_insn_opcode <= mem_rdata;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (resetn && !trap) begin
|
|
||||||
if (mem_do_prefetch || mem_do_r_inst || mem_do_rdata)
|
|
||||||
`assert(!mem_do_wdata);
|
|
||||||
|
|
||||||
if (mem_do_prefetch || mem_do_r_inst)
|
|
||||||
`assert(!mem_do_rdata);
|
|
||||||
|
|
||||||
if (mem_do_rdata)
|
|
||||||
`assert(!mem_do_prefetch && !mem_do_r_inst);
|
|
||||||
|
|
||||||
if (mem_do_wdata)
|
|
||||||
`assert(!(mem_do_prefetch || mem_do_r_inst || mem_do_rdata));
|
|
||||||
|
|
||||||
if (mem_state == 2 || mem_state == 3)
|
|
||||||
`assert(mem_valid || mem_do_prefetch);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (!resetn || trap) begin
|
|
||||||
if (!resetn) mem_state <= 0;
|
|
||||||
if (!resetn || mem_ready) mem_valid <= 0;
|
|
||||||
end else begin
|
|
||||||
if (mem_la_read || mem_la_write) begin
|
|
||||||
mem_addr <= mem_la_addr;
|
|
||||||
mem_wstrb <= mem_la_wstrb & {4{mem_la_write}};
|
|
||||||
end
|
|
||||||
if (mem_la_write) begin
|
|
||||||
mem_wdata <= mem_la_wdata;
|
|
||||||
end
|
|
||||||
case (mem_state)
|
|
||||||
0: begin
|
|
||||||
if (mem_do_prefetch || mem_do_r_inst || mem_do_rdata) begin
|
|
||||||
mem_valid <= 1;
|
|
||||||
mem_instr <= mem_do_prefetch || mem_do_r_inst;
|
|
||||||
mem_wstrb <= 0;
|
|
||||||
mem_state <= 1;
|
|
||||||
end
|
|
||||||
if (mem_do_wdata) begin
|
|
||||||
mem_valid <= 1;
|
|
||||||
mem_instr <= 0;
|
|
||||||
mem_state <= 2;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
1: begin
|
|
||||||
`assert(mem_wstrb == 0);
|
|
||||||
`assert(mem_do_prefetch || mem_do_r_inst || mem_do_rdata);
|
|
||||||
`assert(mem_valid == 1);
|
|
||||||
`assert(mem_instr == (mem_do_prefetch || mem_do_r_inst));
|
|
||||||
if (mem_xfer) begin
|
|
||||||
mem_valid <= 0;
|
|
||||||
mem_state <= mem_do_r_inst || mem_do_rdata ? 0 : 3;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
2: begin
|
|
||||||
`assert(mem_wstrb != 0);
|
|
||||||
`assert(mem_do_wdata);
|
|
||||||
if (mem_xfer) begin
|
|
||||||
mem_valid <= 0;
|
|
||||||
mem_state <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
3: begin
|
|
||||||
`assert(mem_wstrb == 0);
|
|
||||||
`assert(mem_do_prefetch);
|
|
||||||
if (mem_do_r_inst) begin
|
|
||||||
mem_state <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Memory Interface End
|
|
||||||
|
|
||||||
|
|
||||||
// Instruction Decoder
|
// Instruction Decoder
|
||||||
|
|
||||||
reg instr_lui, instr_auipc, instr_jal, instr_jalr;
|
reg instr_lui, instr_auipc, instr_jal, instr_jalr;
|
||||||
|
@ -459,8 +372,8 @@ module picorv32 #(
|
||||||
if (decoder_trigger_q) begin
|
if (decoder_trigger_q) begin
|
||||||
cached_ascii_instr <= new_ascii_instr;
|
cached_ascii_instr <= new_ascii_instr;
|
||||||
cached_insn_imm <= decoded_imm;
|
cached_insn_imm <= decoded_imm;
|
||||||
if (&next_insn_opcode[1:0]) cached_insn_opcode <= next_insn_opcode;
|
if (&mem_rdata_q[1:0]) cached_insn_opcode <= mem_rdata_q;
|
||||||
else cached_insn_opcode <= {16'b0, next_insn_opcode[15:0]};
|
else cached_insn_opcode <= {16'b0, mem_rdata_q[15:0]};
|
||||||
cached_insn_rs1 <= decoded_rs1;
|
cached_insn_rs1 <= decoded_rs1;
|
||||||
cached_insn_rs2 <= decoded_rs2;
|
cached_insn_rs2 <= decoded_rs2;
|
||||||
cached_insn_rd <= decoded_rd;
|
cached_insn_rd <= decoded_rd;
|
||||||
|
@ -489,8 +402,8 @@ module picorv32 #(
|
||||||
dbg_insn_rd = cached_insn_rd;
|
dbg_insn_rd = cached_insn_rd;
|
||||||
end else begin
|
end else begin
|
||||||
dbg_ascii_instr = new_ascii_instr;
|
dbg_ascii_instr = new_ascii_instr;
|
||||||
if (&next_insn_opcode[1:0]) dbg_insn_opcode = next_insn_opcode;
|
if (&mem_rdata_q[1:0]) dbg_insn_opcode = mem_rdata_q;
|
||||||
else dbg_insn_opcode = {16'b0, next_insn_opcode[15:0]};
|
else dbg_insn_opcode = {16'b0, mem_rdata_q[15:0]};
|
||||||
dbg_insn_imm = decoded_imm;
|
dbg_insn_imm = decoded_imm;
|
||||||
dbg_insn_rs1 = decoded_rs1;
|
dbg_insn_rs1 = decoded_rs1;
|
||||||
dbg_insn_rs2 = decoded_rs2;
|
dbg_insn_rs2 = decoded_rs2;
|
||||||
|
@ -1359,3 +1272,141 @@ module picorv32_pcpi_div (
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
/***************************************************************
|
||||||
|
* picorv32_memory
|
||||||
|
***************************************************************/
|
||||||
|
|
||||||
|
module picorv32_memory (
|
||||||
|
input clk,
|
||||||
|
input resetn,
|
||||||
|
input trap,
|
||||||
|
|
||||||
|
output reg mem_valid,
|
||||||
|
input mem_ready,
|
||||||
|
output reg mem_xfer,
|
||||||
|
|
||||||
|
output reg [31:0] mem_addr,
|
||||||
|
output reg [31:0] mem_wdata,
|
||||||
|
output reg [ 3:0] mem_wstrb,
|
||||||
|
input [31:0] mem_rdata,
|
||||||
|
|
||||||
|
// Look-Ahead Interface
|
||||||
|
output mem_la_read,
|
||||||
|
output mem_la_write,
|
||||||
|
input [31:0] mem_la_addr,
|
||||||
|
input [31:0] mem_la_wdata,
|
||||||
|
input [ 3:0] mem_la_wstrb,
|
||||||
|
|
||||||
|
|
||||||
|
input mem_do_prefetch,
|
||||||
|
input mem_do_r_inst,
|
||||||
|
input mem_do_rdata,
|
||||||
|
input mem_do_wdata,
|
||||||
|
output mem_done
|
||||||
|
);
|
||||||
|
|
||||||
|
task empty_statement;
|
||||||
|
// This task is used by the `assert directive in non-formal mode to
|
||||||
|
// avoid empty statement (which are unsupported by plain Verilog syntax).
|
||||||
|
begin
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
reg [1:0] mem_state;
|
||||||
|
reg last_mem_valid;
|
||||||
|
reg [15:0] mem_16bit_buffer;
|
||||||
|
|
||||||
|
reg mem_instr;
|
||||||
|
|
||||||
|
assign mem_xfer = mem_valid && mem_ready;
|
||||||
|
|
||||||
|
wire mem_busy = |{mem_do_prefetch, mem_do_r_inst, mem_do_rdata, mem_do_wdata};
|
||||||
|
assign mem_done = resetn && ((mem_xfer && |mem_state && (mem_do_r_inst || mem_do_rdata || mem_do_wdata)) || (&mem_state && mem_do_r_inst));
|
||||||
|
|
||||||
|
assign mem_la_write = resetn && !mem_state && mem_do_wdata;
|
||||||
|
assign mem_la_read = resetn && ((!mem_state && (mem_do_r_inst || mem_do_prefetch || mem_do_rdata)));
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (!resetn) begin
|
||||||
|
last_mem_valid <= 0;
|
||||||
|
end else begin
|
||||||
|
if (!last_mem_valid) last_mem_valid <= mem_valid && !mem_ready;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (resetn && !trap) begin
|
||||||
|
if (mem_do_prefetch || mem_do_r_inst || mem_do_rdata)
|
||||||
|
`assert(!mem_do_wdata);
|
||||||
|
|
||||||
|
if (mem_do_prefetch || mem_do_r_inst)
|
||||||
|
`assert(!mem_do_rdata);
|
||||||
|
|
||||||
|
if (mem_do_rdata)
|
||||||
|
`assert(!mem_do_prefetch && !mem_do_r_inst);
|
||||||
|
|
||||||
|
if (mem_do_wdata)
|
||||||
|
`assert(!(mem_do_prefetch || mem_do_r_inst || mem_do_rdata));
|
||||||
|
|
||||||
|
if (mem_state == 2 || mem_state == 3)
|
||||||
|
`assert(mem_valid || mem_do_prefetch);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (!resetn || trap) begin
|
||||||
|
if (!resetn) mem_state <= 0;
|
||||||
|
if (!resetn || mem_ready) mem_valid <= 0;
|
||||||
|
end else begin
|
||||||
|
if (mem_la_read || mem_la_write) begin
|
||||||
|
mem_addr <= mem_la_addr;
|
||||||
|
mem_wstrb <= mem_la_wstrb & {4{mem_la_write}};
|
||||||
|
end
|
||||||
|
if (mem_la_write) begin
|
||||||
|
mem_wdata <= mem_la_wdata;
|
||||||
|
end
|
||||||
|
case (mem_state)
|
||||||
|
0: begin
|
||||||
|
if (mem_do_prefetch || mem_do_r_inst || mem_do_rdata) begin
|
||||||
|
mem_valid <= 1;
|
||||||
|
mem_instr <= mem_do_prefetch || mem_do_r_inst;
|
||||||
|
mem_wstrb <= 0;
|
||||||
|
mem_state <= 1;
|
||||||
|
end
|
||||||
|
if (mem_do_wdata) begin
|
||||||
|
mem_valid <= 1;
|
||||||
|
mem_instr <= 0;
|
||||||
|
mem_state <= 2;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
1: begin
|
||||||
|
`assert(mem_wstrb == 0);
|
||||||
|
`assert(mem_do_prefetch || mem_do_r_inst || mem_do_rdata);
|
||||||
|
`assert(mem_valid == 1);
|
||||||
|
`assert(mem_instr == (mem_do_prefetch || mem_do_r_inst));
|
||||||
|
if (mem_xfer) begin
|
||||||
|
mem_valid <= 0;
|
||||||
|
mem_state <= mem_do_r_inst || mem_do_rdata ? 0 : 3;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
`assert(mem_wstrb != 0);
|
||||||
|
`assert(mem_do_wdata);
|
||||||
|
if (mem_xfer) begin
|
||||||
|
mem_valid <= 0;
|
||||||
|
mem_state <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
`assert(mem_wstrb == 0);
|
||||||
|
`assert(mem_do_prefetch);
|
||||||
|
if (mem_do_r_inst) begin
|
||||||
|
mem_state <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
|
@ -40,13 +40,13 @@ int main(int argc, char** argv, char** env) {
|
||||||
trace_fd = fopen("testbench.trace", "w");
|
trace_fd = fopen("testbench.trace", "w");
|
||||||
}
|
}
|
||||||
|
|
||||||
top->wb_clk = 0;
|
top->clk = 0;
|
||||||
top->wb_rst = 1;
|
top->rst = 1;
|
||||||
|
|
||||||
int t = 0;
|
int t = 0;
|
||||||
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
||||||
if (t > 200) top->wb_rst = 0;
|
if (t > 200) top->rst = 0;
|
||||||
top->wb_clk = !top->wb_clk;
|
top->clk = !top->clk;
|
||||||
top->eval();
|
top->eval();
|
||||||
if (tfp) tfp->dump(t);
|
if (tfp) tfp->dump(t);
|
||||||
t += 5;
|
t += 5;
|
||||||
|
|
|
@ -3,16 +3,15 @@
|
||||||
module picorv32_wrapper #(
|
module picorv32_wrapper #(
|
||||||
parameter VERBOSE = 0
|
parameter VERBOSE = 0
|
||||||
) (
|
) (
|
||||||
input wb_clk,
|
input clk,
|
||||||
input wb_rst,
|
input rst,
|
||||||
output trap,
|
output trap,
|
||||||
input [1024:0] hex_file
|
input [1024:0] hex_file
|
||||||
);
|
);
|
||||||
wire exit;
|
wire exit;
|
||||||
wire mem_instr;
|
|
||||||
|
|
||||||
reg [15:0] count_cycle = 0;
|
reg [15:0] count_cycle = 0;
|
||||||
always @(posedge wb_clk) count_cycle <= !wb_rst ? count_cycle + 1 : 0;
|
always @(posedge clk) count_cycle <= !rst ? count_cycle + 1 : 0;
|
||||||
|
|
||||||
wire [31:0] wb_m2s_adr;
|
wire [31:0] wb_m2s_adr;
|
||||||
wire [31:0] wb_m2s_dat;
|
wire [31:0] wb_m2s_dat;
|
||||||
|
@ -26,10 +25,9 @@ module picorv32_wrapper #(
|
||||||
picorv32_wb #() uut (
|
picorv32_wb #() uut (
|
||||||
.trap(trap),
|
.trap(trap),
|
||||||
.exit(exit),
|
.exit(exit),
|
||||||
.mem_instr(mem_instr),
|
|
||||||
|
|
||||||
.wb_clk_i(wb_clk),
|
.clk(clk),
|
||||||
.wb_rst_i(wb_rst)
|
.rst(rst)
|
||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
@ -38,9 +36,9 @@ module picorv32_wrapper #(
|
||||||
end
|
end
|
||||||
|
|
||||||
integer cycle_counter;
|
integer cycle_counter;
|
||||||
always @(posedge wb_clk) begin
|
always @(posedge clk) begin
|
||||||
cycle_counter <= !wb_rst ? cycle_counter + 1 : 0;
|
cycle_counter <= !rst ? cycle_counter + 1 : 0;
|
||||||
if (!wb_rst && trap) begin
|
if (!rst && trap) begin
|
||||||
$display("TRAP after %1d clock cycles", cycle_counter);
|
$display("TRAP after %1d clock cycles", cycle_counter);
|
||||||
if (exit) begin
|
if (exit) begin
|
||||||
$display("ALL TESTS PASSED.");
|
$display("ALL TESTS PASSED.");
|
||||||
|
@ -59,11 +57,8 @@ module picorv32_wb #(
|
||||||
output trap,
|
output trap,
|
||||||
output reg exit,
|
output reg exit,
|
||||||
|
|
||||||
// Wishbone interfaces
|
input rst,
|
||||||
input wb_rst_i,
|
input clk
|
||||||
input wb_clk_i,
|
|
||||||
|
|
||||||
output mem_instr
|
|
||||||
);
|
);
|
||||||
wire mem_valid;
|
wire mem_valid;
|
||||||
wire [31:0] mem_addr;
|
wire [31:0] mem_addr;
|
||||||
|
@ -84,12 +79,10 @@ module picorv32_wb #(
|
||||||
wire [31:0] dbg_insn_addr;
|
wire [31:0] dbg_insn_addr;
|
||||||
wire [63:0] dbg_ascii_instr;
|
wire [63:0] dbg_ascii_instr;
|
||||||
|
|
||||||
wire clk;
|
|
||||||
wire resetn;
|
wire resetn;
|
||||||
initial exit = 0;
|
initial exit = 0;
|
||||||
|
|
||||||
assign clk = wb_clk_i;
|
assign resetn = ~rst;
|
||||||
assign resetn = ~wb_rst_i;
|
|
||||||
|
|
||||||
picorv32 #(
|
picorv32 #(
|
||||||
.PROGADDR_RESET(32'h0001_0000),
|
.PROGADDR_RESET(32'h0001_0000),
|
||||||
|
@ -100,7 +93,6 @@ module picorv32_wb #(
|
||||||
.trap (trap),
|
.trap (trap),
|
||||||
|
|
||||||
.mem_valid (mem_valid),
|
.mem_valid (mem_valid),
|
||||||
.mem_instr (mem_instr),
|
|
||||||
.mem_ready (mem_ready),
|
.mem_ready (mem_ready),
|
||||||
.mem_addr (mem_addr),
|
.mem_addr (mem_addr),
|
||||||
.mem_wdata (mem_wdata),
|
.mem_wdata (mem_wdata),
|
||||||
|
|
Loading…
Reference in New Issue