lm32_decoder.v

Sun, 06 Mar 2011 19:48:34 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 06 Mar 2011 19:48:34 +0000
changeset 16
5fb37de64edc
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rwxr-xr-x

Add JTAG interface for Xilinx Spartan 6 (Michael Walle)

Original-Source: Milkymist mailing list posting, 2010-09-23
Original-Message-Id: <201009232334.04219.michael@walle.cc>
Original-Author: Michael Walle <michael walle.cc>

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