Sat, 06 Aug 2011 00:02:46 +0100
[UPSTREAM PULL] Update baseline to LatticeMico32 v3.8 from Diamond 1.3-lm32 distribution package (datestamp May 2011)
philpem@26 | 1 | // ================================================================== |
philpem@26 | 2 | // >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< |
philpem@26 | 3 | // ------------------------------------------------------------------ |
philpem@26 | 4 | // Copyright (c) 2006-2011 by Lattice Semiconductor Corporation |
philpem@26 | 5 | // ALL RIGHTS RESERVED |
philpem@26 | 6 | // ------------------------------------------------------------------ |
philpem@26 | 7 | // |
philpem@26 | 8 | // IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM. |
philpem@26 | 9 | // |
philpem@26 | 10 | // Permission: |
philpem@26 | 11 | // |
philpem@26 | 12 | // Lattice Semiconductor grants permission to use this code |
philpem@26 | 13 | // pursuant to the terms of the Lattice Semiconductor Corporation |
philpem@26 | 14 | // Open Source License Agreement. |
philpem@26 | 15 | // |
philpem@26 | 16 | // Disclaimer: |
philpem@0 | 17 | // |
philpem@26 | 18 | // Lattice Semiconductor provides no warranty regarding the use or |
philpem@26 | 19 | // functionality of this code. It is the user's responsibility to |
philpem@26 | 20 | // verify the user’s design for consistency and functionality through |
philpem@26 | 21 | // the use of formal verification methods. |
philpem@26 | 22 | // |
philpem@26 | 23 | // -------------------------------------------------------------------- |
philpem@26 | 24 | // |
philpem@26 | 25 | // Lattice Semiconductor Corporation |
philpem@26 | 26 | // 5555 NE Moore Court |
philpem@26 | 27 | // Hillsboro, OR 97214 |
philpem@26 | 28 | // U.S.A |
philpem@26 | 29 | // |
philpem@26 | 30 | // TEL: 1-800-Lattice (USA and Canada) |
philpem@26 | 31 | // 503-286-8001 (other locations) |
philpem@26 | 32 | // |
philpem@26 | 33 | // web: http://www.latticesemi.com/ |
philpem@26 | 34 | // email: techsupport@latticesemi.com |
philpem@26 | 35 | // |
philpem@26 | 36 | // -------------------------------------------------------------------- |
philpem@0 | 37 | // FILE DETAILS |
philpem@0 | 38 | // Project : LatticeMico32 |
philpem@0 | 39 | // File : lm32_decoder.v |
philpem@0 | 40 | // Title : Instruction decoder |
philpem@0 | 41 | // Dependencies : lm32_include.v |
philpem@0 | 42 | // Version : 6.1.17 |
philpem@0 | 43 | // : Initial Release |
philpem@0 | 44 | // Version : 7.0SP2, 3.0 |
philpem@0 | 45 | // : No Change |
philpem@0 | 46 | // Version : 3.1 |
philpem@0 | 47 | // : Support for static branch prediction. Information about |
philpem@0 | 48 | // : branch type is generated and passed on to the predictor. |
philpem@0 | 49 | // Version : 3.2 |
philpem@0 | 50 | // : No change |
philpem@0 | 51 | // Version : 3.3 |
philpem@0 | 52 | // : Renamed port names that conflict with keywords reserved |
philpem@0 | 53 | // : in System-Verilog. |
philpem@0 | 54 | // ============================================================================= |
philpem@0 | 55 | |
philpem@0 | 56 | `include "lm32_include.v" |
philpem@0 | 57 | |
philpem@0 | 58 | // Index of opcode field in an instruction |
philpem@0 | 59 | `define LM32_OPCODE_RNG 31:26 |
philpem@0 | 60 | `define LM32_OP_RNG 30:26 |
philpem@0 | 61 | |
philpem@0 | 62 | // Opcodes - Some are only listed as 5 bits as their MSB is a don't care |
philpem@0 | 63 | `define LM32_OPCODE_ADD 5'b01101 |
philpem@0 | 64 | `define LM32_OPCODE_AND 5'b01000 |
philpem@0 | 65 | `define LM32_OPCODE_ANDHI 6'b011000 |
philpem@0 | 66 | `define LM32_OPCODE_B 6'b110000 |
philpem@0 | 67 | `define LM32_OPCODE_BI 6'b111000 |
philpem@0 | 68 | `define LM32_OPCODE_BE 6'b010001 |
philpem@0 | 69 | `define LM32_OPCODE_BG 6'b010010 |
philpem@0 | 70 | `define LM32_OPCODE_BGE 6'b010011 |
philpem@0 | 71 | `define LM32_OPCODE_BGEU 6'b010100 |
philpem@0 | 72 | `define LM32_OPCODE_BGU 6'b010101 |
philpem@0 | 73 | `define LM32_OPCODE_BNE 6'b010111 |
philpem@0 | 74 | `define LM32_OPCODE_CALL 6'b110110 |
philpem@0 | 75 | `define LM32_OPCODE_CALLI 6'b111110 |
philpem@0 | 76 | `define LM32_OPCODE_CMPE 5'b11001 |
philpem@0 | 77 | `define LM32_OPCODE_CMPG 5'b11010 |
philpem@0 | 78 | `define LM32_OPCODE_CMPGE 5'b11011 |
philpem@0 | 79 | `define LM32_OPCODE_CMPGEU 5'b11100 |
philpem@0 | 80 | `define LM32_OPCODE_CMPGU 5'b11101 |
philpem@0 | 81 | `define LM32_OPCODE_CMPNE 5'b11111 |
philpem@0 | 82 | `define LM32_OPCODE_DIVU 6'b100011 |
philpem@0 | 83 | `define LM32_OPCODE_LB 6'b000100 |
philpem@0 | 84 | `define LM32_OPCODE_LBU 6'b010000 |
philpem@0 | 85 | `define LM32_OPCODE_LH 6'b000111 |
philpem@0 | 86 | `define LM32_OPCODE_LHU 6'b001011 |
philpem@0 | 87 | `define LM32_OPCODE_LW 6'b001010 |
philpem@0 | 88 | `define LM32_OPCODE_MODU 6'b110001 |
philpem@0 | 89 | `define LM32_OPCODE_MUL 5'b00010 |
philpem@0 | 90 | `define LM32_OPCODE_NOR 5'b00001 |
philpem@0 | 91 | `define LM32_OPCODE_OR 5'b01110 |
philpem@0 | 92 | `define LM32_OPCODE_ORHI 6'b011110 |
philpem@0 | 93 | `define LM32_OPCODE_RAISE 6'b101011 |
philpem@0 | 94 | `define LM32_OPCODE_RCSR 6'b100100 |
philpem@0 | 95 | `define LM32_OPCODE_SB 6'b001100 |
philpem@0 | 96 | `define LM32_OPCODE_SEXTB 6'b101100 |
philpem@0 | 97 | `define LM32_OPCODE_SEXTH 6'b110111 |
philpem@0 | 98 | `define LM32_OPCODE_SH 6'b000011 |
philpem@0 | 99 | `define LM32_OPCODE_SL 5'b01111 |
philpem@0 | 100 | `define LM32_OPCODE_SR 5'b00101 |
philpem@0 | 101 | `define LM32_OPCODE_SRU 5'b00000 |
philpem@0 | 102 | `define LM32_OPCODE_SUB 6'b110010 |
philpem@0 | 103 | `define LM32_OPCODE_SW 6'b010110 |
philpem@0 | 104 | `define LM32_OPCODE_USER 6'b110011 |
philpem@0 | 105 | `define LM32_OPCODE_WCSR 6'b110100 |
philpem@0 | 106 | `define LM32_OPCODE_XNOR 5'b01001 |
philpem@0 | 107 | `define LM32_OPCODE_XOR 5'b00110 |
philpem@0 | 108 | |
philpem@0 | 109 | ///////////////////////////////////////////////////// |
philpem@0 | 110 | // Module interface |
philpem@0 | 111 | ///////////////////////////////////////////////////// |
philpem@0 | 112 | |
philpem@0 | 113 | module lm32_decoder ( |
philpem@0 | 114 | // ----- Inputs ------- |
philpem@0 | 115 | instruction, |
philpem@0 | 116 | // ----- Outputs ------- |
philpem@0 | 117 | d_result_sel_0, |
philpem@0 | 118 | d_result_sel_1, |
philpem@0 | 119 | x_result_sel_csr, |
philpem@0 | 120 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 121 | x_result_sel_mc_arith, |
philpem@0 | 122 | `endif |
philpem@0 | 123 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 124 | x_result_sel_shift, |
philpem@0 | 125 | `endif |
philpem@0 | 126 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 127 | x_result_sel_sext, |
philpem@0 | 128 | `endif |
philpem@0 | 129 | x_result_sel_logic, |
philpem@0 | 130 | `ifdef CFG_USER_ENABLED |
philpem@0 | 131 | x_result_sel_user, |
philpem@0 | 132 | `endif |
philpem@0 | 133 | x_result_sel_add, |
philpem@0 | 134 | m_result_sel_compare, |
philpem@0 | 135 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 136 | m_result_sel_shift, |
philpem@0 | 137 | `endif |
philpem@0 | 138 | w_result_sel_load, |
philpem@0 | 139 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 140 | w_result_sel_mul, |
philpem@0 | 141 | `endif |
philpem@0 | 142 | x_bypass_enable, |
philpem@0 | 143 | m_bypass_enable, |
philpem@0 | 144 | read_enable_0, |
philpem@0 | 145 | read_idx_0, |
philpem@0 | 146 | read_enable_1, |
philpem@0 | 147 | read_idx_1, |
philpem@0 | 148 | write_enable, |
philpem@0 | 149 | write_idx, |
philpem@0 | 150 | immediate, |
philpem@0 | 151 | branch_offset, |
philpem@0 | 152 | load, |
philpem@0 | 153 | store, |
philpem@0 | 154 | size, |
philpem@0 | 155 | sign_extend, |
philpem@0 | 156 | adder_op, |
philpem@0 | 157 | logic_op, |
philpem@0 | 158 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 159 | direction, |
philpem@0 | 160 | `endif |
philpem@0 | 161 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 162 | shift_left, |
philpem@0 | 163 | shift_right, |
philpem@0 | 164 | `endif |
philpem@0 | 165 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 166 | multiply, |
philpem@0 | 167 | `endif |
philpem@0 | 168 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 169 | divide, |
philpem@0 | 170 | modulus, |
philpem@0 | 171 | `endif |
philpem@0 | 172 | branch, |
philpem@0 | 173 | branch_reg, |
philpem@0 | 174 | condition, |
philpem@0 | 175 | bi_conditional, |
philpem@0 | 176 | bi_unconditional, |
philpem@0 | 177 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 178 | break_opcode, |
philpem@0 | 179 | `endif |
philpem@0 | 180 | scall, |
philpem@0 | 181 | eret, |
philpem@0 | 182 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 183 | bret, |
philpem@0 | 184 | `endif |
philpem@0 | 185 | `ifdef CFG_USER_ENABLED |
philpem@0 | 186 | user_opcode, |
philpem@0 | 187 | `endif |
philpem@0 | 188 | csr_write_enable |
philpem@0 | 189 | ); |
philpem@0 | 190 | |
philpem@0 | 191 | ///////////////////////////////////////////////////// |
philpem@0 | 192 | // Inputs |
philpem@0 | 193 | ///////////////////////////////////////////////////// |
philpem@0 | 194 | |
philpem@0 | 195 | input [`LM32_INSTRUCTION_RNG] instruction; // Instruction to decode |
philpem@0 | 196 | |
philpem@0 | 197 | ///////////////////////////////////////////////////// |
philpem@0 | 198 | // Outputs |
philpem@0 | 199 | ///////////////////////////////////////////////////// |
philpem@0 | 200 | |
philpem@0 | 201 | output [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0; |
philpem@0 | 202 | reg [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0; |
philpem@0 | 203 | output [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1; |
philpem@0 | 204 | reg [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1; |
philpem@0 | 205 | output x_result_sel_csr; |
philpem@0 | 206 | reg x_result_sel_csr; |
philpem@0 | 207 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 208 | output x_result_sel_mc_arith; |
philpem@0 | 209 | reg x_result_sel_mc_arith; |
philpem@0 | 210 | `endif |
philpem@0 | 211 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 212 | output x_result_sel_shift; |
philpem@0 | 213 | reg x_result_sel_shift; |
philpem@0 | 214 | `endif |
philpem@0 | 215 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 216 | output x_result_sel_sext; |
philpem@0 | 217 | reg x_result_sel_sext; |
philpem@0 | 218 | `endif |
philpem@0 | 219 | output x_result_sel_logic; |
philpem@0 | 220 | reg x_result_sel_logic; |
philpem@0 | 221 | `ifdef CFG_USER_ENABLED |
philpem@0 | 222 | output x_result_sel_user; |
philpem@0 | 223 | reg x_result_sel_user; |
philpem@0 | 224 | `endif |
philpem@0 | 225 | output x_result_sel_add; |
philpem@0 | 226 | reg x_result_sel_add; |
philpem@0 | 227 | output m_result_sel_compare; |
philpem@0 | 228 | reg m_result_sel_compare; |
philpem@0 | 229 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 230 | output m_result_sel_shift; |
philpem@0 | 231 | reg m_result_sel_shift; |
philpem@0 | 232 | `endif |
philpem@0 | 233 | output w_result_sel_load; |
philpem@0 | 234 | reg w_result_sel_load; |
philpem@0 | 235 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 236 | output w_result_sel_mul; |
philpem@0 | 237 | reg w_result_sel_mul; |
philpem@0 | 238 | `endif |
philpem@0 | 239 | output x_bypass_enable; |
philpem@0 | 240 | wire x_bypass_enable; |
philpem@0 | 241 | output m_bypass_enable; |
philpem@0 | 242 | wire m_bypass_enable; |
philpem@0 | 243 | output read_enable_0; |
philpem@0 | 244 | wire read_enable_0; |
philpem@0 | 245 | output [`LM32_REG_IDX_RNG] read_idx_0; |
philpem@0 | 246 | wire [`LM32_REG_IDX_RNG] read_idx_0; |
philpem@0 | 247 | output read_enable_1; |
philpem@0 | 248 | wire read_enable_1; |
philpem@0 | 249 | output [`LM32_REG_IDX_RNG] read_idx_1; |
philpem@0 | 250 | wire [`LM32_REG_IDX_RNG] read_idx_1; |
philpem@0 | 251 | output write_enable; |
philpem@0 | 252 | wire write_enable; |
philpem@0 | 253 | output [`LM32_REG_IDX_RNG] write_idx; |
philpem@0 | 254 | wire [`LM32_REG_IDX_RNG] write_idx; |
philpem@0 | 255 | output [`LM32_WORD_RNG] immediate; |
philpem@0 | 256 | wire [`LM32_WORD_RNG] immediate; |
philpem@0 | 257 | output [`LM32_PC_RNG] branch_offset; |
philpem@0 | 258 | wire [`LM32_PC_RNG] branch_offset; |
philpem@0 | 259 | output load; |
philpem@0 | 260 | wire load; |
philpem@0 | 261 | output store; |
philpem@0 | 262 | wire store; |
philpem@0 | 263 | output [`LM32_SIZE_RNG] size; |
philpem@0 | 264 | wire [`LM32_SIZE_RNG] size; |
philpem@0 | 265 | output sign_extend; |
philpem@0 | 266 | wire sign_extend; |
philpem@0 | 267 | output adder_op; |
philpem@0 | 268 | wire adder_op; |
philpem@0 | 269 | output [`LM32_LOGIC_OP_RNG] logic_op; |
philpem@0 | 270 | wire [`LM32_LOGIC_OP_RNG] logic_op; |
philpem@0 | 271 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 272 | output direction; |
philpem@0 | 273 | wire direction; |
philpem@0 | 274 | `endif |
philpem@0 | 275 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 276 | output shift_left; |
philpem@0 | 277 | wire shift_left; |
philpem@0 | 278 | output shift_right; |
philpem@0 | 279 | wire shift_right; |
philpem@0 | 280 | `endif |
philpem@0 | 281 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 282 | output multiply; |
philpem@0 | 283 | wire multiply; |
philpem@0 | 284 | `endif |
philpem@0 | 285 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 286 | output divide; |
philpem@0 | 287 | wire divide; |
philpem@0 | 288 | output modulus; |
philpem@0 | 289 | wire modulus; |
philpem@0 | 290 | `endif |
philpem@0 | 291 | output branch; |
philpem@0 | 292 | wire branch; |
philpem@0 | 293 | output branch_reg; |
philpem@0 | 294 | wire branch_reg; |
philpem@0 | 295 | output [`LM32_CONDITION_RNG] condition; |
philpem@0 | 296 | wire [`LM32_CONDITION_RNG] condition; |
philpem@0 | 297 | output bi_conditional; |
philpem@0 | 298 | wire bi_conditional; |
philpem@0 | 299 | output bi_unconditional; |
philpem@0 | 300 | wire bi_unconditional; |
philpem@0 | 301 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 302 | output break_opcode; |
philpem@0 | 303 | wire break_opcode; |
philpem@0 | 304 | `endif |
philpem@0 | 305 | output scall; |
philpem@0 | 306 | wire scall; |
philpem@0 | 307 | output eret; |
philpem@0 | 308 | wire eret; |
philpem@0 | 309 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 310 | output bret; |
philpem@0 | 311 | wire bret; |
philpem@0 | 312 | `endif |
philpem@0 | 313 | `ifdef CFG_USER_ENABLED |
philpem@0 | 314 | output [`LM32_USER_OPCODE_RNG] user_opcode; |
philpem@0 | 315 | wire [`LM32_USER_OPCODE_RNG] user_opcode; |
philpem@0 | 316 | `endif |
philpem@0 | 317 | output csr_write_enable; |
philpem@0 | 318 | wire csr_write_enable; |
philpem@0 | 319 | |
philpem@0 | 320 | ///////////////////////////////////////////////////// |
philpem@0 | 321 | // Internal nets and registers |
philpem@0 | 322 | ///////////////////////////////////////////////////// |
philpem@0 | 323 | |
philpem@0 | 324 | wire [`LM32_WORD_RNG] extended_immediate; // Zero or sign extended immediate |
philpem@0 | 325 | wire [`LM32_WORD_RNG] high_immediate; // Immediate as high 16 bits |
philpem@0 | 326 | wire [`LM32_WORD_RNG] call_immediate; // Call immediate |
philpem@0 | 327 | wire [`LM32_WORD_RNG] branch_immediate; // Conditional branch immediate |
philpem@0 | 328 | wire sign_extend_immediate; // Whether the immediate should be sign extended (`TRUE) or zero extended (`FALSE) |
philpem@0 | 329 | wire select_high_immediate; // Whether to select the high immediate |
philpem@0 | 330 | wire select_call_immediate; // Whether to select the call immediate |
philpem@0 | 331 | |
philpem@0 | 332 | ///////////////////////////////////////////////////// |
philpem@0 | 333 | // Functions |
philpem@0 | 334 | ///////////////////////////////////////////////////// |
philpem@0 | 335 | |
philpem@0 | 336 | `include "lm32_functions.v" |
philpem@0 | 337 | |
philpem@0 | 338 | ///////////////////////////////////////////////////// |
philpem@0 | 339 | // Combinational logic |
philpem@0 | 340 | ///////////////////////////////////////////////////// |
philpem@0 | 341 | |
philpem@0 | 342 | // Determine opcode |
philpem@0 | 343 | assign op_add = instruction[`LM32_OP_RNG] == `LM32_OPCODE_ADD; |
philpem@0 | 344 | assign op_and = instruction[`LM32_OP_RNG] == `LM32_OPCODE_AND; |
philpem@0 | 345 | assign op_andhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ANDHI; |
philpem@0 | 346 | assign op_b = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_B; |
philpem@0 | 347 | assign op_bi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BI; |
philpem@0 | 348 | assign op_be = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BE; |
philpem@0 | 349 | assign op_bg = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BG; |
philpem@0 | 350 | assign op_bge = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGE; |
philpem@0 | 351 | assign op_bgeu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGEU; |
philpem@0 | 352 | assign op_bgu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGU; |
philpem@0 | 353 | assign op_bne = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BNE; |
philpem@0 | 354 | assign op_call = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALL; |
philpem@0 | 355 | assign op_calli = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALLI; |
philpem@0 | 356 | assign op_cmpe = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPE; |
philpem@0 | 357 | assign op_cmpg = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPG; |
philpem@0 | 358 | assign op_cmpge = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGE; |
philpem@0 | 359 | assign op_cmpgeu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGEU; |
philpem@0 | 360 | assign op_cmpgu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGU; |
philpem@0 | 361 | assign op_cmpne = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPNE; |
philpem@0 | 362 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 363 | assign op_divu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_DIVU; |
philpem@0 | 364 | `endif |
philpem@0 | 365 | assign op_lb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LB; |
philpem@0 | 366 | assign op_lbu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LBU; |
philpem@0 | 367 | assign op_lh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LH; |
philpem@0 | 368 | assign op_lhu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LHU; |
philpem@0 | 369 | assign op_lw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LW; |
philpem@0 | 370 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 371 | assign op_modu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_MODU; |
philpem@0 | 372 | `endif |
philpem@0 | 373 | `ifdef LM32_MULTIPLY_ENABLED |
philpem@0 | 374 | assign op_mul = instruction[`LM32_OP_RNG] == `LM32_OPCODE_MUL; |
philpem@0 | 375 | `endif |
philpem@0 | 376 | assign op_nor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_NOR; |
philpem@0 | 377 | assign op_or = instruction[`LM32_OP_RNG] == `LM32_OPCODE_OR; |
philpem@0 | 378 | assign op_orhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ORHI; |
philpem@0 | 379 | assign op_raise = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RAISE; |
philpem@0 | 380 | assign op_rcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RCSR; |
philpem@0 | 381 | assign op_sb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SB; |
philpem@0 | 382 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 383 | assign op_sextb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTB; |
philpem@0 | 384 | assign op_sexth = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTH; |
philpem@0 | 385 | `endif |
philpem@0 | 386 | assign op_sh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SH; |
philpem@0 | 387 | `ifdef LM32_BARREL_SHIFT_ENABLED |
philpem@0 | 388 | assign op_sl = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SL; |
philpem@0 | 389 | `endif |
philpem@0 | 390 | assign op_sr = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SR; |
philpem@0 | 391 | assign op_sru = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SRU; |
philpem@0 | 392 | assign op_sub = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SUB; |
philpem@0 | 393 | assign op_sw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SW; |
philpem@0 | 394 | assign op_user = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_USER; |
philpem@0 | 395 | assign op_wcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_WCSR; |
philpem@0 | 396 | assign op_xnor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XNOR; |
philpem@0 | 397 | assign op_xor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XOR; |
philpem@0 | 398 | |
philpem@0 | 399 | // Group opcodes by function |
philpem@0 | 400 | assign arith = op_add | op_sub; |
philpem@0 | 401 | assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; |
philpem@0 | 402 | assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; |
philpem@0 | 403 | assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; |
philpem@0 | 404 | assign bi_unconditional = op_bi; |
philpem@0 | 405 | assign bra = op_b | bi_unconditional | bi_conditional; |
philpem@0 | 406 | assign call = op_call | op_calli; |
philpem@0 | 407 | `ifdef LM32_BARREL_SHIFT_ENABLED |
philpem@0 | 408 | assign shift = op_sl | op_sr | op_sru; |
philpem@0 | 409 | `endif |
philpem@0 | 410 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 411 | assign shift = op_sr | op_sru; |
philpem@0 | 412 | `endif |
philpem@0 | 413 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 414 | assign shift_left = op_sl; |
philpem@0 | 415 | assign shift_right = op_sr | op_sru; |
philpem@0 | 416 | `endif |
philpem@0 | 417 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 418 | assign sext = op_sextb | op_sexth; |
philpem@0 | 419 | `endif |
philpem@0 | 420 | `ifdef LM32_MULTIPLY_ENABLED |
philpem@0 | 421 | assign multiply = op_mul; |
philpem@0 | 422 | `endif |
philpem@0 | 423 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 424 | assign divide = op_divu; |
philpem@0 | 425 | assign modulus = op_modu; |
philpem@0 | 426 | `endif |
philpem@0 | 427 | assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; |
philpem@0 | 428 | assign store = op_sb | op_sh | op_sw; |
philpem@0 | 429 | |
philpem@0 | 430 | // Select pipeline multiplexor controls |
philpem@0 | 431 | always @(*) |
philpem@0 | 432 | begin |
philpem@0 | 433 | // D stage |
philpem@0 | 434 | if (call) |
philpem@0 | 435 | d_result_sel_0 = `LM32_D_RESULT_SEL_0_NEXT_PC; |
philpem@0 | 436 | else |
philpem@0 | 437 | d_result_sel_0 = `LM32_D_RESULT_SEL_0_REG_0; |
philpem@0 | 438 | if (call) |
philpem@0 | 439 | d_result_sel_1 = `LM32_D_RESULT_SEL_1_ZERO; |
philpem@0 | 440 | else if ((instruction[31] == 1'b0) && !bra) |
philpem@0 | 441 | d_result_sel_1 = `LM32_D_RESULT_SEL_1_IMMEDIATE; |
philpem@0 | 442 | else |
philpem@0 | 443 | d_result_sel_1 = `LM32_D_RESULT_SEL_1_REG_1; |
philpem@0 | 444 | // X stage |
philpem@0 | 445 | x_result_sel_csr = `FALSE; |
philpem@0 | 446 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 447 | x_result_sel_mc_arith = `FALSE; |
philpem@0 | 448 | `endif |
philpem@0 | 449 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 450 | x_result_sel_shift = `FALSE; |
philpem@0 | 451 | `endif |
philpem@0 | 452 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 453 | x_result_sel_sext = `FALSE; |
philpem@0 | 454 | `endif |
philpem@0 | 455 | x_result_sel_logic = `FALSE; |
philpem@0 | 456 | `ifdef CFG_USER_ENABLED |
philpem@0 | 457 | x_result_sel_user = `FALSE; |
philpem@0 | 458 | `endif |
philpem@0 | 459 | x_result_sel_add = `FALSE; |
philpem@0 | 460 | if (op_rcsr) |
philpem@0 | 461 | x_result_sel_csr = `TRUE; |
philpem@0 | 462 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 463 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 464 | else if (shift_left | shift_right) |
philpem@0 | 465 | x_result_sel_mc_arith = `TRUE; |
philpem@0 | 466 | `endif |
philpem@0 | 467 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 468 | else if (divide | modulus) |
philpem@0 | 469 | x_result_sel_mc_arith = `TRUE; |
philpem@0 | 470 | `endif |
philpem@0 | 471 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 472 | else if (multiply) |
philpem@0 | 473 | x_result_sel_mc_arith = `TRUE; |
philpem@0 | 474 | `endif |
philpem@0 | 475 | `endif |
philpem@0 | 476 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 477 | else if (shift) |
philpem@0 | 478 | x_result_sel_shift = `TRUE; |
philpem@0 | 479 | `endif |
philpem@0 | 480 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 481 | else if (sext) |
philpem@0 | 482 | x_result_sel_sext = `TRUE; |
philpem@0 | 483 | `endif |
philpem@0 | 484 | else if (logical) |
philpem@0 | 485 | x_result_sel_logic = `TRUE; |
philpem@0 | 486 | `ifdef CFG_USER_ENABLED |
philpem@0 | 487 | else if (op_user) |
philpem@0 | 488 | x_result_sel_user = `TRUE; |
philpem@0 | 489 | `endif |
philpem@0 | 490 | else |
philpem@0 | 491 | x_result_sel_add = `TRUE; |
philpem@0 | 492 | |
philpem@0 | 493 | // M stage |
philpem@0 | 494 | |
philpem@0 | 495 | m_result_sel_compare = cmp; |
philpem@0 | 496 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 497 | m_result_sel_shift = shift; |
philpem@0 | 498 | `endif |
philpem@0 | 499 | |
philpem@0 | 500 | // W stage |
philpem@0 | 501 | w_result_sel_load = load; |
philpem@0 | 502 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 503 | w_result_sel_mul = op_mul; |
philpem@0 | 504 | `endif |
philpem@0 | 505 | end |
philpem@0 | 506 | |
philpem@0 | 507 | // Set if result is valid at end of X stage |
philpem@0 | 508 | assign x_bypass_enable = arith |
philpem@0 | 509 | | logical |
philpem@0 | 510 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 511 | | shift_left |
philpem@0 | 512 | | shift_right |
philpem@0 | 513 | `endif |
philpem@0 | 514 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 515 | | multiply |
philpem@0 | 516 | `endif |
philpem@0 | 517 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 518 | | divide |
philpem@0 | 519 | | modulus |
philpem@0 | 520 | `endif |
philpem@0 | 521 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 522 | | shift |
philpem@0 | 523 | `endif |
philpem@0 | 524 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 525 | | sext |
philpem@0 | 526 | `endif |
philpem@0 | 527 | `ifdef CFG_USER_ENABLED |
philpem@0 | 528 | | op_user |
philpem@0 | 529 | `endif |
philpem@0 | 530 | | op_rcsr |
philpem@0 | 531 | ; |
philpem@0 | 532 | // Set if result is valid at end of M stage |
philpem@0 | 533 | assign m_bypass_enable = x_bypass_enable |
philpem@0 | 534 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 535 | | shift |
philpem@0 | 536 | `endif |
philpem@0 | 537 | | cmp |
philpem@0 | 538 | ; |
philpem@0 | 539 | // Register file read port 0 |
philpem@0 | 540 | assign read_enable_0 = ~(op_bi | op_calli); |
philpem@0 | 541 | assign read_idx_0 = instruction[25:21]; |
philpem@0 | 542 | // Register file read port 1 |
philpem@0 | 543 | assign read_enable_1 = ~(op_bi | op_calli | load); |
philpem@0 | 544 | assign read_idx_1 = instruction[20:16]; |
philpem@0 | 545 | // Register file write port |
philpem@0 | 546 | assign write_enable = ~(bra | op_raise | store | op_wcsr); |
philpem@0 | 547 | assign write_idx = call |
philpem@0 | 548 | ? 5'd29 |
philpem@0 | 549 | : instruction[31] == 1'b0 |
philpem@0 | 550 | ? instruction[20:16] |
philpem@0 | 551 | : instruction[15:11]; |
philpem@0 | 552 | |
philpem@0 | 553 | // Size of load/stores |
philpem@0 | 554 | assign size = instruction[27:26]; |
philpem@0 | 555 | // Whether to sign or zero extend |
philpem@0 | 556 | assign sign_extend = instruction[28]; |
philpem@0 | 557 | // Set adder_op to 1 to perform a subtraction |
philpem@0 | 558 | assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; |
philpem@0 | 559 | // Logic operation (and, or, etc) |
philpem@0 | 560 | assign logic_op = instruction[29:26]; |
philpem@0 | 561 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 562 | // Shift direction |
philpem@0 | 563 | assign direction = instruction[29]; |
philpem@0 | 564 | `endif |
philpem@0 | 565 | // Control flow microcodes |
philpem@0 | 566 | assign branch = bra | call; |
philpem@0 | 567 | assign branch_reg = op_call | op_b; |
philpem@0 | 568 | assign condition = instruction[28:26]; |
philpem@0 | 569 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 570 | assign break_opcode = op_raise & ~instruction[2]; |
philpem@0 | 571 | `endif |
philpem@0 | 572 | assign scall = op_raise & instruction[2]; |
philpem@0 | 573 | assign eret = op_b & (instruction[25:21] == 5'd30); |
philpem@0 | 574 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 575 | assign bret = op_b & (instruction[25:21] == 5'd31); |
philpem@0 | 576 | `endif |
philpem@0 | 577 | `ifdef CFG_USER_ENABLED |
philpem@0 | 578 | // Extract user opcode |
philpem@0 | 579 | assign user_opcode = instruction[10:0]; |
philpem@0 | 580 | `endif |
philpem@0 | 581 | // CSR read/write |
philpem@0 | 582 | assign csr_write_enable = op_wcsr; |
philpem@0 | 583 | |
philpem@0 | 584 | // Extract immediate from instruction |
philpem@0 | 585 | |
philpem@0 | 586 | assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); |
philpem@0 | 587 | assign select_high_immediate = op_andhi | op_orhi; |
philpem@0 | 588 | assign select_call_immediate = instruction[31]; |
philpem@0 | 589 | |
philpem@0 | 590 | assign high_immediate = {instruction[15:0], 16'h0000}; |
philpem@0 | 591 | assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; |
philpem@0 | 592 | assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; |
philpem@0 | 593 | assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; |
philpem@0 | 594 | |
philpem@0 | 595 | assign immediate = select_high_immediate == `TRUE |
philpem@0 | 596 | ? high_immediate |
philpem@0 | 597 | : extended_immediate; |
philpem@0 | 598 | |
philpem@0 | 599 | assign branch_offset = select_call_immediate == `TRUE |
philpem@0 | 600 | ? call_immediate |
philpem@0 | 601 | : branch_immediate; |
philpem@0 | 602 | |
philpem@0 | 603 | endmodule |
philpem@0 | 604 |