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