|
@@ -47,31 +47,6 @@
|
|
|
`define assert(assert_expr) empty_statement
|
|
|
`endif
|
|
|
|
|
|
-// 32-bit left rotate
|
|
|
-function reg [31:0] rol32 (
|
|
|
- input [31:0] val,
|
|
|
- input [ 4:0] cnt
|
|
|
- );
|
|
|
- reg [63:0] val2;
|
|
|
-
|
|
|
- val2 = {val, val};
|
|
|
- val2 <<= cnt;
|
|
|
- rol32 = val2[63:32];
|
|
|
-endfunction // rol32
|
|
|
-
|
|
|
-// 32-bit right rotate
|
|
|
-function reg [31:0] ror32 (
|
|
|
- input [31:0] val,
|
|
|
- input [ 4:0] cnt
|
|
|
- );
|
|
|
-
|
|
|
- reg [63:0] val2;
|
|
|
-
|
|
|
- val2 = {val, val};
|
|
|
- val2 >>= cnt;
|
|
|
- ror32 = val2[31:0];
|
|
|
-endfunction // ror32
|
|
|
-
|
|
|
// uncomment this for register file in extra module
|
|
|
// `define PICORV32_REGS picorv32_regs
|
|
|
|
|
@@ -79,6 +54,7 @@ endfunction // ror32
|
|
|
// design are read in the correct order.
|
|
|
`define PICORV32_V
|
|
|
|
|
|
+
|
|
|
/***************************************************************
|
|
|
* picorv32
|
|
|
***************************************************************/
|
|
@@ -96,7 +72,6 @@ module picorv32 #(
|
|
|
parameter [ 0:0] COMPRESSED_ISA = 0,
|
|
|
parameter [ 0:0] CATCH_MISALIGN = 1,
|
|
|
parameter [ 0:0] CATCH_ILLINSN = 1,
|
|
|
- parameter [ 0:0] UNALIGNED_DATA = 0,
|
|
|
parameter [ 0:0] ENABLE_PCPI = 0,
|
|
|
parameter [ 0:0] ENABLE_MUL = 0,
|
|
|
parameter [ 0:0] ENABLE_FAST_MUL = 0,
|
|
@@ -112,47 +87,46 @@ module picorv32 #(
|
|
|
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010,
|
|
|
parameter [31:0] STACKADDR = 32'h ffff_ffff
|
|
|
) (
|
|
|
- input clk, resetn,
|
|
|
- output reg trap,
|
|
|
+ input clk, resetn,
|
|
|
+ output reg trap,
|
|
|
|
|
|
- output reg mem_instr,
|
|
|
- input mem_ready,
|
|
|
+ output reg mem_valid,
|
|
|
+ output reg mem_instr,
|
|
|
+ input mem_ready,
|
|
|
|
|
|
- output reg mem_read,
|
|
|
- output reg mem_write,
|
|
|
output reg [31:0] mem_addr,
|
|
|
output reg [31:0] mem_wdata,
|
|
|
- output reg [ 7:0] mem_be,
|
|
|
- input [31:0] mem_rdata,
|
|
|
+ output reg [ 3:0] mem_wstrb,
|
|
|
+ input [31:0] mem_rdata,
|
|
|
|
|
|
// Look-Ahead Interface
|
|
|
- output mem_la_read,
|
|
|
- output mem_la_write,
|
|
|
- output [31:0] mem_la_addr,
|
|
|
+ output mem_la_read,
|
|
|
+ output mem_la_write,
|
|
|
+ output [31:0] mem_la_addr,
|
|
|
output reg [31:0] mem_la_wdata,
|
|
|
- output reg [ 7:0] mem_la_be,
|
|
|
+ output reg [ 3:0] mem_la_wstrb,
|
|
|
|
|
|
// Pico Co-Processor Interface (PCPI)
|
|
|
- output reg pcpi_valid,
|
|
|
+ output reg pcpi_valid,
|
|
|
output reg [31:0] pcpi_insn,
|
|
|
- output [31:0] pcpi_rs1,
|
|
|
- output [31:0] pcpi_rs2,
|
|
|
- input pcpi_wr,
|
|
|
- input [31:0] pcpi_rd,
|
|
|
- input pcpi_wait,
|
|
|
- input pcpi_ready,
|
|
|
+ output [31:0] pcpi_rs1,
|
|
|
+ output [31:0] pcpi_rs2,
|
|
|
+ input pcpi_wr,
|
|
|
+ input [31:0] pcpi_rd,
|
|
|
+ input pcpi_wait,
|
|
|
+ input pcpi_ready,
|
|
|
|
|
|
// IRQ Interface
|
|
|
- input [31:0] irq,
|
|
|
+ input [31:0] irq,
|
|
|
output reg [31:0] eoi,
|
|
|
|
|
|
`ifdef RISCV_FORMAL
|
|
|
- output reg rvfi_valid,
|
|
|
+ output reg rvfi_valid,
|
|
|
output reg [63:0] rvfi_order,
|
|
|
output reg [31:0] rvfi_insn,
|
|
|
- output reg rvfi_trap,
|
|
|
- output reg rvfi_halt,
|
|
|
- output reg rvfi_intr,
|
|
|
+ output reg rvfi_trap,
|
|
|
+ output reg rvfi_halt,
|
|
|
+ output reg rvfi_intr,
|
|
|
output reg [ 1:0] rvfi_mode,
|
|
|
output reg [ 1:0] rvfi_ixl,
|
|
|
output reg [ 4:0] rvfi_rs1_addr,
|
|
@@ -181,7 +155,7 @@ module picorv32 #(
|
|
|
`endif
|
|
|
|
|
|
// Trace Interface
|
|
|
- output reg trace_valid,
|
|
|
+ output reg trace_valid,
|
|
|
output reg [35:0] trace_data
|
|
|
);
|
|
|
localparam integer irq_timer = 0;
|
|
@@ -198,8 +172,6 @@ module picorv32 #(
|
|
|
localparam [35:0] TRACE_ADDR = {4'b 0010, 32'b 0};
|
|
|
localparam [35:0] TRACE_IRQ = {4'b 1000, 32'b 0};
|
|
|
|
|
|
- localparam CATCH_MISALIGN_DATA = CATCH_MISALIGN && !UNALIGNED_DATA;
|
|
|
-
|
|
|
reg [63:0] count_cycle, count_instr;
|
|
|
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
|
|
reg [4:0] reg_sh;
|
|
@@ -213,7 +185,7 @@ module picorv32 #(
|
|
|
wire dbg_mem_ready = mem_ready;
|
|
|
wire [31:0] dbg_mem_addr = mem_addr;
|
|
|
wire [31:0] dbg_mem_wdata = mem_wdata;
|
|
|
- wire [ 3:0] dbg_mem_wstrb = {4{mem_write}} & (mem_be[3:0]|mem_be[7:4]);
|
|
|
+ wire [ 3:0] dbg_mem_wstrb = mem_wstrb;
|
|
|
wire [31:0] dbg_mem_rdata = mem_rdata;
|
|
|
|
|
|
assign pcpi_rs1 = reg_op1;
|
|
@@ -227,8 +199,6 @@ module picorv32 #(
|
|
|
reg [31:0] irq_pending;
|
|
|
reg [31:0] timer;
|
|
|
|
|
|
- wire mem_valid = mem_read | mem_write;
|
|
|
-
|
|
|
`ifndef PICORV32_REGS
|
|
|
reg [31:0] cpuregs [0:regfile_size-1];
|
|
|
|
|
@@ -409,7 +379,7 @@ module picorv32 #(
|
|
|
assign mem_la_write = resetn && !mem_state && mem_do_wdata;
|
|
|
assign mem_la_read = resetn && ((!mem_la_use_prefetched_high_word && !mem_state && (mem_do_rinst || mem_do_prefetch || mem_do_rdata)) ||
|
|
|
(COMPRESSED_ISA && mem_xfer && (!last_mem_valid ? mem_la_firstword : mem_la_firstword_reg) && !mem_la_secondword && &mem_rdata_latched[1:0]));
|
|
|
- assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + mem_la_firstword_xfer, mem_la_firstword, 1'b0} : reg_op1;
|
|
|
+ assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + mem_la_firstword_xfer, 2'b00} : {reg_op1[31:2], 2'b00};
|
|
|
|
|
|
assign mem_rdata_latched_noshuffle = (mem_xfer || LATCHED_MEM_RDATA) ? mem_rdata : mem_rdata_q;
|
|
|
|
|
@@ -428,22 +398,33 @@ module picorv32 #(
|
|
|
end
|
|
|
end
|
|
|
|
|
|
- // The effective low address of a memory reference, adjusted for size
|
|
|
- // unless UNALIGNED_DATA is supported.
|
|
|
- wire [1:0] mem_la_lowaddr;
|
|
|
-
|
|
|
always @* begin
|
|
|
- if (UNALIGNED_DATA)
|
|
|
- mem_la_lowaddr = mem_la_addr[1:0];
|
|
|
- else
|
|
|
- mem_la_lowaddr = mem_la_addr[1:0] & mem_wordsize;
|
|
|
-
|
|
|
- mem_la_be = { 4'b0000, {2{~mem_wordsize[1]}},
|
|
|
- ~mem_wordsize[0], 1'b1 }
|
|
|
- << mem_la_lowaddr;
|
|
|
-
|
|
|
- mem_la_wdata = rol32(reg_op2, mem_la_lowaddr << 3);
|
|
|
- mem_rdata_word = ror32(mem_rdata, mem_la_lowaddr << 3);
|
|
|
+ (* 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
|
|
@@ -586,49 +567,44 @@ module picorv32 #(
|
|
|
if (!resetn)
|
|
|
mem_state <= 0;
|
|
|
if (!resetn || mem_ready)
|
|
|
- begin
|
|
|
- mem_read <= 0;
|
|
|
- mem_write <= 0;
|
|
|
- end
|
|
|
+ mem_valid <= 0;
|
|
|
mem_la_secondword <= 0;
|
|
|
prefetched_high_word <= 0;
|
|
|
end else begin
|
|
|
if (mem_la_read || mem_la_write) begin
|
|
|
- mem_addr <= mem_la_addr;
|
|
|
- mem_be <= mem_la_be;
|
|
|
+ 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
|
|
|
- mem_write <= 0;
|
|
|
- mem_read <= 0;
|
|
|
if (mem_do_prefetch || mem_do_rinst || mem_do_rdata) begin
|
|
|
- mem_read <= !mem_la_use_prefetched_high_word;
|
|
|
+ mem_valid <= !mem_la_use_prefetched_high_word;
|
|
|
mem_instr <= mem_do_prefetch || mem_do_rinst;
|
|
|
+ mem_wstrb <= 0;
|
|
|
mem_state <= 1;
|
|
|
- mem_read <= 1;
|
|
|
end
|
|
|
if (mem_do_wdata) begin
|
|
|
+ mem_valid <= 1;
|
|
|
mem_instr <= 0;
|
|
|
mem_state <= 2;
|
|
|
- mem_write <= 1;
|
|
|
end
|
|
|
end
|
|
|
1: begin
|
|
|
- `assert(!mem_write);
|
|
|
+ `assert(mem_wstrb == 0);
|
|
|
`assert(mem_do_prefetch || mem_do_rinst || mem_do_rdata);
|
|
|
`assert(mem_valid == !mem_la_use_prefetched_high_word);
|
|
|
`assert(mem_instr == (mem_do_prefetch || mem_do_rinst));
|
|
|
if (mem_xfer) begin
|
|
|
if (COMPRESSED_ISA && mem_la_read) begin
|
|
|
- mem_read <= 1;
|
|
|
+ mem_valid <= 1;
|
|
|
mem_la_secondword <= 1;
|
|
|
if (!mem_la_use_prefetched_high_word)
|
|
|
mem_16bit_buffer <= mem_rdata[31:16];
|
|
|
end else begin
|
|
|
- mem_read <= 0;
|
|
|
+ mem_valid <= 0;
|
|
|
mem_la_secondword <= 0;
|
|
|
if (COMPRESSED_ISA && !mem_do_rdata) begin
|
|
|
if (~&mem_rdata[1:0] || mem_la_secondword) begin
|
|
@@ -643,16 +619,15 @@ module picorv32 #(
|
|
|
end
|
|
|
end
|
|
|
2: begin
|
|
|
- `assert(mem_write);
|
|
|
- `assert(!mem_read);
|
|
|
+ `assert(mem_wstrb != 0);
|
|
|
`assert(mem_do_wdata);
|
|
|
if (mem_xfer) begin
|
|
|
- mem_write <= 0;
|
|
|
+ mem_valid <= 0;
|
|
|
mem_state <= 0;
|
|
|
end
|
|
|
end
|
|
|
3: begin
|
|
|
- `assert(!mem_write);
|
|
|
+ `assert(mem_wstrb == 0);
|
|
|
`assert(mem_do_prefetch);
|
|
|
if (mem_do_rinst) begin
|
|
|
mem_state <= 0;
|
|
@@ -1690,7 +1665,7 @@ module picorv32 #(
|
|
|
latched_branch <= 1;
|
|
|
latched_store <= 1;
|
|
|
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
|
- reg_out <= CATCH_MISALIGN_DATA ? (cpuregs_rs1 & 32'h fffffffe) : cpuregs_rs1;
|
|
|
+ reg_out <= CATCH_MISALIGN ? (cpuregs_rs1 & 32'h fffffffe) : cpuregs_rs1;
|
|
|
dbg_rs1val <= cpuregs_rs1;
|
|
|
dbg_rs1val_valid <= 1;
|
|
|
cpu_state <= cpu_state_fetch;
|
|
@@ -1878,7 +1853,7 @@ module picorv32 #(
|
|
|
if (!mem_do_wdata) begin
|
|
|
(* parallel_case, full_case *)
|
|
|
case (1'b1)
|
|
|
- instr_sb: mem_wordsize <= 3;
|
|
|
+ instr_sb: mem_wordsize <= 2;
|
|
|
instr_sh: mem_wordsize <= 1;
|
|
|
instr_sw: mem_wordsize <= 0;
|
|
|
endcase
|
|
@@ -1903,13 +1878,13 @@ module picorv32 #(
|
|
|
if (!mem_do_rdata) begin
|
|
|
(* parallel_case, full_case *)
|
|
|
case (1'b1)
|
|
|
- instr_lb || instr_lbu: mem_wordsize <= 3;
|
|
|
+ instr_lb || instr_lbu: mem_wordsize <= 2;
|
|
|
instr_lh || instr_lhu: mem_wordsize <= 1;
|
|
|
instr_lw: mem_wordsize <= 0;
|
|
|
endcase
|
|
|
latched_is_lu <= is_lbu_lhu_lw;
|
|
|
- latched_is_lh <= instr_lh | instr_lhu;
|
|
|
- latched_is_lb <= instr_lb | instr_lbu;
|
|
|
+ latched_is_lh <= instr_lh;
|
|
|
+ latched_is_lb <= instr_lb;
|
|
|
if (ENABLE_TRACE) begin
|
|
|
trace_valid <= 1;
|
|
|
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
|
@@ -1918,13 +1893,11 @@ module picorv32 #(
|
|
|
set_mem_do_rdata = 1;
|
|
|
end
|
|
|
if (!mem_do_prefetch && mem_done) begin
|
|
|
- (* full_case *)
|
|
|
- case ( {latched_is_lu, latched_is_lh, latched_is_lb} )
|
|
|
- 3'b100: reg_out <= mem_rdata_word;
|
|
|
- 3'b010: reg_out <= $signed(mem_rdata_word[15:0]);
|
|
|
- 3'b110: reg_out <= {16'b0, mem_rdata_word[15:0]};
|
|
|
- 3'b001: reg_out <= $signed(mem_rdata_word[7:0]);
|
|
|
- 3'b101: reg_out <= {24'b0, mem_rdata_word[7:0]};
|
|
|
+ (* parallel_case, full_case *)
|
|
|
+ case (1'b1)
|
|
|
+ latched_is_lu: reg_out <= mem_rdata_word;
|
|
|
+ latched_is_lh: reg_out <= $signed(mem_rdata_word[15:0]);
|
|
|
+ latched_is_lb: reg_out <= $signed(mem_rdata_word[7:0]);
|
|
|
endcase
|
|
|
decoder_trigger <= 1;
|
|
|
decoder_pseudo_trigger <= 1;
|
|
@@ -1941,7 +1914,7 @@ module picorv32 #(
|
|
|
next_irq_pending[irq_timer] = 1;
|
|
|
end
|
|
|
|
|
|
- if (CATCH_MISALIGN_DATA && resetn && (mem_do_rdata || mem_do_wdata)) begin
|
|
|
+ if (CATCH_MISALIGN && resetn && (mem_do_rdata || mem_do_wdata)) begin
|
|
|
if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin
|
|
|
`debug($display("MISALIGNED WORD: 0x%08x", reg_op1);)
|
|
|
if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin
|