aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--firmware/firmware.h2
-rw-r--r--firmware/irq.c17
-rw-r--r--firmware/multest.c24
-rw-r--r--firmware/print.c4
-rw-r--r--firmware/sieve.c2
-rw-r--r--picorv32.v332
-rw-r--r--testbench.v4
8 files changed, 346 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 690418b..5ded656 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ FIRMWARE_OBJS = firmware/start.o firmware/irq.o firmware/print.o firmware/sieve.
GCC_WARNS = -Werror -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings
GCC_WARNS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes -pedantic # -Wconversion
TOOLCHAIN_PREFIX = riscv32-unknown-elf-
+# COMPRESSED_ISA = C
test: testbench.exe firmware/firmware.hex
vvp -N testbench.exe
@@ -33,15 +34,15 @@ test_synth: testbench_synth.exe firmware/firmware.hex
vvp -N testbench_synth.exe
testbench.exe: testbench.v picorv32.v
- iverilog -o testbench.exe testbench.v picorv32.v
+ iverilog -o testbench.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) testbench.v picorv32.v
chmod -x testbench.exe
testbench_sp.exe: testbench.v picorv32.v
- iverilog -o testbench_sp.exe -DSP_TEST testbench.v picorv32.v
+ iverilog -o testbench_sp.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) -DSP_TEST testbench.v picorv32.v
chmod -x testbench_sp.exe
testbench_axi.exe: testbench.v picorv32.v
- iverilog -o testbench_axi.exe -DAXI_TEST testbench.v picorv32.v
+ iverilog -o testbench_axi.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) -DAXI_TEST testbench.v picorv32.v
chmod -x testbench_axi.exe
testbench_synth.exe: testbench.v synth.v
@@ -65,10 +66,10 @@ firmware/firmware.elf: $(FIRMWARE_OBJS) $(TEST_OBJS) firmware/sections.lds
chmod -x $@
firmware/start.o: firmware/start.S
- $(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32IMXcustom -o $@ $<
+ $(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32IM$(COMPRESSED_ISA)Xcustom -o $@ $<
firmware/%.o: firmware/%.c
- $(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32I -Os --std=c99 $(GCC_WARNS) -ffreestanding -nostdlib -o $@ $<
+ $(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32I$(COMPRESSED_ISA) -Os --std=c99 $(GCC_WARNS) -ffreestanding -nostdlib -o $@ $<
tests/%.o: tests/%.S tests/riscv_test.h tests/test_macros.h
$(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32IM -o $@ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
diff --git a/firmware/firmware.h b/firmware/firmware.h
index ce5e321..59b5c75 100644
--- a/firmware/firmware.h
+++ b/firmware/firmware.h
@@ -18,7 +18,7 @@ uint32_t *irq(uint32_t *regs, uint32_t irqs);
void print_chr(char ch);
void print_str(const char *p);
void print_dec(unsigned int val);
-void print_hex(unsigned int val);
+void print_hex(unsigned int val, int digits);
// sieve.c
void sieve(void);
diff --git a/firmware/irq.c b/firmware/irq.c
index e67b16d..a387524 100644
--- a/firmware/irq.c
+++ b/firmware/irq.c
@@ -31,30 +31,31 @@ uint32_t *irq(uint32_t *regs, uint32_t irqs)
if ((irqs & 6) != 0)
{
uint32_t pc = regs[0] - 4;
- uint32_t instr = *(uint32_t*)pc;
+ uint16_t *instr_hwords = (uint16_t*)pc;
+ uint32_t instr = instr_hwords[0] | (instr_hwords[1] << 16);
print_str("\n");
print_str("------------------------------------------------------------\n");
if ((irqs & 2) != 0) {
- if (instr == 0x00100073) {
+ if (instr == 0x00100073 || (instr & 0xffff) == 9002) {
print_str("SBREAK instruction at 0x");
- print_hex(pc);
+ print_hex(pc, 8);
print_str("\n");
} else {
print_str("Illegal Instruction at 0x");
- print_hex(pc);
+ print_hex(pc, 8);
print_str(": 0x");
- print_hex(instr);
+ print_hex(instr, ((instr & 3) == 3) ? 8 : 4);
print_str("\n");
}
}
if ((irqs & 4) != 0) {
print_str("Bus error in Instruction at 0x");
- print_hex(pc);
+ print_hex(pc, 8);
print_str(": 0x");
- print_hex(instr);
+ print_hex(instr, ((instr & 3) == 3) ? 8 : 4);
print_str("\n");
}
@@ -90,7 +91,7 @@ uint32_t *irq(uint32_t *regs, uint32_t irqs)
print_chr(' ');
}
- print_hex(regs[r]);
+ print_hex(regs[r], 8);
print_str(k == 3 ? "\n" : " ");
}
diff --git a/firmware/multest.c b/firmware/multest.c
index 37ecf32..5b68555 100644
--- a/firmware/multest.c
+++ b/firmware/multest.c
@@ -26,51 +26,51 @@ void multest(void)
int64_t as = (int32_t)a, bs = (int32_t)b;
print_str("input [");
- print_hex(as >> 32);
+ print_hex(as >> 32, 8);
print_str("] ");
- print_hex(a);
+ print_hex(a, 8);
print_str(" [");
- print_hex(bs >> 32);
+ print_hex(bs >> 32, 8);
print_str("] ");
- print_hex(b);
+ print_hex(b, 8);
print_chr('\n');
uint32_t h_mul, h_mulh, h_mulhsu, h_mulhu;
print_str("hard ");
h_mul = hard_mul(a, b);
- print_hex(h_mul);
+ print_hex(h_mul, 8);
print_str(" ");
h_mulh = hard_mulh(a, b);
- print_hex(h_mulh);
+ print_hex(h_mulh, 8);
print_str(" ");
h_mulhsu = hard_mulhsu(a, b);
- print_hex(h_mulhsu);
+ print_hex(h_mulhsu, 8);
print_str(" ");
h_mulhu = hard_mulhu(a, b);
- print_hex(h_mulhu);
+ print_hex(h_mulhu, 8);
print_chr('\n');
uint32_t s_mul, s_mulh, s_mulhsu, s_mulhu;
print_str("soft ");
s_mul = a * b;
- print_hex(s_mul);
+ print_hex(s_mul, 8);
print_str(" ");
s_mulh = (as * bs) >> 32;
- print_hex(s_mulh);
+ print_hex(s_mulh, 8);
print_str(" ");
s_mulhsu = (as * bu) >> 32;
- print_hex(s_mulhsu);
+ print_hex(s_mulhsu, 8);
print_str(" ");
s_mulhu = (au * bu) >> 32;
- print_hex(s_mulhu);
+ print_hex(s_mulhu, 8);
print_str(" ");
if (s_mul != h_mul || s_mulh != h_mulh || s_mulhsu != h_mulhsu || s_mulhu != h_mulhu) {
diff --git a/firmware/print.c b/firmware/print.c
index a3000f5..accce26 100644
--- a/firmware/print.c
+++ b/firmware/print.c
@@ -33,9 +33,9 @@ void print_dec(unsigned int val)
}
}
-void print_hex(unsigned int val)
+void print_hex(unsigned int val, int digits)
{
- for (int i = 32-4; i >= 0; i -= 4)
+ for (int i = (4*digits)-4; i >= 0; i -= 4)
*((volatile uint32_t*)OUTPORT) = "0123456789ABCDEF"[(val >> i) % 16];
}
diff --git a/firmware/sieve.c b/firmware/sieve.c
index f3350c6..c31e942 100644
--- a/firmware/sieve.c
+++ b/firmware/sieve.c
@@ -72,7 +72,7 @@ void sieve(void)
}
print_str("checksum: ");
- print_hex(hash);
+ print_hex(hash, 8);
if (hash == 0x1772A48F) {
print_str(" OK\n");
diff --git a/picorv32.v b/picorv32.v
index fd1740d..8a6dbbb 100644
--- a/picorv32.v
+++ b/picorv32.v
@@ -45,6 +45,7 @@ module picorv32 #(
parameter [ 0:0] TWO_STAGE_SHIFT = 1,
parameter [ 0:0] TWO_CYCLE_COMPARE = 0,
parameter [ 0:0] TWO_CYCLE_ALU = 0,
+ parameter [ 0:0] COMPRESSED_ISA = 0,
parameter [ 0:0] CATCH_MISALIGN = 1,
parameter [ 0:0] CATCH_ILLINSN = 1,
parameter [ 0:0] ENABLE_PCPI = 0,
@@ -105,6 +106,9 @@ module picorv32 #(
reg [31:0] cpuregs [0:regfile_size-1];
reg [4:0] reg_sh;
+ reg [31:0] current_insn;
+ reg [31:0] current_insn_addr;
+
assign pcpi_rs1 = reg_op1;
assign pcpi_rs2 = reg_op2;
@@ -179,15 +183,22 @@ module picorv32 #(
reg mem_do_rdata;
reg mem_do_wdata;
+ reg mem_la_secondword;
+ wire mem_la_firstword = COMPRESSED_ISA && (mem_do_prefetch || mem_do_rinst) && next_pc[1] && !mem_la_secondword;
+ reg [15:0] mem_16bit_buffer;
+
wire mem_busy = |{mem_do_prefetch, mem_do_rinst, mem_do_rdata, mem_do_wdata};
- wire mem_done = resetn && ((mem_ready && |mem_state && (mem_do_rinst || mem_do_rdata || mem_do_wdata)) || (&mem_state && mem_do_rinst));
+ wire mem_done = resetn && ((mem_ready && |mem_state && (mem_do_rinst || mem_do_rdata || mem_do_wdata)) || (&mem_state && mem_do_rinst)) && !mem_la_firstword;
assign mem_la_write = resetn && !mem_state && mem_do_wdata;
- assign mem_la_read = resetn && !mem_state && (mem_do_rinst || mem_do_prefetch || mem_do_rdata);
- assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? next_pc : {reg_op1[31:2], 2'b00};
+ assign mem_la_read = resetn && ((!mem_state && (mem_do_rinst || mem_do_prefetch || mem_do_rdata)) || (mem_ready && mem_la_firstword && !mem_la_secondword));
+ assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + (mem_ready && mem_la_firstword), 2'b00} : {reg_op1[31:2], 2'b00};
+
+ wire [31:0] mem_rdata_latched_noshuffle;
+ assign mem_rdata_latched_noshuffle = ((mem_valid && mem_ready) || LATCHED_MEM_RDATA) ? mem_rdata : mem_rdata_q;
wire [31:0] mem_rdata_latched;
- assign mem_rdata_latched = ((mem_valid && mem_ready) || LATCHED_MEM_RDATA) ? mem_rdata : mem_rdata_q;
+ assign mem_rdata_latched = COMPRESSED_ISA && mem_la_secondword ? {mem_rdata_latched_noshuffle[15:0], mem_16bit_buffer} : mem_rdata_latched_noshuffle;
always @* begin
(* full_case *)
@@ -219,19 +230,133 @@ module picorv32 #(
end
always @(posedge clk) begin
- if (mem_valid && mem_ready)
- mem_rdata_q <= mem_rdata_latched;
+ if (mem_valid && mem_ready) begin
+ mem_rdata_q <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata;
+ end
+
+ if (COMPRESSED_ISA && mem_done && (mem_do_prefetch || mem_do_rinst)) begin
+ case (mem_rdata_latched[1:0])
+ 2'b00: begin // Quadrant 0
+ case (mem_rdata_latched[15:13])
+ 3'b000: begin // C.ADDI4SPN
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= {mem_rdata_latched[10:7], mem_rdata_latched[12:11], mem_rdata_latched[5], mem_rdata_latched[6]};
+ end
+ 3'b010: begin // C.LW
+ mem_rdata_q[31:20] <= {mem_rdata_latched[5], mem_rdata_latched[12:10], mem_rdata_latched[6], 2'b00};
+ mem_rdata_q[14:12] <= 3'b 010;
+ end
+ 3'b 110: begin // C.SW
+ {mem_rdata_q[31:25], mem_rdata_q[11:7]} <= {mem_rdata_latched[5], mem_rdata_latched[12:10], mem_rdata_latched[6], 2'b00};
+ mem_rdata_q[14:12] <= 3'b 010;
+ end
+ endcase
+ end
+ 2'b01: begin // Quadrant 1
+ case (mem_rdata_latched[15:13])
+ 3'b 000: begin // C.ADDI
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]});
+ end
+ 3'b 010: begin // C.LI
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]});
+ end
+ 3'b 011: begin
+ if (mem_rdata_latched[11:7] == 2) begin // C.ADDI16SP
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[4:3],
+ mem_rdata_latched[5], mem_rdata_latched[2], mem_rdata_latched[6], 4'b 0000});
+ end else begin // C.LUI
+ mem_rdata_q[31:12] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]});
+ end
+ end
+ 3'b100: begin
+ if (mem_rdata_latched[11:10] == 2'b00) begin // C.SRLI
+ mem_rdata_q[31:25] <= 7'b0000000;
+ mem_rdata_q[14:12] <= 3'b 101;
+ end
+ if (mem_rdata_latched[11:10] == 2'b00) begin // C.SRAI
+ mem_rdata_q[31:25] <= 7'b0100000;
+ mem_rdata_q[14:12] <= 3'b 101;
+ end
+ if (mem_rdata_latched[11:10] == 2'b10) begin // C.ANDI
+ mem_rdata_q[14:12] <= 3'b111;
+ mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]});
+ end
+ if (mem_rdata_latched[12:10] == 3'b011) begin // C.SUB, C.XOR, C.OR, C.AND
+ if (mem_rdata_latched[6:5] == 2'b00) mem_rdata_q[14:12] <= 3'b000;
+ if (mem_rdata_latched[6:5] == 2'b01) mem_rdata_q[14:12] <= 3'b100;
+ if (mem_rdata_latched[6:5] == 2'b10) mem_rdata_q[14:12] <= 3'b110;
+ if (mem_rdata_latched[6:5] == 2'b11) mem_rdata_q[14:12] <= 3'b111;
+ mem_rdata_q[31:25] <= mem_rdata_latched[6:5] == 2'b00 ? 7'b0100000 : 7'b0000000;
+ end
+ end
+ 3'b 110: begin // C.BEQZ
+ mem_rdata_q[14:12] <= 3'b000;
+ { mem_rdata_q[31], mem_rdata_q[7], mem_rdata_q[30:25], mem_rdata_q[11:8] } <=
+ $signed({mem_rdata_latched[12], mem_rdata_latched[6:5], mem_rdata_latched[2],
+ mem_rdata_latched[11:10], mem_rdata_latched[4:3]});
+ end
+ 3'b 111: begin // C.BNEZ
+ mem_rdata_q[14:12] <= 3'b001;
+ { mem_rdata_q[31], mem_rdata_q[7], mem_rdata_q[30:25], mem_rdata_q[11:8] } <=
+ $signed({mem_rdata_latched[12], mem_rdata_latched[6:5], mem_rdata_latched[2],
+ mem_rdata_latched[11:10], mem_rdata_latched[4:3]});
+ end
+ endcase
+ end
+ 2'b10: begin // Quadrant 2
+ case (mem_rdata_latched[15:13])
+ 3'b000: begin // C.SLLI
+ mem_rdata_q[31:25] <= 7'b0000000;
+ mem_rdata_q[14:12] <= 3'b 001;
+ end
+ 3'b010: begin // C.LWSP
+ mem_rdata_q[31:20] <= {mem_rdata_latched[3:2], mem_rdata_latched[12], mem_rdata_latched[6:4], 2'b00};
+ mem_rdata_q[14:12] <= 3'b 010;
+ end
+ 3'b100: begin
+ if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] == 0) begin // C.JR
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= 12'b0;
+ end
+ if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] != 0) begin // C.MV
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:25] <= 7'b0000000;
+ end
+ if (mem_rdata_latched[12] != 0 && mem_rdata_latched[11:7] != 0 && mem_rdata_latched[6:2] == 0) begin // C.JALR
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:20] <= 12'b0;
+ end
+ if (mem_rdata_latched[12] != 0 && mem_rdata_latched[6:2] != 0) begin // C.ADD
+ mem_rdata_q[14:12] <= 3'b000;
+ mem_rdata_q[31:25] <= 7'b0000000;
+ end
+ end
+ 3'b110: begin // C.SWSP
+ {mem_rdata_q[31:25], mem_rdata_q[11:7]} <= {mem_rdata_latched[8:7], mem_rdata_latched[12:9], 2'b00};
+ mem_rdata_q[14:12] <= 3'b 010;
+ end
+ endcase
+ end
+ endcase
+ end
end
always @(posedge clk) begin
if (!resetn) begin
mem_state <= 0;
mem_valid <= 0;
+ mem_la_secondword <= 0;
end else case (mem_state)
0: begin
mem_addr <= mem_la_addr;
mem_wdata <= mem_la_wdata;
mem_wstrb <= mem_la_wstrb & {4{mem_la_write}};
+ if (mem_do_prefetch || mem_do_rinst) begin
+ current_insn_addr <= next_pc;
+ end
if (mem_do_prefetch || mem_do_rinst || mem_do_rdata) begin
mem_valid <= 1;
mem_instr <= mem_do_prefetch || mem_do_rinst;
@@ -246,8 +371,15 @@ module picorv32 #(
end
1: begin
if (mem_ready) begin
- mem_valid <= 0;
- mem_state <= mem_do_rinst || mem_do_rdata ? 0 : 3;
+ if (COMPRESSED_ISA && mem_la_firstword && !mem_la_secondword) begin
+ mem_addr <= mem_la_addr;
+ mem_la_secondword <= 1;
+ mem_16bit_buffer <= mem_rdata[31:16];
+ end else begin
+ mem_valid <= 0;
+ mem_la_secondword <= 0;
+ mem_state <= mem_do_rinst || mem_do_rdata ? 0 : 3;
+ end
end
end
2: begin
@@ -281,6 +413,8 @@ module picorv32 #(
reg decoder_trigger;
reg decoder_trigger_q;
reg decoder_pseudo_trigger;
+ reg decoder_pseudo_trigger_q;
+ reg compressed_instr;
reg is_lui_auipc_jal;
reg is_lb_lh_lw_lbu_lhu;
@@ -313,6 +447,7 @@ module picorv32 #(
always @(posedge clk) begin
new_ascii_instr = "";
+
if (instr_lui) new_ascii_instr = "lui";
if (instr_auipc) new_ascii_instr = "auipc";
if (instr_jal) new_ascii_instr = "jal";
@@ -367,8 +502,15 @@ module picorv32 #(
if (instr_waitirq) new_ascii_instr = "waitirq";
if (instr_timer) new_ascii_instr = "timer";
- if (decoder_trigger_q)
+ if (decoder_trigger_q && !decoder_pseudo_trigger_q) begin
ascii_instr <= new_ascii_instr;
+`ifdef DEBUG
+ if (&current_insn[1:0])
+ $display("DECODE: 0x%08x 0x%08x %-0s", current_insn_addr, current_insn, new_ascii_instr ? new_ascii_instr : "UNKNOWN");
+ else
+ $display("DECODE: 0x%08x 0x%04x %-0s", current_insn_addr, current_insn[15:0], new_ascii_instr ? new_ascii_instr : "UNKNOWN");
+`endif
+ end
end
always @(posedge clk) begin
@@ -380,6 +522,8 @@ module picorv32 #(
is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu};
if (mem_do_rinst && mem_done) begin
+ current_insn <= mem_rdata_latched;
+
instr_lui <= mem_rdata_latched[6:0] == 7'b0110111;
instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111;
instr_jal <= mem_rdata_latched[6:0] == 7'b1101111;
@@ -404,6 +548,144 @@ module picorv32 #(
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ)
decoded_rs1 <= ENABLE_IRQ_QREGS ? irqregs_offset : 3; // instr_retirq
+
+ compressed_instr <= 0;
+ if (COMPRESSED_ISA && mem_rdata_latched[1:0] != 2'b11) begin
+ compressed_instr <= 1;
+ decoded_rd <= 0;
+ decoded_rs1 <= 0;
+ decoded_rs2 <= 0;
+
+ { decoded_imm_uj[31:11], decoded_imm_uj[4], decoded_imm_uj[9:8], decoded_imm_uj[10], decoded_imm_uj[6],
+ decoded_imm_uj[7], decoded_imm_uj[3:1], decoded_imm_uj[5], decoded_imm_uj[0] } <= $signed({mem_rdata_latched[12:2], 1'b0});
+
+ case (mem_rdata_latched[1:0])
+ 2'b00: begin // Quadrant 0
+ case (mem_rdata_latched[15:13])
+ 3'b000: begin // C.ADDI4SPN
+ is_alu_reg_imm <= |mem_rdata_latched[12:5];
+ decoded_rs1 <= 2;
+ decoded_rd <= 8 + mem_rdata_latched[9:7];
+ end
+ 3'b010: begin // C.LW
+ is_lb_lh_lw_lbu_lhu <= 1;
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rd <= 8 + mem_rdata_latched[4:2];
+ end
+ 3'b110: begin // C.SW
+ is_sb_sh_sw <= 1;
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rs2 <= 8 + mem_rdata_latched[4:2];
+ end
+ endcase
+ end
+ 2'b01: begin // Quadrant 1
+ case (mem_rdata_latched[15:13])
+ 3'b000: begin // C.NOP / C.ADDI
+ is_alu_reg_imm <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ end
+ 3'b001: begin // C.JAL
+ instr_jal <= 1;
+ decoded_rd <= 1;
+ end
+ 3'b 010: begin // C.LI
+ is_alu_reg_imm <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= 0;
+ end
+ 3'b 011: begin
+ if (mem_rdata_latched[11:7] == 2) begin // C.ADDI16SP
+ is_alu_reg_imm <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ end else begin // C.LUI
+ instr_lui <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= 0;
+ end
+ end
+ 3'b100: begin
+ if (mem_rdata_latched[11] == 1'b0) begin // C.SRLI, C.SRAI
+ is_alu_reg_imm <= 1;
+ decoded_rd <= 8 + mem_rdata_latched[9:7];
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rs2 <= {mem_rdata_latched[12], mem_rdata_latched[6:2]};
+ end
+ if (mem_rdata_latched[11:10] == 2'b10) begin // C.ANDI
+ is_alu_reg_imm <= 1;
+ decoded_rd <= 8 + mem_rdata_latched[9:7];
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ end
+ if (mem_rdata_latched[12:10] == 3'b011) begin // C.SUB, C.XOR, C.OR, C.AND
+ is_alu_reg_reg <= 1;
+ decoded_rd <= 8 + mem_rdata_latched[9:7];
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rs2 <= 8 + mem_rdata_latched[4:2];
+ end
+ end
+ 3'b101: begin // C.J
+ instr_jal <= 1;
+ end
+ 3'b110: begin // C.BEQZ
+ is_beq_bne_blt_bge_bltu_bgeu <= 1;
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rs2 <= 0;
+ end
+ 3'b111: begin // C.BNEZ
+ is_beq_bne_blt_bge_bltu_bgeu <= 1;
+ decoded_rs1 <= 8 + mem_rdata_latched[9:7];
+ decoded_rs2 <= 0;
+ end
+ endcase
+ end
+ 2'b10: begin // Quadrant 2
+ case (mem_rdata_latched[15:13])
+ 3'b000: begin // C.SLLI
+ is_alu_reg_imm <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ decoded_rs2 <= {mem_rdata_latched[12], mem_rdata_latched[6:2]};
+ end
+ 3'b010: begin // C.LWSP
+ is_lb_lh_lw_lbu_lhu <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= 2;
+ end
+ 3'b100: begin
+ if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] == 0) begin // C.JR
+ instr_jalr <= 1;
+ decoded_rd <= 0;
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ end
+ if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] != 0) begin // C.MV
+ is_alu_reg_reg <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= 0;
+ decoded_rs2 <= mem_rdata_latched[6:2];
+ end
+ if (mem_rdata_latched[12] != 0 && mem_rdata_latched[11:7] != 0 && mem_rdata_latched[6:2] == 0) begin // C.JALR
+ instr_jalr <= 1;
+ decoded_rd <= 1;
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ end
+ if (mem_rdata_latched[12] != 0 && mem_rdata_latched[6:2] != 0) begin // C.ADD
+ is_alu_reg_reg <= 1;
+ decoded_rd <= mem_rdata_latched[11:7];
+ decoded_rs1 <= mem_rdata_latched[11:7];
+ decoded_rs2 <= mem_rdata_latched[6:2];
+ end
+ end
+ 3'b110: begin // C.SWSP
+ is_sb_sh_sw <= 1;
+ decoded_rs1 <= 2;
+ decoded_rs2 <= mem_rdata_latched[6:2];
+ end
+ endcase
+ end
+ endcase
+ end
end
if (decoder_trigger && !decoder_pseudo_trigger) begin
@@ -535,6 +817,7 @@ module picorv32 #(
reg latched_store;
reg latched_stalu;
reg latched_branch;
+ reg latched_compr;
reg latched_is_lu;
reg latched_is_lh;
reg latched_is_lb;
@@ -644,9 +927,10 @@ module picorv32 #(
next_irq_pending = next_irq_pending | irq;
end
- decoder_trigger_q <= decoder_trigger;
decoder_trigger <= mem_do_rinst && mem_done;
+ decoder_trigger_q <= decoder_trigger;
decoder_pseudo_trigger <= 0;
+ decoder_pseudo_trigger_q <= decoder_pseudo_trigger;
do_waitirq <= 0;
if (!resetn) begin
@@ -686,8 +970,8 @@ module picorv32 #(
case (1'b1)
latched_branch: begin
current_pc = latched_store ? (latched_stalu ? alu_out_q : 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;
+ `debug($display("ST_RD: %2d 0x%08x, BRANCH 0x%08x", latched_rd, reg_pc + (latched_compr ? 2 : 4), current_pc);)
+ cpuregs[latched_rd] <= reg_pc + (latched_compr ? 2 : 4);
end
latched_store && !latched_branch: begin
`debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? alu_out_q : reg_out);)
@@ -716,6 +1000,7 @@ module picorv32 #(
latched_is_lh <= 0;
latched_is_lb <= 0;
latched_rd <= decoded_rd;
+ latched_compr <= compressed_instr;
if (ENABLE_IRQ && ((decoder_trigger && !irq_active && |(irq_pending & ~irq_mask)) || irq_state)) begin
irq_state <=
@@ -730,18 +1015,17 @@ module picorv32 #(
if (irq_pending) begin
latched_store <= 1;
reg_out <= irq_pending;
- reg_next_pc <= current_pc + 4;
+ reg_next_pc <= current_pc + (compressed_instr ? 2 : 4);
mem_do_rinst <= 1;
end else
do_waitirq <= 1;
end else
if (decoder_trigger) begin
`debug($display("-- %-0t", $time);)
- reg_next_pc <= current_pc + 4;
+ reg_next_pc <= current_pc + (compressed_instr ? 2 : 4);
if (ENABLE_COUNTERS)
count_instr <= count_instr + 1;
if (instr_jal) begin
- `debug($display("DECODE: 0x%08x jal", current_pc);)
mem_do_rinst <= 1;
reg_next_pc <= current_pc + decoded_imm_uj;
latched_branch <= 1;
@@ -756,7 +1040,6 @@ module picorv32 #(
cpu_state_ld_rs1: begin
reg_op1 <= 'bx;
reg_op2 <= 'bx;
- `debug($display("DECODE: 0x%08x %-0s", reg_pc, ascii_instr ? ascii_instr : "UNKNOWN");)
(* parallel_case *)
case (1'b1)
@@ -1068,7 +1351,7 @@ module picorv32 #(
cpu_state <= cpu_state_trap;
end
end
- if (CATCH_MISALIGN && resetn && mem_do_rinst && reg_pc[1:0] != 0) begin
+ if (CATCH_MISALIGN && resetn && mem_do_rinst && (COMPRESSED_ISA ? reg_pc[0] : |reg_pc[1:0])) begin
`debug($display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);)
if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin
next_irq_pending[irq_buserror] = 1;
@@ -1092,8 +1375,13 @@ module picorv32 #(
irq_pending <= next_irq_pending & ~MASKED_IRQ;
- reg_pc[1:0] <= 0;
- reg_next_pc[1:0] <= 0;
+ if (COMPRESSED_ISA) begin
+ reg_pc[0] <= 0;
+ reg_next_pc[0] <= 0;
+ end else begin
+ reg_pc[1:0] <= 0;
+ reg_next_pc[1:0] <= 0;
+ end
current_pc = 'bx;
end
@@ -1271,6 +1559,7 @@ module picorv32_axi #(
parameter [ 0:0] TWO_STAGE_SHIFT = 1,
parameter [ 0:0] TWO_CYCLE_COMPARE = 0,
parameter [ 0:0] TWO_CYCLE_ALU = 0,
+ parameter [ 0:0] COMPRESSED_ISA = 0,
parameter [ 0:0] CATCH_MISALIGN = 1,
parameter [ 0:0] CATCH_ILLINSN = 1,
parameter [ 0:0] ENABLE_PCPI = 0,
@@ -1368,6 +1657,7 @@ module picorv32_axi #(
.TWO_STAGE_SHIFT (TWO_STAGE_SHIFT ),
.TWO_CYCLE_COMPARE (TWO_CYCLE_COMPARE ),
.TWO_CYCLE_ALU (TWO_CYCLE_ALU ),
+ .COMPRESSED_ISA (COMPRESSED_ISA ),
.CATCH_MISALIGN (CATCH_MISALIGN ),
.CATCH_ILLINSN (CATCH_ILLINSN ),
.ENABLE_PCPI (ENABLE_PCPI ),
@@ -1451,6 +1741,7 @@ module picorv32_axi_adapter (
reg ack_awvalid;
reg ack_arvalid;
reg ack_wvalid;
+ reg xfer_done;
assign mem_axi_awvalid = mem_valid && |mem_wstrb && !ack_awvalid;
assign mem_axi_awaddr = mem_addr;
@@ -1473,13 +1764,14 @@ module picorv32_axi_adapter (
if (!resetn) begin
ack_awvalid <= 0;
end else begin
+ xfer_done <= mem_valid && mem_ready;
if (mem_axi_awready && mem_axi_awvalid)
ack_awvalid <= 1;
if (mem_axi_arready && mem_axi_arvalid)
ack_arvalid <= 1;
if (mem_axi_wready && mem_axi_wvalid)
ack_wvalid <= 1;
- if (!mem_valid) begin
+ if (xfer_done || !mem_valid) begin
ack_awvalid <= 0;
ack_arvalid <= 0;
ack_wvalid <= 0;
diff --git a/testbench.v b/testbench.v
index 4703f3a..c23f6b3 100644
--- a/testbench.v
+++ b/testbench.v
@@ -7,7 +7,6 @@
`timescale 1 ns / 1 ps
// `define VERBOSE
-// `define AXI_TEST
module testbench;
@@ -55,6 +54,9 @@ module testbench;
`ifdef SP_TEST
.ENABLE_REGS_DUALPORT(0),
`endif
+`ifdef COMPRESSED_ISA
+ .COMPRESSED_ISA(1),
+`endif
.ENABLE_MUL(1),
.ENABLE_IRQ(1)
) uut (