OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_decompressor.vhd] - Blame information for rev 74

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
-- #################################################################################################
2 49 zero_gravi
-- # << NEORV32 - CPU: Compressed Instructions Decoder (RISC-V "C" Extension) >>                   #
3 2 zero_gravi
-- # ********************************************************************************************* #
4
-- # BSD 3-Clause License                                                                          #
5
-- #                                                                                               #
6 73 zero_gravi
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
7 2 zero_gravi
-- #                                                                                               #
8
-- # Redistribution and use in source and binary forms, with or without modification, are          #
9
-- # permitted provided that the following conditions are met:                                     #
10
-- #                                                                                               #
11
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
-- #    conditions and the following disclaimer.                                                   #
13
-- #                                                                                               #
14
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
16
-- #    provided with the distribution.                                                            #
17
-- #                                                                                               #
18
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
-- #    endorse or promote products derived from this software without specific prior written      #
20
-- #    permission.                                                                                #
21
-- #                                                                                               #
22
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
-- # ********************************************************************************************* #
32
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
-- #################################################################################################
34
 
35
library ieee;
36
use ieee.std_logic_1164.all;
37
use ieee.numeric_std.all;
38
 
39
library neorv32;
40
use neorv32.neorv32_package.all;
41
 
42
entity neorv32_cpu_decompressor is
43 73 zero_gravi
  generic (
44
    FPU_ENABLE : boolean -- floating-point instruction enabled
45
  );
46 2 zero_gravi
  port (
47
    -- instruction input --
48
    ci_instr16_i : in  std_ulogic_vector(15 downto 0); -- compressed instruction input
49
    -- instruction output --
50
    ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction
51
    ci_instr32_o : out std_ulogic_vector(31 downto 0)  -- 32-bit decompressed instruction
52
  );
53
end neorv32_cpu_decompressor;
54
 
55
architecture neorv32_cpu_decompressor_rtl of neorv32_cpu_decompressor is
56
 
57
  -- compressed instruction layout --
58
  constant ci_opcode_lsb_c : natural :=  0;
59
  constant ci_opcode_msb_c : natural :=  1;
60
  constant ci_rd_3_lsb_c   : natural :=  2;
61
  constant ci_rd_3_msb_c   : natural :=  4;
62
  constant ci_rd_5_lsb_c   : natural :=  7;
63
  constant ci_rd_5_msb_c   : natural := 11;
64
  constant ci_rs1_3_lsb_c  : natural :=  7;
65
  constant ci_rs1_3_msb_c  : natural :=  9;
66
  constant ci_rs1_5_lsb_c  : natural :=  7;
67
  constant ci_rs1_5_msb_c  : natural := 11;
68
  constant ci_rs2_3_lsb_c  : natural :=  2;
69
  constant ci_rs2_3_msb_c  : natural :=  4;
70
  constant ci_rs2_5_lsb_c  : natural :=  2;
71
  constant ci_rs2_5_msb_c  : natural :=  6;
72
  constant ci_funct3_lsb_c : natural := 13;
73
  constant ci_funct3_msb_c : natural := 15;
74
 
75
begin
76
 
77
  -- Compressed Instruction Decoder ---------------------------------------------------------
78
  -- -------------------------------------------------------------------------------------------
79
  decompressor: process(ci_instr16_i)
80
    variable imm20_v : std_ulogic_vector(20 downto 0);
81
    variable imm12_v : std_ulogic_vector(12 downto 0);
82
  begin
83
    -- defaults --
84
    ci_illegal_o <= '0';
85
    ci_instr32_o <= (others => '0');
86
 
87 58 zero_gravi
    -- helper: 22-bit sign-extended immediate for J/JAL --
88 2 zero_gravi
    imm20_v := (others => ci_instr16_i(12)); -- sign extension
89
    imm20_v(00):= '0';
90
    imm20_v(01):= ci_instr16_i(3);
91
    imm20_v(02):= ci_instr16_i(4);
92
    imm20_v(03):= ci_instr16_i(5);
93
    imm20_v(04):= ci_instr16_i(11);
94
    imm20_v(05):= ci_instr16_i(2);
95
    imm20_v(06):= ci_instr16_i(7);
96
    imm20_v(07):= ci_instr16_i(6);
97
    imm20_v(08):= ci_instr16_i(9);
