lm32_decoder.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

reduce size of caches to fit in DE1 FPGA

The default cache size makes the Icache and Dcache "just a bit" too big to
fit in the EP2C20 FPGA on the DE1 board. This commit reduces the Icache and
Dcache sizes to the defaults shown in the LatticeMico32 Processor Reference
Manual (pages 36 and 37).

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