aboutsummaryrefslogtreecommitdiffstats
path: root/picorv32.v
diff options
context:
space:
mode:
Diffstat (limited to 'picorv32.v')
-rw-r--r--picorv32.v318
1 files changed, 173 insertions, 145 deletions
diff --git a/picorv32.v b/picorv32.v
index 9aba3c4..daf2226 100644
--- a/picorv32.v
+++ b/picorv32.v
@@ -639,26 +639,29 @@ module picorv32 #(
current_pc = reg_next_pc;
- if (latched_branch) begin
- current_pc = latched_store ? (latched_stalu ? reg_alu_out : reg_out) : reg_next_pc;
- `debug($display("ST_RD: %2d 0x%08x, BRANCH 0x%08x", latched_rd, reg_pc + 4, current_pc);)
- cpuregs[latched_rd] <= reg_pc + 4;
- end else
- if (latched_store) begin
- `debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? reg_alu_out : reg_out);)
- cpuregs[latched_rd] <= latched_stalu ? reg_alu_out : reg_out;
- end else
- if (ENABLE_IRQ && irq_state[0]) begin
- cpuregs[latched_rd] <= current_pc;
- current_pc = PROGADDR_IRQ;
- irq_active <= 1;
- mem_do_rinst <= 1;
- end else
- if (ENABLE_IRQ && irq_state[1]) begin
- eoi <= irq_pending & ~irq_mask;
- cpuregs[latched_rd] <= irq_pending & ~irq_mask;
- next_irq_pending = next_irq_pending & irq_mask;
- end
+ (* parallel_case *)
+ case (1'b1)
+ latched_branch: begin
+ current_pc = latched_store ? (latched_stalu ? reg_alu_out : reg_out) : reg_next_pc;
+ `debug($display("ST_RD: %2d 0x%08x, BRANCH 0x%08x", latched_rd, reg_pc + 4, current_pc);)
+ cpuregs[latched_rd] <= reg_pc + 4;
+ end
+ latched_store && !latched_branch: begin
+ `debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? reg_alu_out : reg_out);)
+ cpuregs[latched_rd] <= latched_stalu ? reg_alu_out : reg_out;
+ end
+ ENABLE_IRQ && irq_state[0]: begin
+ cpuregs[latched_rd] <= current_pc;
+ current_pc = PROGADDR_IRQ;
+ irq_active <= 1;
+ mem_do_rinst <= 1;
+ end
+ ENABLE_IRQ && irq_state[1]: begin
+ eoi <= irq_pending & ~irq_mask;
+ cpuregs[latched_rd] <= irq_pending & ~irq_mask;
+ next_irq_pending = next_irq_pending & irq_mask;
+ end
+ endcase
reg_pc <= current_pc;
reg_next_pc <= current_pc;
@@ -711,153 +714,178 @@ module picorv32 #(
reg_op1 <= 'bx;
reg_op2 <= 'bx;
`debug($display("DECODE: 0x%08x %-0s", reg_pc, instruction ? instruction : "UNKNOWN");)
- if ((CATCH_ILLINSN || WITH_PCPI) && instr_trap) begin
- if (WITH_PCPI) begin
- reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
- if (ENABLE_REGS_DUALPORT) begin
- pcpi_valid <= 1;
- reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
- reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
- if (pcpi_int_ready) begin
- mem_do_rinst <= 1;
- pcpi_valid <= 0;
- reg_out <= pcpi_int_rd;
- latched_store <= pcpi_int_wr;
- cpu_state <= cpu_state_fetch;
- end else
- if (CATCH_ILLINSN && pcpi_timeout) begin
- `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
- if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
- next_irq_pending[irq_sbreak] = 1;
+
+ (* parallel_case *)
+ case (1'b1)
+ (CATCH_ILLINSN || WITH_PCPI) && instr_trap: begin
+ if (WITH_PCPI) begin
+ reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
+ if (ENABLE_REGS_DUALPORT) begin
+ pcpi_valid <= 1;
+ reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
+ reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
+ if (pcpi_int_ready) begin
+ mem_do_rinst <= 1;
+ pcpi_valid <= 0;
+ reg_out <= pcpi_int_rd;
+ latched_store <= pcpi_int_wr;
cpu_state <= cpu_state_fetch;
end else
- cpu_state <= cpu_state_trap;
+ if (CATCH_ILLINSN && pcpi_timeout) begin
+ `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
+ if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
+ next_irq_pending[irq_sbreak] = 1;
+ cpu_state <= cpu_state_fetch;
+ end else
+ cpu_state <= cpu_state_trap;
+ end
+ end else begin
+ cpu_state <= cpu_state_ld_rs2;
end
end else begin
- cpu_state <= cpu_state_ld_rs2;
+ `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
+ if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
+ next_irq_pending[irq_sbreak] = 1;
+ cpu_state <= cpu_state_fetch;
+ end else
+ cpu_state <= cpu_state_trap;
end
- end else begin
- `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
- if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
- next_irq_pending[irq_sbreak] = 1;
- cpu_state <= cpu_state_fetch;
- end else
- cpu_state <= cpu_state_trap;
end
- end else
- if (is_rdcycle_rdcycleh_rdinstr_rdinstrh) begin
- (* parallel_case, full_case *)
- case (1'b1)
- instr_rdcycle:
- reg_out <= count_cycle[31:0];
- instr_rdcycleh:
- reg_out <= count_cycle[63:32];
- instr_rdinstr:
- reg_out <= count_instr[31:0];
- instr_rdinstrh:
- reg_out <= count_instr[63:32];
- endcase
- latched_store <= 1;
- cpu_state <= cpu_state_fetch;
- end else
- if (is_lui_auipc_jal) begin
- reg_op1 <= instr_lui ? 0 : reg_pc;
- reg_op2 <= decoded_imm;
- mem_do_rinst <= mem_do_prefetch;
- cpu_state <= cpu_state_exec;
- end else
- if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_getq) begin
- reg_out <= cpuregs[decoded_rs1];
- latched_store <= 1;
- cpu_state <= cpu_state_fetch;
- end else
- if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_setq) begin
- reg_out <= cpuregs[decoded_rs1];
- latched_rd <= latched_rd | irqregs_offset;
- latched_store <= 1;
- cpu_state <= cpu_state_fetch;
- end else
- if (ENABLE_IRQ && instr_retirq) begin
- eoi <= 0;
- irq_active <= 0;
- latched_branch <= 1;
- latched_store <= 1;
- reg_out <= cpuregs[decoded_rs1];
- cpu_state <= cpu_state_fetch;
- end else
- if (ENABLE_IRQ && instr_maskirq) begin
- latched_store <= 1;
- reg_out <= irq_mask;
- irq_mask <= (decoded_rs1 ? cpuregs[decoded_rs1] : 0) | MASKED_IRQ;
- cpu_state <= cpu_state_fetch;
- end else
- if (ENABLE_IRQ && ENABLE_IRQ_TIMER && instr_timer) begin
- latched_store <= 1;
- reg_out <= timer;
- timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
- cpu_state <= cpu_state_fetch;
- end else begin
- `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);)
- reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
- if (is_lb_lh_lw_lbu_lhu) begin
+ ENABLE_COUNTERS && is_rdcycle_rdcycleh_rdinstr_rdinstrh: begin
+ (* parallel_case, full_case *)
+ case (1'b1)
+ instr_rdcycle:
+ reg_out <= count_cycle[31:0];
+ instr_rdcycleh:
+ reg_out <= count_cycle[63:32];
+ instr_rdinstr:
+ reg_out <= count_instr[31:0];
+ instr_rdinstrh:
+ reg_out <= count_instr[63:32];
+ endcase
+ latched_store <= 1;
+ cpu_state <= cpu_state_fetch;
+ end
+ is_lui_auipc_jal: begin
+ reg_op1 <= instr_lui ? 0 : reg_pc;
+ reg_op2 <= decoded_imm;
+ mem_do_rinst <= mem_do_prefetch;
+ cpu_state <= cpu_state_exec;
+ end
+ ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_getq: begin
+ reg_out <= cpuregs[decoded_rs1];
+ latched_store <= 1;
+ cpu_state <= cpu_state_fetch;
+ end
+ ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_setq: begin
+ reg_out <= cpuregs[decoded_rs1];
+ latched_rd <= latched_rd | irqregs_offset;
+ latched_store <= 1;
+ cpu_state <= cpu_state_fetch;
+ end
+ ENABLE_IRQ && instr_retirq: begin
+ eoi <= 0;
+ irq_active <= 0;
+ latched_branch <= 1;
+ latched_store <= 1;
+ reg_out <= cpuregs[decoded_rs1];
+ cpu_state <= cpu_state_fetch;
+ end
+ ENABLE_IRQ && instr_maskirq: begin
+ latched_store <= 1;
+ reg_out <= irq_mask;
+ irq_mask <= (decoded_rs1 ? cpuregs[decoded_rs1] : 0) | MASKED_IRQ;
+ cpu_state <= cpu_state_fetch;
+ end
+ ENABLE_IRQ && ENABLE_IRQ_TIMER && instr_timer: begin
+ latched_store <= 1;
+ reg_out <= timer;
+ timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
+ cpu_state <= cpu_state_fetch;
+ end
+ is_lb_lh_lw_lbu_lhu: begin
+ `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);)
+ reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
cpu_state <= cpu_state_ldmem;
mem_do_rinst <= 1;
- end else if (is_slli_srli_srai) begin
+ end
+ is_slli_srli_srai: begin
+ `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);)
+ reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
reg_sh <= decoded_rs2;
cpu_state <= cpu_state_shift;
- end else if (is_jalr_addi_slti_sltiu_xori_ori_andi) begin
+ end
+ is_jalr_addi_slti_sltiu_xori_ori_andi: begin
+ `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);)
+ reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
reg_op2 <= decoded_imm;
mem_do_rinst <= mem_do_prefetch;
cpu_state <= cpu_state_exec;
- end else if (ENABLE_REGS_DUALPORT) begin
- `debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, decoded_rs2 ? cpuregs[decoded_rs2] : 0);)
- reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
- reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
- if (is_sb_sh_sw) begin
- cpu_state <= cpu_state_stmem;
- mem_do_rinst <= 1;
- end else if (is_sll_srl_sra) begin
- cpu_state <= cpu_state_shift;
- end else begin
- mem_do_rinst <= mem_do_prefetch;
- cpu_state <= cpu_state_exec;
- end
- end else
- cpu_state <= cpu_state_ld_rs2;
- end
+ end
+ default: begin
+ `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);)
+ reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
+ if (ENABLE_REGS_DUALPORT) begin
+ `debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, decoded_rs2 ? cpuregs[decoded_rs2] : 0);)
+ reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
+ reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
+ (* parallel_case *)
+ case (1'b1)
+ is_sb_sh_sw: begin
+ cpu_state <= cpu_state_stmem;
+ mem_do_rinst <= 1;
+ end
+ is_sll_srl_sra: begin
+ cpu_state <= cpu_state_shift;
+ end
+ default: begin
+ mem_do_rinst <= mem_do_prefetch;
+ cpu_state <= cpu_state_exec;
+ end
+ endcase
+ end else
+ cpu_state <= cpu_state_ld_rs2;
+ end
+ endcase
end
cpu_state_ld_rs2: begin
`debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, decoded_rs2 ? cpuregs[decoded_rs2] : 0);)
reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
- if (WITH_PCPI && instr_trap) begin
- pcpi_valid <= 1;
- if (pcpi_int_ready) begin
- mem_do_rinst <= 1;
- pcpi_valid <= 0;
- reg_out <= pcpi_int_rd;
- latched_store <= pcpi_int_wr;
- cpu_state <= cpu_state_fetch;
- end else
- if (CATCH_ILLINSN && pcpi_timeout) begin
- `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
- if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
- next_irq_pending[irq_sbreak] = 1;
+
+ (* parallel_case *)
+ case (1'b1)
+ WITH_PCPI && instr_trap: begin
+ pcpi_valid <= 1;
+ if (pcpi_int_ready) begin
+ mem_do_rinst <= 1;
+ pcpi_valid <= 0;
+ reg_out <= pcpi_int_rd;
+ latched_store <= pcpi_int_wr;
cpu_state <= cpu_state_fetch;
end else
- cpu_state <= cpu_state_trap;
+ if (CATCH_ILLINSN && pcpi_timeout) begin
+ `debug($display("SBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
+ if (ENABLE_IRQ && !irq_mask[irq_sbreak] && !irq_active) begin
+ next_irq_pending[irq_sbreak] = 1;
+ cpu_state <= cpu_state_fetch;
+ end else
+ cpu_state <= cpu_state_trap;
+ end
end
- end else
- if (is_sb_sh_sw) begin
- cpu_state <= cpu_state_stmem;
- mem_do_rinst <= 1;
- end else if (is_sll_srl_sra) begin
- cpu_state <= cpu_state_shift;
- end else begin
- mem_do_rinst <= mem_do_prefetch;
- cpu_state <= cpu_state_exec;
- end
+ is_sb_sh_sw: begin
+ cpu_state <= cpu_state_stmem;
+ mem_do_rinst <= 1;
+ end
+ is_sll_srl_sra: begin
+ cpu_state <= cpu_state_shift;
+ end
+ default: begin
+ mem_do_rinst <= mem_do_prefetch;
+ cpu_state <= cpu_state_exec;
+ end
+ endcase
end
cpu_state_exec: begin