98
    imm20_v(09):= ci_instr16_i(10);
99
    imm20_v(10):= ci_instr16_i(8);
100
    imm20_v(11):= ci_instr16_i(12);
101
 
102 58 zero_gravi
    -- helper: 12-bit sign-extended immediate for branches --
103 2 zero_gravi
    imm12_v := (others => ci_instr16_i(12)); -- sign extension
104
    imm12_v(00):= '0';
105
    imm12_v(01):= ci_instr16_i(3);
106
    imm12_v(02):= ci_instr16_i(4);
107
    imm12_v(03):= ci_instr16_i(10);
108
    imm12_v(04):= ci_instr16_i(11);
109
    imm12_v(05):= ci_instr16_i(2);
110
    imm12_v(06):= ci_instr16_i(5);
111
    imm12_v(07):= ci_instr16_i(6);
112
    imm12_v(08):= ci_instr16_i(12);
113
 
114
    -- actual decoder --
115
    case ci_instr16_i(ci_opcode_msb_c downto ci_opcode_lsb_c) is
116
 
117
      when "00" => -- C0: Register-Based Loads and Stores
118
        case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
119
 
120 52 zero_gravi
          when "010" | "011" => -- C.LW / C.FLW
121 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
122 53 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
123 2 zero_gravi
            ci_instr32_o(21 downto 20)                                 <= "00";
124
            ci_instr32_o(22)                                           <= ci_instr16_i(6);
125
            ci_instr32_o(23)                                           <= ci_instr16_i(10);
126
            ci_instr32_o(24)                                           <= ci_instr16_i(11);
127
            ci_instr32_o(25)                                           <= ci_instr16_i(12);
128
            ci_instr32_o(26)                                           <= ci_instr16_i(5);
129 6 zero_gravi
            ci_instr32_o(31 downto 27)                                 <= (others => '0');
130 2 zero_gravi
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
131
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
132
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);   -- x8 - x15
133 73 zero_gravi
            if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FLW
134 53 zero_gravi
              ci_illegal_o <= '1';
135
            end if;
136 2 zero_gravi
 
137 52 zero_gravi
          when "110" | "111" => -- C.SW / C.FSW
138 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
139 53 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
140 2 zero_gravi
            ci_instr32_o(08 downto 07)                                 <= "00";
141
            ci_instr32_o(09)                                           <= ci_instr16_i(6);
142
            ci_instr32_o(10)                                           <= ci_instr16_i(10);
143
            ci_instr32_o(11)                                           <= ci_instr16_i(11);
144
            ci_instr32_o(25)                                           <= ci_instr16_i(12);
145
            ci_instr32_o(26)                                           <= ci_instr16_i(5);
146
            ci_instr32_o(31 downto 27)                                 <= (others => '0');
147
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
148
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
149
            ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c)       <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c); -- x8 - x15
150 73 zero_gravi
            if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FSW
151 53 zero_gravi
              ci_illegal_o <= '1';
152
            end if;
153 2 zero_gravi
 
154 74 zero_gravi
          when others => -- "000": Illegal_instruction, C.ADDI4SPN; others: illegal
155 49 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
156 74 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
157
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00010"; -- stack pointer
158
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);
159
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
160
            ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c)   <= (others => '0'); -- zero extend
161
            ci_instr32_o(instr_imm12_lsb_c + 0)                        <= '0';
162
            ci_instr32_o(instr_imm12_lsb_c + 1)                        <= '0';
163
            ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(6);
164
            ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
165
            ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(11);
166
            ci_instr32_o(instr_imm12_lsb_c + 5)                        <= ci_instr16_i(12);
167
            ci_instr32_o(instr_imm12_lsb_c + 6)                        <= ci_instr16_i(7);
168
            ci_instr32_o(instr_imm12_lsb_c + 7)                        <= ci_instr16_i(8);
169
            ci_instr32_o(instr_imm12_lsb_c + 8)                        <= ci_instr16_i(9);
170
            ci_instr32_o(instr_imm12_lsb_c + 9)                        <= ci_instr16_i(10);
171
            --
172
            if (ci_instr16_i(12 downto 5) = "00000000") or -- canonical illegal C instruction or C.ADDI4SPN with nzuimm = 0
173
               (ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) = "001") or -- C.FLS / C.LQ
