Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
013606a
new start
vogma Sep 2, 2025
3d9c27a
zcmp simulation
vogma Sep 2, 2025
5335103
added fsm for micro ops
vogma Sep 2, 2025
35fad9a
work
vogma Sep 2, 2025
d85e6f3
simulation
vogma Sep 4, 2025
0f83962
added cm.push example program
vogma Sep 4, 2025
1a05018
working cm.push simulation
vogma Sep 4, 2025
efa7bcd
working cm.push simulation. bug fixed
vogma Sep 5, 2025
b87e99a
Merge branch 'stnolting:main' into zcmp_extension
vogma Sep 7, 2025
5c19950
modified control unit. Not working
vogma Sep 7, 2025
1666e05
cm.push working(?). more tests needed
vogma Sep 8, 2025
08bfdb5
working cm.push on fpga
vogma Sep 8, 2025
d0ed3b3
zcmp functionality in generate
vogma Sep 8, 2025
3b05450
added test code
vogma Sep 9, 2025
67d2d23
renamed test file
vogma Sep 9, 2025
d24ac33
added cm.push support
vogma Sep 9, 2025
fc2bcd5
fixed cm.pop bug
vogma Sep 11, 2025
9f198cf
added necessary instruction signals for popret and popretz
vogma Sep 18, 2025
0bcf277
fixed bug in cm.pop
vogma Sep 23, 2025
b5331bb
software tests
vogma Sep 24, 2025
6571170
ls
vogma Sep 24, 2025
5801d83
Merge branch 'main' into zcmp_extension
vogma Sep 24, 2025
bef4ee4
frontend old
vogma Sep 24, 2025
04ed917
zcmp back
vogma Sep 24, 2025
86779d8
removed redundancy in control. Added popret support
vogma Sep 24, 2025
b314ee9
popretz working
vogma Sep 25, 2025
88fd990
double move implemented
vogma Sep 25, 2025
97c2a21
almost working
vogma Oct 3, 2025
ef45182
commit
vogma Oct 3, 2025
41da15d
fixed bug
vogma Oct 3, 2025
64a609f
fixed bug
vogma Oct 5, 2025
bc300d9
added test harness for zcmp
vogma Oct 6, 2025
77ae569
added push detection to decompressor
vogma Oct 6, 2025
476a5ea
fixed bugs in zcmp implementation
vogma Oct 6, 2025
d9ac737
Merge branch 'main' into zcmp_extension
vogma Oct 7, 2025
25ebfde
added cm.push tests
vogma Oct 7, 2025
995ad31
added double move test
vogma Oct 7, 2025
a8cffef
added a0 printout
vogma Oct 7, 2025
acaf33c
added mvsa01 test
vogma Oct 7, 2025
d3c0c3f
added self checking test for mvsa01
vogma Oct 7, 2025
86e0ce9
removed old tests
vogma Oct 7, 2025
093cea0
self checking tb for mvsa01
vogma Oct 7, 2025
22bfcc7
added push self checking tb
vogma Oct 7, 2025
4265e26
added pop self checking tests
vogma Oct 7, 2025
a3846ad
zcmp working, all tests passing
vogma Oct 12, 2025
185eccb
refined implementation. VHDL-2008 req removed
vogma Oct 13, 2025
944bbb9
test bench
vogma Oct 13, 2025
771816f
:Merge branch 'main' into zcmp_extension
vogma Oct 13, 2025
3074c88
refactoring
vogma Oct 13, 2025
6dbe4c0
if_bus_t modified
vogma Oct 13, 2025
64cee61
Merge branch 'stnolting:main' into zcmp_extension
vogma Oct 17, 2025
3b99cd6
Merge branch 'main' into zcmp_extension
vogma Oct 20, 2025
dc6954e
refactoring, comments
vogma Oct 20, 2025
9f86502
removed unnecessary modifications
vogma Oct 22, 2025
96cd40b
removed unused signal
vogma Oct 22, 2025
31f999d
Merge branch 'main' into zcmp_extension
vogma Oct 29, 2025
578019e
Merge branch 'main' into zcmp_extension
vogma Nov 3, 2025
c8773b0
fixed bug in double moves.
vogma Nov 8, 2025
da485eb
Merge branch 'main' into zcmp_extension
vogma Nov 9, 2025
c52a701
Merge branch 'main' into zcmp_extension
vogma Nov 30, 2025
c960292
fix
vogma Nov 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions rtl/core/neorv32_cpu.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ entity neorv32_cpu is
RISCV_ISA_U : boolean; -- user mode extension
RISCV_ISA_Zaamo : boolean; -- atomic read-modify-write operations extension
RISCV_ISA_Zalrsc : boolean; -- atomic reservation-set operations extension
RISCV_ISA_Zcb : boolean; -- additional code size reduction instructions
RISCV_ISA_Zcmp : boolean; -- implement additional code size reduction instructions
RISCV_ISA_Zba : boolean; -- shifted-add bit-manipulation extension
RISCV_ISA_Zbb : boolean; -- basic bit-manipulation extension
RISCV_ISA_Zbkb : boolean; -- bit-manipulation instructions for cryptography
RISCV_ISA_Zbkc : boolean; -- carry-less multiplication instructions
RISCV_ISA_Zbkx : boolean; -- cryptography crossbar permutation extension
RISCV_ISA_Zbs : boolean; -- single-bit bit-manipulation extension
RISCV_ISA_Zcb : boolean; -- additional code size reduction instructions
RISCV_ISA_Zfinx : boolean; -- 32-bit floating-point extension
RISCV_ISA_Zibi : boolean; -- branch with immediate
RISCV_ISA_Zicntr : boolean; -- base counters
Expand Down Expand Up @@ -101,6 +102,7 @@ architecture neorv32_cpu_rtl of neorv32_cpu is
constant riscv_a_c : boolean := RISCV_ISA_Zaamo and RISCV_ISA_Zalrsc; -- A: atomic memory operations
constant riscv_b_c : boolean := RISCV_ISA_Zba and RISCV_ISA_Zbb and RISCV_ISA_Zbs; -- B: bit manipulation
constant riscv_zcb_c : boolean := RISCV_ISA_C and RISCV_ISA_Zcb; -- Zcb: additional compressed instructions
constant riscv_zcmp_c : boolean := RISCV_ISA_C and RISCV_ISA_Zcmp; -- Zcmp: additional compressed instructions
constant riscv_zkt_c : boolean := CPU_FAST_SHIFT_EN; -- Zkt: data-independent execution time for cryptography operations
constant riscv_zkn_c : boolean := RISCV_ISA_Zbkb and RISCV_ISA_Zbkc and RISCV_ISA_Zbkx and
RISCV_ISA_Zkne and RISCV_ISA_Zknd and RISCV_ISA_Zknh; -- Zkn: NIST suite
Expand Down Expand Up @@ -151,8 +153,9 @@ begin
cond_sel_string_f(true, "x", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zaamo, "_zaamo", "" ) &
cond_sel_string_f(RISCV_ISA_Zalrsc, "_zalrsc", "" ) &
cond_sel_string_f(RISCV_ISA_C, "_zca", "" ) & -- Zcb requires Zca (=C) in the ISA string
cond_sel_string_f(riscv_zcb_c, "_zcb", "" ) &
cond_sel_string_f(RISCV_ISA_C, "_zca", "" ) &
cond_sel_string_f(riscv_zcb_c, "_zcb", "" ) & -- Zcb requires Zca (=C) in the ISA string
cond_sel_string_f(riscv_zcmp_c, "_zcmp", "" ) & -- Zcb requires Zca (=C) in the ISA string
cond_sel_string_f(RISCV_ISA_Zba, "_zba", "" ) &
cond_sel_string_f(RISCV_ISA_Zbb, "_zbb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkb, "_zbkb", "" ) &
Expand Down Expand Up @@ -199,7 +202,8 @@ begin
neorv32_cpu_frontend_inst: entity neorv32.neorv32_cpu_frontend
generic map (
RISCV_C => RISCV_ISA_C, -- implement C ISA extension
RISCV_ZCB => RISCV_ISA_Zcb -- implement Zcb ISA sub-extension
RISCV_ZCB => riscv_zcb_c, -- implement Zcb ISA sub-extension
RISCV_ZCMP => riscv_zcmp_c -- implement Zcmp ISA sub-extension
)
port map (
-- global control --
Expand Down Expand Up @@ -236,7 +240,8 @@ begin
RISCV_ISA_U => RISCV_ISA_U, -- user mode extension
RISCV_ISA_Zaamo => RISCV_ISA_Zaamo, -- atomic read-modify-write operations extension
RISCV_ISA_Zalrsc => RISCV_ISA_Zalrsc, -- atomic reservation-set operations extension
RISCV_ISA_Zcb => riscv_zcb_c, -- additional code size reduction instructions
RISCV_ISA_Zcb => riscv_zcb_c, -- additional code size reduction instructions (Zcb)
RISCV_ISA_Zcmp => riscv_zcmp_c, -- implement additional code size reduction instructions (Zcmp)
RISCV_ISA_Zba => RISCV_ISA_Zba, -- shifted-add bit-manipulation extension
RISCV_ISA_Zbb => RISCV_ISA_Zbb, -- basic bit-manipulation extension
RISCV_ISA_Zbkb => RISCV_ISA_Zbkb, -- bit-manipulation instructions for cryptography
Expand Down
83 changes: 75 additions & 8 deletions rtl/core/neorv32_cpu_control.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ entity neorv32_cpu_control is
RISCV_ISA_Zaamo : boolean; -- atomic read-modify-write extension
RISCV_ISA_Zalrsc : boolean; -- atomic reservation-set operations extension
RISCV_ISA_Zcb : boolean; -- additional code size reduction instructions
RISCV_ISA_Zcmp : boolean; -- implement additional code size reduction instructions
RISCV_ISA_Zba : boolean; -- shifted-add bit-manipulation extension
RISCV_ISA_Zbb : boolean; -- basic bit-manipulation extension
RISCV_ISA_Zbkb : boolean; -- bit-manipulation instructions for cryptography
Expand Down Expand Up @@ -197,6 +198,9 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
signal cnt_event : std_ulogic_vector(11 downto 0); -- counter events
signal ebreak_trig : std_ulogic; -- environment break exception trigger

signal zcmp_event, zcmp_event_nxt, zcmp_event_reset : std_ulogic;
signal zcmp_pc, zcmp_pc_nxt : std_ulogic_vector(31 downto 0);

begin

-- ****************************************************************************************************************************
Expand Down Expand Up @@ -276,15 +280,14 @@ begin

-- Execute Engine FSM (Micro Sequencer) Comb ----------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(exe_engine, debug_ctrl, trap_ctrl, hwtrig_i, opcode, frontend_i,
execute_engine_fsm_comb: process(exe_engine,frontend_i, debug_ctrl, zcmp_pc, zcmp_event, trap_ctrl, hwtrig_i, opcode, frontend_i,
csr, ctrl, alu_cp_done_i, lsu_wait_i, alu_add_i, branch_taken)
variable funct3_v : std_ulogic_vector(2 downto 0);
variable funct7_v : std_ulogic_vector(6 downto 0);
begin
-- shortcuts --
funct3_v := exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
funct7_v := exe_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c);

-- arbiter defaults --
exe_engine_nxt.state <= exe_engine.state;
exe_engine_nxt.ir <= exe_engine.ir;
Expand Down Expand Up @@ -355,14 +358,21 @@ begin
ctrl_nxt.alu_opa_mux <= '1'; -- prepare update of next PC in EX_EXECUTE (opa = current PC)
ctrl_nxt.alu_opb_mux <= '1'; -- prepare update of next PC in EX_EXECUTE (opb = imm = +2/4)
--
if (trap_ctrl.env_pending = '1') or (trap_ctrl.exc_fire = '1') then -- pending trap or pending exception (fast)
if (((trap_ctrl.env_pending = '1') or (trap_ctrl.exc_fire = '1')) and (frontend_i.zcmp_atomic_tail='0')) then -- pending trap or pending exception (fast), only taken when zcmp not in atomic section
exe_engine_nxt.state <= EX_TRAP_ENTER;
elsif (frontend_i.valid = '1') and (hwtrig_i = '0') then -- new instruction word available and no pending HW trigger
trap_ctrl.instr_be <= frontend_i.fault; -- access fault during instruction fetch
exe_engine_nxt.ci <= frontend_i.compr; -- this is a de-compressed instruction
exe_engine_nxt.ir <= frontend_i.instr; -- instruction word


if(frontend_i.zcmp_in_uop_seq = '1' and zcmp_event = '0') then -- currently executing zcmp uop instructions?
exe_engine_nxt.pc <= zcmp_pc; -- hold program counter at zcmp instruction
else -- normal instruction dispatch
exe_engine_nxt.pc <= exe_engine.pc2(XLEN-1 downto 1) & '0'; -- PC <= next PC
exe_engine_nxt.state <= EX_EXECUTE; -- start executing new instruction
end if;

exe_engine_nxt.state <= EX_EXECUTE; -- start executing new instruction
end if;

when EX_TRAP_ENTER => -- enter trap environment and jump to trap vector
Expand Down Expand Up @@ -391,8 +401,13 @@ begin

when EX_EXECUTE => -- decode and prepare execution (FSM will be here for exactly 1 cycle in any case)
-- ------------------------------------------------------------
exe_engine_nxt.pc2 <= alu_add_i(XLEN-1 downto 1) & '0'; -- next PC = PC + immediate

if(frontend_i.zcmp_in_uop_seq = '1') then -- currently executing zcmp uop instruction?
exe_engine_nxt.pc2 <= std_ulogic_vector(unsigned(zcmp_pc)+2);
else -- normal instruction execution
exe_engine_nxt.pc2 <= alu_add_i(XLEN-1 downto 1) & '0'; -- next PC = PC + immediate
end if;

-- decode instruction class/type; [NOTE] register file is read in THIS stage; due to the sync read data will be available in the NEXT state --
case opcode is

Expand Down Expand Up @@ -558,7 +573,6 @@ begin
end case;
end process execute_engine_fsm_comb;


-- CPU Control Bus Output -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- instruction fetch --
Expand Down Expand Up @@ -613,11 +627,65 @@ begin
ctrl_o.cpu_debug <= debug_ctrl.run;


zcmp_enabled:
if RISCV_ISA_Zcmp generate

-- ****************************************************************************************************************************
-- Zcmp micro op detection
-- ****************************************************************************************************************************

-- single bit register saves the zcmp_start signal from the frontend
zcmp_event_sync : process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
zcmp_event <= '0';
elsif rising_edge(clk_i) then
zcmp_event <= zcmp_event_nxt;
zcmp_pc <= zcmp_pc_nxt;
end if;
end process zcmp_event_sync;

zcmp_event_comb : process(zcmp_pc, frontend_i, zcmp_event_reset, zcmp_event,exe_engine)
begin
zcmp_pc_nxt <= zcmp_pc;
zcmp_event_nxt <= zcmp_event;
zcmp_event_reset <= '0';

if(zcmp_event = '1' and exe_engine.state = EX_DISPATCH) then -- zcmp instruction is detected in frontend
zcmp_pc_nxt <= std_ulogic_vector(unsigned(exe_engine.pc2)); -- save current pc2 value (program counter will be held at this value during zcmp uop sequence)
zcmp_event_reset <= '1';
end if;

if(frontend_i.zcmp_start = '1') then
zcmp_event_nxt <= '1';
elsif (zcmp_event_reset = '1') then
zcmp_event_nxt <= '0';
else
zcmp_event_nxt <= zcmp_event;
end if;

end process;

end generate;

zcmp_disabled:
if not RISCV_ISA_Zcmp generate

zcmp_event <= '0';
zcmp_event_nxt <= '0';
zcmp_pc <= (others => '0');
zcmp_pc_nxt <= (others => '0');
zcmp_event_reset <= '0';

end generate;



-- CPU (Counter) Events -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
cnt_event(cnt_event_cy_c) <= '0' when (exe_engine.state = EX_SLEEP) else '1'; -- active cycle
cnt_event(cnt_event_tm_c) <= '0'; -- time: not available
cnt_event(cnt_event_ir_c) <= '1' when (exe_engine.state = EX_EXECUTE) else '0'; -- retired (=executed) instruction
cnt_event(cnt_event_ir_c) <= '1' when (exe_engine.state = EX_EXECUTE) and ((frontend_i.zcmp_in_uop_seq='0') or (frontend_i.zcmp_start='1')) else '0'; -- retired (=executed) instruction
cnt_event(cnt_event_compr_c) <= '1' when (exe_engine.state = EX_EXECUTE) and (exe_engine.ci = '1') else '0'; -- executed compressed instruction
cnt_event(cnt_event_wait_dis_c) <= '1' when (exe_engine.state = EX_DISPATCH) and (frontend_i.valid = '0') else '0'; -- instruction dispatch wait cycle
cnt_event(cnt_event_wait_alu_c) <= '1' when (exe_engine.state = EX_ALU_WAIT) else '0'; -- multi-cycle ALU wait cycle
Expand Down Expand Up @@ -1368,7 +1436,6 @@ begin
-- CSR read data output (to register file mux) --
csr_rdata_o <= csr.rdata;


-- ****************************************************************************************************************************
-- CPU Debug Mode
-- ****************************************************************************************************************************
Expand Down
45 changes: 43 additions & 2 deletions rtl/core/neorv32_cpu_decompressor.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@ use neorv32.neorv32_package.all;

entity neorv32_cpu_decompressor is
generic (
ZCB_EN : boolean -- enable Zcb ISA extension
ZCB_EN : boolean; -- enable Zcb ISA extension
ZCMP_EN : boolean
);
port (
instr_i : in std_ulogic_vector(15 downto 0); -- compressed instruction
instr_o : out std_ulogic_vector(31 downto 0) -- decompressed instruction
instr_o : out std_ulogic_vector(31 downto 0); -- decompressed instruction
instr_is_zcmp : out std_ulogic; -- instruction is part of Zcmp extension
zcmp_is_push : out std_ulogic;
zcmp_is_popret : out std_ulogic; -- instruction is popret
zcmp_is_popretz : out std_ulogic; -- instruction is popretz
zcmp_is_mvsa01 : out std_ulogic;
zcmp_is_mva01s : out std_ulogic
);
end neorv32_cpu_decompressor;

Expand Down Expand Up @@ -67,6 +74,12 @@ begin
-- defaults --
illegal <= '0';
decoded <= x"00000003"; -- empty rv32 instruction
instr_is_zcmp <= '0';
zcmp_is_popret <= '0';
zcmp_is_popretz <= '0';
zcmp_is_mvsa01 <= '0';
zcmp_is_mva01s <= '0';
zcmp_is_push <= '0';

-- decoder --
case instr_i(ci_opcode_msb_c downto ci_opcode_lsb_c) is
Expand Down Expand Up @@ -364,6 +377,34 @@ begin
end if;
end if;

when "101" =>

if ZCMP_EN then
case instr_i(12 downto 8) is
when "11000" => -- cm.push
instr_is_zcmp <= '1';
zcmp_is_push <= '1';
when "11010" => -- cm.pop
instr_is_zcmp <= '1';
when "11110" => -- cm.popret
instr_is_zcmp <= '1';
zcmp_is_popret<='1';
when "11100" => -- cm.popretz
instr_is_zcmp <= '1';
zcmp_is_popretz <='1';
when others =>
illegal <= '1';
end case;
if (instr_i(12 downto 10) = "011") then -- double moves
if (instr_i(6 downto 5) = "01") then -- mvsa01
instr_is_zcmp <= '1';
zcmp_is_mvsa01 <= '1';
elsif (instr_i(6 downto 5) = "11") then -- mvsa01s
instr_is_zcmp <= '1';
zcmp_is_mva01s <= '1';
end if;
end if;
end if;
when others => -- "001"/"101": C.FLDSP / C.LQSP, C.FSDSP / C.SQSP -> illegal
-- --------------------------------------------------------------------------------------
illegal <= '1';
Expand Down
Loading