174
               (ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) = "100") or -- reserved
175
               (ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) = "101") then -- C.C.FSD / C.SQ
176
              ci_illegal_o <= '1';
177
            end if;
178 49 zero_gravi
 
179 2 zero_gravi
        end case;
180
 
181
      when "01" => -- C1: Control Transfer Instructions, Integer Constant-Generation Instructions
182
 
183
        case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
184 74 zero_gravi
          when "101" | "001" => -- C.J, C.JAL
185 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
186 74 zero_gravi
            if (ci_instr16_i(ci_funct3_msb_c) = '1') then -- C.J
187
              ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00000"; -- discard return address
188
            else -- C.JAL
189
              ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00001"; -- save return address to link register
190
            end if;
191 2 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jal_c;
192
            ci_instr32_o(19 downto 12)                                 <= imm20_v(19 downto 12);
193
            ci_instr32_o(20)                                           <= imm20_v(11);
194
            ci_instr32_o(30 downto 21)                                 <= imm20_v(10 downto 01);
195
            ci_instr32_o(31)                                           <= imm20_v(20);
196
 
197 74 zero_gravi
          when "110" | "111" => -- C.BEQ, C.BNEZ
198 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
199 74 zero_gravi
            if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.BEQ
200
              ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_beq_c;
201
            else -- C.BNEZ
202
              ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_bne_c;
203
            end if;
204 2 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_branch_c;
205
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
206
            ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c)       <= "00000"; -- x0
207
            ci_instr32_o(07)                                           <= imm12_v(11);
208
            ci_instr32_o(11 downto 08)                                 <= imm12_v(04 downto 01);
209
            ci_instr32_o(30 downto 25)                                 <= imm12_v(10 downto 05);
210
            ci_instr32_o(31)                                           <= imm12_v(12);
211
 
212
          when "010" => -- C.LI
213
          -- ----------------------------------------------------------------------------------------------------------
214
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
215
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
216
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00000"; -- x0
217
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
218
            ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c)   <= (others => ci_instr16_i(12)); -- sign extend
219
            ci_instr32_o(instr_imm12_lsb_c + 0)                        <= ci_instr16_i(2);
220
            ci_instr32_o(instr_imm12_lsb_c + 1)                        <= ci_instr16_i(3);
221
            ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(4);
222
            ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
223
            ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
224
            ci_instr32_o(instr_imm12_lsb_c + 5)                        <= ci_instr16_i(12);
225
 
226
          when "011" => -- C.LUI / C.ADDI16SP
227
          -- ----------------------------------------------------------------------------------------------------------
228
            if (ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c) = "00010") then -- C.ADDI16SP
229
              ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
230
              ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
231
              ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
232
              ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00010"; -- stack pointer
233
              ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= "00010"; -- stack pointer
234
              ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c)   <= (others => ci_instr16_i(12)); -- sign extend
235 41 zero_gravi
              ci_instr32_o(instr_imm12_lsb_c + 0)                        <= '0';
236
              ci_instr32_o(instr_imm12_lsb_c + 1)                        <= '0';
237
              ci_instr32_o(instr_imm12_lsb_c + 2)                        <= '0';
238
              ci_instr32_o(instr_imm12_lsb_c + 3)                        <= '0';
239
              ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
240
              ci_instr32_o(instr_imm12_lsb_c + 5)                        <= ci_instr16_i(2);
241
              ci_instr32_o(instr_imm12_lsb_c + 6)                        <= ci_instr16_i(5);
242
              ci_instr32_o(instr_imm12_lsb_c + 7)                        <= ci_instr16_i(3);
243
              ci_instr32_o(instr_imm12_lsb_c + 8)                        <= ci_instr16_i(4);
244
              ci_instr32_o(instr_imm12_lsb_c + 9)                        <= ci_instr16_i(12);
245 2 zero_gravi
            else -- C.LUI
246
              ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_lui_c;
247
              ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
248
              ci_instr32_o(instr_imm20_msb_c downto instr_imm20_lsb_c)   <= (others => ci_instr16_i(12)); -- sign extend
249
              ci_instr32_o(instr_imm20_lsb_c + 0)                        <= ci_instr16_i(2);
250
              ci_instr32_o(instr_imm20_lsb_c + 1)                        <= ci_instr16_i(3);
251
              ci_instr32_o(instr_imm20_lsb_c + 2)                        <= ci_instr16_i(4);
252
              ci_instr32_o(instr_imm20_lsb_c + 3)                        <= ci_instr16_i(5);
253
              ci_instr32_o(instr_imm20_lsb_c + 4)                        <= ci_instr16_i(6);
254
              ci_instr32_o(instr_imm20_lsb_c + 5)                        <= ci_instr16_i(12);
255
            end if;
256 74 zero_gravi
            if (ci_instr16_i(6 downto 2) = "00000") and (ci_instr16_i(12) = '0') then -- reserved if nzimm = 0
257 2 zero_gravi
              ci_illegal_o <= '1';
258
            end if;
259
 
260
          when "000" => -- C.NOP (rd=0) / C.ADDI
261
          -- ----------------------------------------------------------------------------------------------------------
262
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
263
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
264
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
265
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
266
            ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c)   <= (others => ci_instr16_i(12)); -- sign extend
267
            ci_instr32_o(instr_imm12_lsb_c + 0)                        <= ci_instr16_i(2);
268
            ci_instr32_o(instr_imm12_lsb_c + 1)                        <= ci_instr16_i(3);
269
            ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(4);
270
            ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
271
            ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
272
            ci_instr32_o(instr_imm12_lsb_c + 5)                        <= ci_instr16_i(12);
273
 
274 74 zero_gravi
          when others => -- 100: C.SRLI, C.SRAI, C.ANDI, C.SUB, C.XOR, C.OR, C.AND, reserved
275 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
276 73 zero_gravi
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)   <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
277 2 zero_gravi
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
278 73 zero_gravi
            ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c);
279
            case ci_instr16_i(11 downto 10) is
280 74 zero_gravi
              when "00" | "01" => -- C.SRLI, C.SRAI
281
                if (ci_instr16_i(10) = '0') then -- C.SRLI
282
                  ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
283
                else -- C.SRAI
284
                  ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
285 73 zero_gravi
                end if;
286
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
287
                ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
288
                ci_instr32_o(instr_imm12_lsb_c + 0)                        <= ci_instr16_i(2);
289
                ci_instr32_o(instr_imm12_lsb_c + 1)                        <= ci_instr16_i(3);
290
                ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(4);
291
                ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
292
                ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
293 74 zero_gravi
                if (ci_instr16_i(12) = '1') then -- nzuimm[5] = 1 -> RV32 custom
294 73 zero_gravi
                  ci_illegal_o <= '1';
295
                end if;
296
              when "10" => -- C.ANDI
297
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
298
                ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
299
                ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c)   <= (others => ci_instr16_i(12)); -- sign extend
300
                ci_instr32_o(instr_imm12_lsb_c + 0)                        <= ci_instr16_i(2);
301
                ci_instr32_o(instr_imm12_lsb_c + 1)                        <= ci_instr16_i(3);
302
                ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(4);
303
                ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
304
                ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
305
                ci_instr32_o(instr_imm12_lsb_c + 5)                        <= ci_instr16_i(12);
306
              when others => -- "11" = register-register operation
307
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
308
                case ci_instr16_i(6 downto 5) is
309
                  when "00" => -- C.SUB
310
                    ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
311
                    ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
312
                  when "01" => -- C.XOR
313
                    ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_xor_c;
314
                    ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
315
                  when "10" => -- C.OR
316
                    ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_or_c;
317
                    ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
318
                  when others => -- C.AND
319
                    ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
320
                    ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
321
                end case;
322
            end case;
323 2 zero_gravi
 
324
        end case;
325
 
326 74 zero_gravi
      when others => -- C2: Stack-Pointer-Based Loads and Stores, Control Transfer Instructions (or C3, which is not a RVC instruction)
327 2 zero_gravi
        case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
328
 
329
          when "000" => -- C.SLLI
330
          -- ----------------------------------------------------------------------------------------------------------
331
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
332
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
333
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
334
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sll_c;
335
            ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
336
            ci_instr32_o(instr_imm12_lsb_c + 0)                        <= ci_instr16_i(2);
337
            ci_instr32_o(instr_imm12_lsb_c + 1)                        <= ci_instr16_i(3);
338
            ci_instr32_o(instr_imm12_lsb_c + 2)                        <= ci_instr16_i(4);
339
            ci_instr32_o(instr_imm12_lsb_c + 3)                        <= ci_instr16_i(5);
340
            ci_instr32_o(instr_imm12_lsb_c + 4)                        <= ci_instr16_i(6);
341 74 zero_gravi
            if (ci_instr16_i(12) = '1') then -- nzuimm[5] = 1 -> RV32 custom
342
              ci_illegal_o <= '1';
343 73 zero_gravi
            end if;
344 2 zero_gravi
 
345 52 zero_gravi
          when "010" | "011" => -- C.LWSP / C.FLWSP
346 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
347 53 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
348 2 zero_gravi
            ci_instr32_o(21 downto 20)                                 <= "00";
349
            ci_instr32_o(22)                                           <= ci_instr16_i(4);
350
            ci_instr32_o(23)                                           <= ci_instr16_i(5);
351
            ci_instr32_o(24)                                           <= ci_instr16_i(6);
352
            ci_instr32_o(25)                                           <= ci_instr16_i(12);
353
            ci_instr32_o(26)                                           <= ci_instr16_i(2);
354
            ci_instr32_o(27)                                           <= ci_instr16_i(3);
355
            ci_instr32_o(31 downto 28)                                 <= (others => '0');
356
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
357
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00010"; -- stack pointer
358
            ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
359 73 zero_gravi
            if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FLWSP
360 53 zero_gravi
              ci_illegal_o <= '1';
361
            end if;
362 2 zero_gravi
 
363 52 zero_gravi
          when "110" | "111" => -- C.SWSP / C.FSWSP
364 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
365 53 zero_gravi
            ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
366 2 zero_gravi
            ci_instr32_o(08 downto 07)                                 <= "00";
367
            ci_instr32_o(09)                                           <= ci_instr16_i(9);
368
            ci_instr32_o(10)                                           <= ci_instr16_i(10);
369
            ci_instr32_o(11)                                           <= ci_instr16_i(11);
370
            ci_instr32_o(25)                                           <= ci_instr16_i(12);
371
            ci_instr32_o(26)                                           <= ci_instr16_i(7);
372
            ci_instr32_o(27)                                           <= ci_instr16_i(8);
373
            ci_instr32_o(31 downto 28)                                 <= (others => '0');
374
            ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
375
            ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00010"; -- stack pointer
376
            ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c)       <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
377 73 zero_gravi
            if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FSWSP
378 53 zero_gravi
              ci_illegal_o <= '1';
379
            end if;
380 2 zero_gravi
 
381 74 zero_gravi
          when others => -- "100": C.JR, C.JALR, C.MV, C.EBREAK, C.ADD; others: undefined
382 2 zero_gravi
          -- ----------------------------------------------------------------------------------------------------------
383
            if (ci_instr16_i(12) = '0') then -- C.JR, C.MV
384
              if (ci_instr16_i(6 downto 2) = "00000") then -- C.JR
385
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jalr_c;
386
                ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
387
                ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= "00000"; -- discard return address
388
              else -- C.MV
389
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
390
                ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= "000";
391
                ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
392
                ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= "00000"; -- x0
393
                ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c)       <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
394
              end if;
395
            else -- C.EBREAK, C.JALR, C.ADD
396
              if (ci_instr16_i(6 downto 2) = "00000") then -- C.EBREAK, C.JALR
397
                if (ci_instr16_i(11 downto 7) = "00000") then -- C.EBREAK
398 74 zero_gravi
                  ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c)   <= opcode_system_c;
399
                  ci_instr32_o(instr_funct12_msb_c downto instr_funct12_lsb_c) <= funct12_ebreak_c;
400 2 zero_gravi
                else -- C.JALR
401
                  ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jalr_c;
402
                  ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
403
                  ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= "00001"; -- save return address to link register
404
                end if;
405
              else -- C.ADD
406
                ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
407
                ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= "000";
408
                ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c)         <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
409
                ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c)       <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
410
                ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c)       <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
411
              end if;
412
            end if;
413 74 zero_gravi
            --
414
            if (ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) = "001") or -- C.FLDSP / C.LQSP
415
               (ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) = "101") then -- C.FSDSP / C.SQSP
416
              ci_illegal_o <= '1';
417
            end if;
418 2 zero_gravi
 
419
        end case;
420
 
421
    end case;
422
  end process decompressor;
423
 
424
 
425
end neorv32_cpu_decompressor_rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.