lm32_instruction_unit.v

Sun, 06 Mar 2011 21:03:32 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 06 Mar 2011 21:03:32 +0000
changeset 18
cc945f778cd7
parent 8
07be9df9fee8
child 26
73de224304c1
permissions
-rwxr-xr-x

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_instruction_unit.v
philpem@0 19 // Title : Instruction unit
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 is added. Fetching of
philpem@0 27 // : instructions can also be altered by branches predicted in D
philpem@0 28 // : stage of pipeline, and mispredicted branches in the X and M
philpem@0 29 // : stages of the pipeline.
philpem@0 30 // Version : 3.2
philpem@0 31 // : EBRs use SYNC resets instead of ASYNC resets.
philpem@0 32 // Version : 3.3
philpem@0 33 // : Support for a non-cacheable Instruction Memory that has a
philpem@0 34 // : single-cycle access latency. This memory can be accessed by
philpem@0 35 // : data port of LM32 (so that debugger has access to it).
philpem@0 36 // Version : 3.4
philpem@0 37 // : No change
philpem@0 38 // Version : 3.5
philpem@0 39 // : Bug fix: Inline memory is correctly generated if it is not a
philpem@0 40 // : power-of-two.
philpem@0 41 // : Bug fix: Fixed a bug that caused LM32 (configured without
philpem@0 42 // : instruction cache) to lock up in to an infinite loop due to a
philpem@0 43 // : instruction bus error when EBA was set to instruction inline
philpem@0 44 // : memory.
philpem@0 45 // =============================================================================
philpem@0 46
philpem@0 47 `include "lm32_include.v"
philpem@0 48
philpem@0 49 /////////////////////////////////////////////////////
philpem@0 50 // Module interface
philpem@0 51 /////////////////////////////////////////////////////
philpem@0 52
philpem@0 53 module lm32_instruction_unit (
philpem@0 54 // ----- Inputs -------
philpem@0 55 clk_i,
philpem@0 56 rst_i,
philpem@0 57 // From pipeline
philpem@0 58 stall_a,
philpem@0 59 stall_f,
philpem@0 60 stall_d,
philpem@0 61 stall_x,
philpem@0 62 stall_m,
philpem@0 63 valid_f,
philpem@0 64 valid_d,
philpem@0 65 kill_f,
philpem@0 66 branch_predict_taken_d,
philpem@0 67 branch_predict_address_d,
philpem@0 68 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 69 branch_taken_x,
philpem@0 70 branch_target_x,
philpem@0 71 `endif
philpem@0 72 exception_m,
philpem@0 73 branch_taken_m,
philpem@0 74 branch_mispredict_taken_m,
philpem@0 75 branch_target_m,
philpem@0 76 `ifdef CFG_ICACHE_ENABLED
philpem@0 77 iflush,
philpem@0 78 `endif
philpem@0 79 `ifdef CFG_DCACHE_ENABLED
philpem@0 80 dcache_restart_request,
philpem@0 81 dcache_refill_request,
philpem@0 82 dcache_refilling,
philpem@0 83 `endif
philpem@0 84 `ifdef CFG_IROM_ENABLED
philpem@0 85 irom_store_data_m,
philpem@0 86 irom_address_xm,
philpem@0 87 irom_we_xm,
philpem@0 88 `endif
philpem@0 89 `ifdef CFG_IWB_ENABLED
philpem@0 90 // From Wishbone
philpem@0 91 i_dat_i,
philpem@0 92 i_ack_i,
philpem@0 93 i_err_i,
philpem@0 94 `endif
philpem@0 95 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 96 jtag_read_enable,
philpem@0 97 jtag_write_enable,
philpem@0 98 jtag_write_data,
philpem@0 99 jtag_address,
philpem@0 100 `endif
philpem@0 101 // ----- Outputs -------
philpem@0 102 // To pipeline
philpem@0 103 pc_f,
philpem@0 104 pc_d,
philpem@0 105 pc_x,
philpem@0 106 pc_m,
philpem@0 107 pc_w,
philpem@0 108 `ifdef CFG_ICACHE_ENABLED
philpem@0 109 icache_stall_request,
philpem@0 110 icache_restart_request,
philpem@0 111 icache_refill_request,
philpem@0 112 icache_refilling,
philpem@0 113 `endif
philpem@0 114 `ifdef CFG_IROM_ENABLED
philpem@0 115 irom_data_m,
philpem@0 116 `endif
philpem@0 117 `ifdef CFG_IWB_ENABLED
philpem@0 118 // To Wishbone
philpem@0 119 i_dat_o,
philpem@0 120 i_adr_o,
philpem@0 121 i_cyc_o,
philpem@0 122 i_sel_o,
philpem@0 123 i_stb_o,
philpem@0 124 i_we_o,
philpem@0 125 i_cti_o,
philpem@0 126 i_lock_o,
philpem@0 127 i_bte_o,
philpem@0 128 `endif
philpem@0 129 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 130 jtag_read_data,
philpem@0 131 jtag_access_complete,
philpem@0 132 `endif
philpem@0 133 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 134 bus_error_d,
philpem@0 135 `endif
philpem@0 136 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 137 instruction_f,
philpem@0 138 `endif
philpem@0 139 instruction_d
philpem@0 140 );
philpem@0 141
philpem@0 142 /////////////////////////////////////////////////////
philpem@0 143 // Parameters
philpem@0 144 /////////////////////////////////////////////////////
philpem@0 145
philpem@0 146 parameter associativity = 1; // Associativity of the cache (Number of ways)
philpem@0 147 parameter sets = 512; // Number of sets
philpem@0 148 parameter bytes_per_line = 16; // Number of bytes per cache line
philpem@0 149 parameter base_address = 0; // Base address of cachable memory
philpem@0 150 parameter limit = 0; // Limit (highest address) of cachable memory
philpem@0 151
philpem@0 152 // For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
philpem@0 153 localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2;
philpem@0 154 localparam addr_offset_lsb = 2;
philpem@0 155 localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
philpem@0 156
philpem@0 157 /////////////////////////////////////////////////////
philpem@0 158 // Inputs
philpem@0 159 /////////////////////////////////////////////////////
philpem@0 160
philpem@0 161 input clk_i; // Clock
philpem@0 162 input rst_i; // Reset
philpem@0 163
philpem@0 164 input stall_a; // Stall A stage instruction
philpem@0 165 input stall_f; // Stall F stage instruction
philpem@0 166 input stall_d; // Stall D stage instruction
philpem@0 167 input stall_x; // Stall X stage instruction
philpem@0 168 input stall_m; // Stall M stage instruction
philpem@0 169 input valid_f; // Instruction in F stage is valid
philpem@0 170 input valid_d; // Instruction in D stage is valid
philpem@0 171 input kill_f; // Kill instruction in F stage
philpem@0 172
philpem@0 173 input branch_predict_taken_d; // Branch is predicted taken in D stage
philpem@0 174 input [`LM32_PC_RNG] branch_predict_address_d; // Branch target address
philpem@0 175
philpem@0 176 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 177 input branch_taken_x; // Branch instruction in X stage is taken
philpem@0 178 input [`LM32_PC_RNG] branch_target_x; // Target PC of X stage branch instruction
philpem@0 179 `endif
philpem@0 180 input exception_m;
philpem@0 181 input branch_taken_m; // Branch instruction in M stage is taken
philpem@0 182 input branch_mispredict_taken_m; // Branch instruction in M stage is mispredicted as taken
philpem@0 183 input [`LM32_PC_RNG] branch_target_m; // Target PC of M stage branch instruction
philpem@0 184
philpem@0 185 `ifdef CFG_ICACHE_ENABLED
philpem@0 186 input iflush; // Flush instruction cache
philpem@0 187 `endif
philpem@0 188 `ifdef CFG_DCACHE_ENABLED
philpem@0 189 input dcache_restart_request; // Restart instruction that caused a data cache miss
philpem@0 190 input dcache_refill_request; // Request to refill data cache
philpem@0 191 input dcache_refilling;
philpem@0 192 `endif
philpem@0 193
philpem@0 194 `ifdef CFG_IROM_ENABLED
philpem@0 195 input [`LM32_WORD_RNG] irom_store_data_m; // Data from load-store unit
philpem@0 196 input [`LM32_WORD_RNG] irom_address_xm; // Address from load-store unit
philpem@0 197 input irom_we_xm; // Indicates if memory operation is load or store
philpem@0 198 `endif
philpem@0 199
philpem@0 200 `ifdef CFG_IWB_ENABLED
philpem@0 201 input [`LM32_WORD_RNG] i_dat_i; // Instruction Wishbone interface read data
philpem@0 202 input i_ack_i; // Instruction Wishbone interface acknowledgement
philpem@0 203 input i_err_i; // Instruction Wishbone interface error
philpem@0 204 `endif
philpem@0 205
philpem@0 206 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 207 input jtag_read_enable; // JTAG read memory request
philpem@0 208 input jtag_write_enable; // JTAG write memory request
philpem@0 209 input [`LM32_BYTE_RNG] jtag_write_data; // JTAG wrirte data
philpem@0 210 input [`LM32_WORD_RNG] jtag_address; // JTAG read/write address
philpem@0 211 `endif
philpem@0 212
philpem@0 213 /////////////////////////////////////////////////////
philpem@0 214 // Outputs
philpem@0 215 /////////////////////////////////////////////////////
philpem@0 216
philpem@0 217 output [`LM32_PC_RNG] pc_f; // F stage PC
philpem@0 218 reg [`LM32_PC_RNG] pc_f;
philpem@0 219 output [`LM32_PC_RNG] pc_d; // D stage PC
philpem@0 220 reg [`LM32_PC_RNG] pc_d;
philpem@0 221 output [`LM32_PC_RNG] pc_x; // X stage PC
philpem@0 222 reg [`LM32_PC_RNG] pc_x;
philpem@0 223 output [`LM32_PC_RNG] pc_m; // M stage PC
philpem@0 224 reg [`LM32_PC_RNG] pc_m;
philpem@0 225 output [`LM32_PC_RNG] pc_w; // W stage PC
philpem@0 226 reg [`LM32_PC_RNG] pc_w;
philpem@0 227
philpem@0 228 `ifdef CFG_ICACHE_ENABLED
philpem@0 229 output icache_stall_request; // Instruction cache stall request
philpem@0 230 wire icache_stall_request;
philpem@0 231 output icache_restart_request; // Request to restart instruction that cached instruction cache miss
philpem@0 232 wire icache_restart_request;
philpem@0 233 output icache_refill_request; // Instruction cache refill request
philpem@0 234 wire icache_refill_request;
philpem@0 235 output icache_refilling; // Indicates the icache is refilling
philpem@0 236 wire icache_refilling;
philpem@0 237 `endif
philpem@0 238
philpem@0 239 `ifdef CFG_IROM_ENABLED
philpem@0 240 output [`LM32_WORD_RNG] irom_data_m; // Data to load-store unit on load
philpem@0 241 wire [`LM32_WORD_RNG] irom_data_m;
philpem@0 242 `endif
philpem@0 243
philpem@0 244 `ifdef CFG_IWB_ENABLED
philpem@0 245 output [`LM32_WORD_RNG] i_dat_o; // Instruction Wishbone interface write data
philpem@0 246 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 247 reg [`LM32_WORD_RNG] i_dat_o;
philpem@0 248 `else
philpem@0 249 wire [`LM32_WORD_RNG] i_dat_o;
philpem@0 250 `endif
philpem@0 251 output [`LM32_WORD_RNG] i_adr_o; // Instruction Wishbone interface address
philpem@0 252 reg [`LM32_WORD_RNG] i_adr_o;
philpem@0 253 output i_cyc_o; // Instruction Wishbone interface cycle
philpem@0 254 reg i_cyc_o;
philpem@0 255 output [`LM32_BYTE_SELECT_RNG] i_sel_o; // Instruction Wishbone interface byte select
philpem@0 256 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 257 reg [`LM32_BYTE_SELECT_RNG] i_sel_o;
philpem@0 258 `else
philpem@0 259 wire [`LM32_BYTE_SELECT_RNG] i_sel_o;
philpem@0 260 `endif
philpem@0 261 output i_stb_o; // Instruction Wishbone interface strobe
philpem@0 262 reg i_stb_o;
philpem@0 263 output i_we_o; // Instruction Wishbone interface write enable
philpem@0 264 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 265 reg i_we_o;
philpem@0 266 `else
philpem@0 267 wire i_we_o;
philpem@0 268 `endif
philpem@0 269 output [`LM32_CTYPE_RNG] i_cti_o; // Instruction Wishbone interface cycle type
philpem@0 270 reg [`LM32_CTYPE_RNG] i_cti_o;
philpem@0 271 output i_lock_o; // Instruction Wishbone interface lock bus
philpem@0 272 reg i_lock_o;
philpem@0 273 output [`LM32_BTYPE_RNG] i_bte_o; // Instruction Wishbone interface burst type
philpem@0 274 wire [`LM32_BTYPE_RNG] i_bte_o;
philpem@0 275 `endif
philpem@0 276
philpem@0 277 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 278 output [`LM32_BYTE_RNG] jtag_read_data; // Data read for JTAG interface
philpem@0 279 reg [`LM32_BYTE_RNG] jtag_read_data;
philpem@0 280 output jtag_access_complete; // Requested memory access by JTAG interface is complete
philpem@0 281 wire jtag_access_complete;
philpem@0 282 `endif
philpem@0 283
philpem@0 284 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 285 output bus_error_d; // Indicates a bus error occured while fetching the instruction
philpem@0 286 reg bus_error_d;
philpem@0 287 `endif
philpem@0 288 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 289 output [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction (only to have register indices extracted from)
philpem@0 290 wire [`LM32_INSTRUCTION_RNG] instruction_f;
philpem@0 291 `endif
philpem@0 292 output [`LM32_INSTRUCTION_RNG] instruction_d; // D stage instruction to be decoded
philpem@0 293 reg [`LM32_INSTRUCTION_RNG] instruction_d;
philpem@0 294
philpem@0 295 /////////////////////////////////////////////////////
philpem@0 296 // Internal nets and registers
philpem@0 297 /////////////////////////////////////////////////////
philpem@0 298
philpem@0 299 reg [`LM32_PC_RNG] pc_a; // A stage PC
philpem@0 300
philpem@0 301 `ifdef LM32_CACHE_ENABLED
philpem@0 302 reg [`LM32_PC_RNG] restart_address; // Address to restart from after a cache miss
philpem@0 303 `endif
philpem@0 304
philpem@0 305 `ifdef CFG_ICACHE_ENABLED
philpem@0 306 wire icache_read_enable_f; // Indicates if instruction cache miss is valid
philpem@0 307 wire [`LM32_PC_RNG] icache_refill_address; // Address that caused cache miss
philpem@0 308 reg icache_refill_ready; // Indicates when next word of refill data is ready to be written to cache
philpem@0 309 reg [`LM32_INSTRUCTION_RNG] icache_refill_data; // Next word of refill data, fetched from Wishbone
philpem@0 310 wire [`LM32_INSTRUCTION_RNG] icache_data_f; // Instruction fetched from instruction cache
philpem@0 311 wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
philpem@0 312 wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
philpem@0 313 wire last_word; // Indicates if this is the last word in the cache line
philpem@0 314 wire [`LM32_PC_RNG] first_address; // First cache refill address
philpem@0 315 `else
philpem@0 316 `ifdef CFG_IWB_ENABLED
philpem@0 317 reg [`LM32_INSTRUCTION_RNG] wb_data_f; // Instruction fetched from Wishbone
philpem@0 318 `endif
philpem@0 319 `endif
philpem@0 320 `ifdef CFG_IROM_ENABLED
philpem@0 321 wire irom_select_a; // Indicates if A stage PC maps to a ROM address
philpem@0 322 reg irom_select_f; // Indicates if F stage PC maps to a ROM address
philpem@0 323 wire [`LM32_INSTRUCTION_RNG] irom_data_f; // Instruction fetched from ROM
philpem@0 324 `endif
philpem@0 325 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 326 `else
philpem@0 327 wire [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction
philpem@0 328 `endif
philpem@0 329 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 330 reg bus_error_f; // Indicates if a bus error occured while fetching the instruction in the F stage
philpem@0 331 `endif
philpem@0 332
philpem@0 333 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 334 reg jtag_access; // Indicates if a JTAG WB access is in progress
philpem@0 335 `endif
philpem@0 336
philpem@0 337 /////////////////////////////////////////////////////
philpem@0 338 // Functions
philpem@0 339 /////////////////////////////////////////////////////
philpem@0 340
philpem@0 341 `include "lm32_functions.v"
philpem@0 342
philpem@0 343 /////////////////////////////////////////////////////
philpem@0 344 // Instantiations
philpem@0 345 /////////////////////////////////////////////////////
philpem@0 346
philpem@0 347 // Instruction ROM
philpem@0 348 `ifdef CFG_IROM_ENABLED
philpem@0 349 pmi_ram_dp_true
philpem@0 350 #(
philpem@0 351 // ----- Parameters -------
philpem@0 352 .pmi_family (`LATTICE_FAMILY),
philpem@0 353
philpem@0 354 //.pmi_addr_depth_a (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 355 //.pmi_addr_width_a ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 356 //.pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 357 //.pmi_addr_depth_b (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 358 //.pmi_addr_width_b ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 359 //.pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 360
philpem@0 361 .pmi_addr_depth_a (`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1),
philpem@0 362 .pmi_addr_width_a (clogb2_v1(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)),
philpem@0 363 .pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 364 .pmi_addr_depth_b (`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1),
philpem@0 365 .pmi_addr_width_b (clogb2_v1(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)),
philpem@0 366 .pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 367
philpem@0 368 .pmi_regmode_a ("noreg"),
philpem@0 369 .pmi_regmode_b ("noreg"),
philpem@0 370 .pmi_gsr ("enable"),
philpem@0 371 .pmi_resetmode ("sync"),
philpem@0 372 .pmi_init_file (`CFG_IROM_INIT_FILE),
philpem@0 373 .pmi_init_file_format (`CFG_IROM_INIT_FILE_FORMAT),
philpem@0 374 .module_type ("pmi_ram_dp_true")
philpem@0 375 )
philpem@0 376 ram (
philpem@0 377 // ----- Inputs -------
philpem@0 378 .ClockA (clk_i),
philpem@0 379 .ClockB (clk_i),
philpem@0 380 .ResetA (rst_i),
philpem@0 381 .ResetB (rst_i),
philpem@0 382 .DataInA ({32{1'b0}}),
philpem@0 383 .DataInB (irom_store_data_m),
philpem@0 384 .AddressA (pc_a[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
philpem@0 385 .AddressB (irom_address_xm[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
philpem@0 386 .ClockEnA (!stall_a),
philpem@0 387 .ClockEnB (!stall_x || !stall_m),
philpem@0 388 .WrA (`FALSE),
philpem@0 389 .WrB (irom_we_xm),
philpem@0 390 // ----- Outputs -------
philpem@0 391 .QA (irom_data_f),
philpem@0 392 .QB (irom_data_m)
philpem@0 393 );
philpem@0 394 `endif
philpem@0 395
philpem@0 396 `ifdef CFG_ICACHE_ENABLED
philpem@0 397 // Instruction cache
philpem@0 398 lm32_icache #(
philpem@0 399 .associativity (associativity),
philpem@0 400 .sets (sets),
philpem@0 401 .bytes_per_line (bytes_per_line),
philpem@0 402 .base_address (base_address),
philpem@0 403 .limit (limit)
philpem@0 404 ) icache (
philpem@0 405 // ----- Inputs -----
philpem@0 406 .clk_i (clk_i),
philpem@0 407 .rst_i (rst_i),
philpem@0 408 .stall_a (stall_a),
philpem@0 409 .stall_f (stall_f),
philpem@0 410 .branch_predict_taken_d (branch_predict_taken_d),
philpem@0 411 .valid_d (valid_d),
philpem@0 412 .address_a (pc_a),
philpem@0 413 .address_f (pc_f),
philpem@0 414 .read_enable_f (icache_read_enable_f),
philpem@0 415 .refill_ready (icache_refill_ready),
philpem@0 416 .refill_data (icache_refill_data),
philpem@0 417 .iflush (iflush),
philpem@0 418 // ----- Outputs -----
philpem@0 419 .stall_request (icache_stall_request),
philpem@0 420 .restart_request (icache_restart_request),
philpem@0 421 .refill_request (icache_refill_request),
philpem@0 422 .refill_address (icache_refill_address),
philpem@0 423 .refilling (icache_refilling),
philpem@0 424 .inst (icache_data_f)
philpem@0 425 );
philpem@0 426 `endif
philpem@0 427
philpem@0 428 /////////////////////////////////////////////////////
philpem@0 429 // Combinational Logic
philpem@0 430 /////////////////////////////////////////////////////
philpem@0 431
philpem@0 432 `ifdef CFG_ICACHE_ENABLED
philpem@0 433 // Generate signal that indicates when instruction cache misses are valid
philpem@0 434 assign icache_read_enable_f = (valid_f == `TRUE)
philpem@0 435 && (kill_f == `FALSE)
philpem@0 436 `ifdef CFG_DCACHE_ENABLED
philpem@0 437 && (dcache_restart_request == `FALSE)
philpem@0 438 `endif
philpem@0 439 `ifdef CFG_IROM_ENABLED
philpem@0 440 && (irom_select_f == `FALSE)
philpem@0 441 `endif
philpem@0 442 ;
philpem@0 443 `endif
philpem@0 444
philpem@0 445 // Compute address of next instruction to fetch
philpem@0 446 always @(*)
philpem@0 447 begin
philpem@0 448 // The request from the latest pipeline stage must take priority
philpem@0 449 `ifdef CFG_DCACHE_ENABLED
philpem@0 450 if (dcache_restart_request == `TRUE)
philpem@0 451 pc_a = restart_address;
philpem@0 452 else
philpem@0 453 `endif
philpem@0 454 if (branch_taken_m == `TRUE)
philpem@0 455 if ((branch_mispredict_taken_m == `TRUE) && (exception_m == `FALSE))
philpem@0 456 pc_a = pc_x;
philpem@0 457 else
philpem@0 458 pc_a = branch_target_m;
philpem@0 459 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 460 else if (branch_taken_x == `TRUE)
philpem@0 461 pc_a = branch_target_x;
philpem@0 462 `endif
philpem@0 463 else
philpem@0 464 if ( (valid_d == `TRUE) && (branch_predict_taken_d == `TRUE) )
philpem@0 465 pc_a = branch_predict_address_d;
philpem@0 466 else
philpem@0 467 `ifdef CFG_ICACHE_ENABLED
philpem@0 468 if (icache_restart_request == `TRUE)
philpem@0 469 pc_a = restart_address;
philpem@0 470 else
philpem@0 471 `endif
philpem@0 472 pc_a = pc_f + 1'b1;
philpem@0 473 end
philpem@0 474
philpem@0 475 // Select where instruction should be fetched from
philpem@0 476 `ifdef CFG_IROM_ENABLED
philpem@0 477 assign irom_select_a = ({pc_a, 2'b00} >= `CFG_IROM_BASE_ADDRESS) && ({pc_a, 2'b00} <= `CFG_IROM_LIMIT);
philpem@0 478 `endif
philpem@0 479
philpem@0 480 // Select instruction from selected source
philpem@0 481 `ifdef CFG_ICACHE_ENABLED
philpem@0 482 `ifdef CFG_IROM_ENABLED
philpem@0 483 assign instruction_f = irom_select_f == `TRUE ? irom_data_f : icache_data_f;
philpem@0 484 `else
philpem@0 485 assign instruction_f = icache_data_f;
philpem@0 486 `endif
philpem@0 487 `else
philpem@0 488 `ifdef CFG_IROM_ENABLED
philpem@0 489 `ifdef CFG_IWB_ENABLED
philpem@0 490 assign instruction_f = irom_select_f == `TRUE ? irom_data_f : wb_data_f;
philpem@0 491 `else
philpem@0 492 assign instruction_f = irom_data_f;
philpem@0 493 `endif
philpem@0 494 `else
philpem@0 495 assign instruction_f = wb_data_f;
philpem@0 496 `endif
philpem@0 497 `endif
philpem@0 498
philpem@0 499 // Unused/constant Wishbone signals
philpem@0 500 `ifdef CFG_IWB_ENABLED
philpem@0 501 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 502 `else
philpem@0 503 assign i_dat_o = 32'd0;
philpem@0 504 assign i_we_o = `FALSE;
philpem@0 505 assign i_sel_o = 4'b1111;
philpem@0 506 `endif
philpem@0 507 assign i_bte_o = `LM32_BTYPE_LINEAR;
philpem@0 508 `endif
philpem@0 509
philpem@0 510 `ifdef CFG_ICACHE_ENABLED
philpem@0 511 // Determine parameters for next cache refill Wishbone access
philpem@0 512 generate
philpem@0 513 case (bytes_per_line)
philpem@0 514 4:
philpem@0 515 begin
philpem@0 516 assign first_cycle_type = `LM32_CTYPE_END;
philpem@0 517 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 518 assign last_word = `TRUE;
philpem@0 519 assign first_address = icache_refill_address;
philpem@0 520 end
philpem@0 521 8:
philpem@0 522 begin
philpem@0 523 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 524 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 525 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1;
philpem@0 526 assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
philpem@0 527 end
philpem@0 528 16:
philpem@0 529 begin
philpem@0 530 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 531 assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
philpem@0 532 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11;
philpem@0 533 assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
philpem@0 534 end
philpem@0 535 endcase
philpem@0 536 endgenerate
philpem@0 537 `endif
philpem@0 538
philpem@0 539 /////////////////////////////////////////////////////
philpem@0 540 // Sequential Logic
philpem@0 541 /////////////////////////////////////////////////////
philpem@0 542
philpem@0 543 // PC
philpem@0 544 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 545 begin
philpem@0 546 if (rst_i == `TRUE)
philpem@0 547 begin
philpem@0 548 pc_f <= (`CFG_EBA_RESET-4)/4;
philpem@0 549 pc_d <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 550 pc_x <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 551 pc_m <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 552 pc_w <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 553 end
philpem@0 554 else
philpem@0 555 begin
philpem@0 556 if (stall_f == `FALSE)
philpem@0 557 pc_f <= pc_a;
philpem@0 558 if (stall_d == `FALSE)
philpem@0 559 pc_d <= pc_f;
philpem@0 560 if (stall_x == `FALSE)
philpem@0 561 pc_x <= pc_d;
philpem@0 562 if (stall_m == `FALSE)
philpem@0 563 pc_m <= pc_x;
philpem@0 564 pc_w <= pc_m;
philpem@0 565 end
philpem@0 566 end
philpem@0 567
philpem@0 568 `ifdef LM32_CACHE_ENABLED
philpem@0 569 // Address to restart from after a cache miss has been handled
philpem@0 570 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 571 begin
philpem@0 572 if (rst_i == `TRUE)
philpem@0 573 restart_address <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 574 else
philpem@0 575 begin
philpem@0 576 `ifdef CFG_DCACHE_ENABLED
philpem@0 577 `ifdef CFG_ICACHE_ENABLED
philpem@0 578 // D-cache restart address must take priority, otherwise instructions will be lost
philpem@0 579 if (dcache_refill_request == `TRUE)
philpem@0 580 restart_address <= pc_w;
philpem@0 581 else if ((icache_refill_request == `TRUE) && (!dcache_refilling) && (!dcache_restart_request))
philpem@0 582 restart_address <= icache_refill_address;
philpem@0 583 `else
philpem@0 584 if (dcache_refill_request == `TRUE)
philpem@0 585 restart_address <= pc_w;
philpem@0 586 `endif
philpem@0 587 `else
philpem@0 588 `ifdef CFG_ICACHE_ENABLED
philpem@0 589 if (icache_refill_request == `TRUE)
philpem@0 590 restart_address <= icache_refill_address;
philpem@0 591 `endif
philpem@0 592 `endif
philpem@0 593 end
philpem@0 594 end
philpem@0 595 `endif
philpem@0 596
philpem@0 597 // Record where instruction was fetched from
philpem@0 598 `ifdef CFG_IROM_ENABLED
philpem@0 599 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 600 begin
philpem@0 601 if (rst_i == `TRUE)
philpem@0 602 irom_select_f <= `FALSE;
philpem@0 603 else
philpem@0 604 begin
philpem@0 605 if (stall_f == `FALSE)
philpem@0 606 irom_select_f <= irom_select_a;
philpem@0 607 end
philpem@0 608 end
philpem@0 609 `endif
philpem@0 610
philpem@0 611 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 612 assign jtag_access_complete = (i_cyc_o == `TRUE) && ((i_ack_i == `TRUE) || (i_err_i == `TRUE)) && (jtag_access == `TRUE);
philpem@0 613 always @(*)
philpem@0 614 begin
philpem@0 615 case (jtag_address[1:0])
philpem@0 616 2'b00: jtag_read_data = i_dat_i[`LM32_BYTE_3_RNG];
philpem@0 617 2'b01: jtag_read_data = i_dat_i[`LM32_BYTE_2_RNG];
philpem@0 618 2'b10: jtag_read_data = i_dat_i[`LM32_BYTE_1_RNG];
philpem@0 619 2'b11: jtag_read_data = i_dat_i[`LM32_BYTE_0_RNG];
philpem@0 620 endcase
philpem@0 621 end
philpem@0 622 `endif
philpem@0 623
philpem@0 624 `ifdef CFG_IWB_ENABLED
philpem@0 625 // Instruction Wishbone interface
philpem@0 626 `ifdef CFG_ICACHE_ENABLED
philpem@0 627 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 628 begin
philpem@0 629 if (rst_i == `TRUE)
philpem@0 630 begin
philpem@0 631 i_cyc_o <= `FALSE;
philpem@0 632 i_stb_o <= `FALSE;
philpem@0 633 i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 634 i_cti_o <= `LM32_CTYPE_END;
philpem@0 635 i_lock_o <= `FALSE;
philpem@0 636 icache_refill_data <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 637 icache_refill_ready <= `FALSE;
philpem@0 638 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 639 bus_error_f <= `FALSE;
philpem@0 640 `endif
philpem@0 641 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 642 i_we_o <= `FALSE;
philpem@0 643 i_sel_o <= 4'b1111;
philpem@0 644 jtag_access <= `FALSE;
philpem@0 645 `endif
philpem@0 646 end
philpem@0 647 else
philpem@0 648 begin
philpem@0 649 icache_refill_ready <= `FALSE;
philpem@0 650 // Is a cycle in progress?
philpem@0 651 if (i_cyc_o == `TRUE)
philpem@0 652 begin
philpem@0 653 // Has cycle completed?
philpem@0 654 if ((i_ack_i == `TRUE) || (i_err_i == `TRUE))
philpem@0 655 begin
philpem@0 656 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 657 if (jtag_access == `TRUE)
philpem@0 658 begin
philpem@0 659 i_cyc_o <= `FALSE;
philpem@0 660 i_stb_o <= `FALSE;
philpem@0 661 i_we_o <= `FALSE;
philpem@0 662 jtag_access <= `FALSE;
philpem@0 663 end
philpem@0 664 else
philpem@0 665 `endif
philpem@0 666 begin
philpem@0 667 if (last_word == `TRUE)
philpem@0 668 begin
philpem@0 669 // Cache line fill complete
philpem@0 670 i_cyc_o <= `FALSE;
philpem@0 671 i_stb_o <= `FALSE;
philpem@0 672 i_lock_o <= `FALSE;
philpem@0 673 end
philpem@0 674 // Fetch next word in cache line
philpem@0 675 i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
philpem@0 676 i_cti_o <= next_cycle_type;
philpem@0 677 // Write fetched data into instruction cache
philpem@0 678 icache_refill_ready <= `TRUE;
philpem@0 679 icache_refill_data <= i_dat_i;
philpem@0 680 end
philpem@0 681 end
philpem@0 682 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 683 if (i_err_i == `TRUE)
philpem@0 684 begin
philpem@0 685 bus_error_f <= `TRUE;
philpem@0 686 $display ("Instruction bus error. Address: %x", i_adr_o);
philpem@0 687 end
philpem@0 688 `endif
philpem@0 689 end
philpem@0 690 else
philpem@0 691 begin
philpem@0 692 if ((icache_refill_request == `TRUE) && (icache_refill_ready == `FALSE))
philpem@0 693 begin
philpem@0 694 // Read first word of cache line
philpem@0 695 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 696 i_sel_o <= 4'b1111;
philpem@0 697 `endif
philpem@0 698 i_adr_o <= {first_address, 2'b00};
philpem@0 699 i_cyc_o <= `TRUE;
philpem@0 700 i_stb_o <= `TRUE;
philpem@0 701 i_cti_o <= first_cycle_type;
philpem@0 702 //i_lock_o <= `TRUE;
philpem@0 703 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 704 bus_error_f <= `FALSE;
philpem@0 705 `endif
philpem@0 706 end
philpem@0 707 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 708 else
philpem@0 709 begin
philpem@0 710 if ((jtag_read_enable == `TRUE) || (jtag_write_enable == `TRUE))
philpem@0 711 begin
philpem@0 712 case (jtag_address[1:0])
philpem@0 713 2'b00: i_sel_o <= 4'b1000;
philpem@0 714 2'b01: i_sel_o <= 4'b0100;
philpem@0 715 2'b10: i_sel_o <= 4'b0010;
philpem@0 716 2'b11: i_sel_o <= 4'b0001;
philpem@0 717 endcase
philpem@0 718 i_adr_o <= jtag_address;
philpem@0 719 i_dat_o <= {4{jtag_write_data}};
philpem@0 720 i_cyc_o <= `TRUE;
philpem@0 721 i_stb_o <= `TRUE;
philpem@0 722 i_we_o <= jtag_write_enable;
philpem@0 723 i_cti_o <= `LM32_CTYPE_END;
philpem@0 724 jtag_access <= `TRUE;
philpem@0 725 end
philpem@0 726 end
philpem@0 727 `endif
philpem@0 728 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 729 // Clear bus error when exception taken, otherwise they would be
philpem@0 730 // continually generated if exception handler is cached
philpem@0 731 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 732 if (branch_taken_x == `TRUE)
philpem@0 733 bus_error_f <= `FALSE;
philpem@0 734 `endif
philpem@0 735 if (branch_taken_m == `TRUE)
philpem@0 736 bus_error_f <= `FALSE;
philpem@0 737 `endif
philpem@0 738 end
philpem@0 739 end
philpem@0 740 end
philpem@0 741 `else
philpem@0 742 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 743 begin
philpem@0 744 if (rst_i == `TRUE)
philpem@0 745 begin
philpem@0 746 i_cyc_o <= `FALSE;
philpem@0 747 i_stb_o <= `FALSE;
philpem@0 748 i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 749 i_cti_o <= `LM32_CTYPE_END;
philpem@0 750 i_lock_o <= `FALSE;
philpem@0 751 wb_data_f <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 752 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 753 bus_error_f <= `FALSE;
philpem@0 754 `endif
philpem@0 755 end
philpem@0 756 else
philpem@0 757 begin
philpem@0 758 // Is a cycle in progress?
philpem@0 759 if (i_cyc_o == `TRUE)
philpem@0 760 begin
philpem@0 761 // Has cycle completed?
philpem@0 762 if((i_ack_i == `TRUE) || (i_err_i == `TRUE))
philpem@0 763 begin
philpem@0 764 // Cycle complete
philpem@0 765 i_cyc_o <= `FALSE;
philpem@0 766 i_stb_o <= `FALSE;
philpem@0 767 // Register fetched instruction
philpem@0 768 wb_data_f <= i_dat_i;
philpem@0 769 end
philpem@0 770 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 771 if (i_err_i == `TRUE)
philpem@0 772 begin
philpem@0 773 bus_error_f <= `TRUE;
philpem@0 774 $display ("Instruction bus error. Address: %x", i_adr_o);
philpem@0 775 end
philpem@0 776 `endif
philpem@0 777 end
philpem@0 778 else
philpem@0 779 begin
philpem@0 780 // Wait for an instruction fetch from an external address
philpem@0 781 if ( (stall_a == `FALSE)
philpem@0 782 `ifdef CFG_IROM_ENABLED
philpem@0 783 && (irom_select_a == `FALSE)
philpem@0 784 `endif
philpem@0 785 )
philpem@0 786 begin
philpem@0 787 // Fetch instruction
philpem@0 788 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 789 i_sel_o <= 4'b1111;
philpem@0 790 `endif
philpem@0 791 i_adr_o <= {pc_a, 2'b00};
philpem@0 792 i_cyc_o <= `TRUE;
philpem@0 793 i_stb_o <= `TRUE;
philpem@0 794 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 795 bus_error_f <= `FALSE;
philpem@0 796 `endif
philpem@0 797 end
philpem@0 798 else
philpem@0 799 begin
philpem@0 800 if ( (stall_a == `FALSE)
philpem@0 801 `ifdef CFG_IROM_ENABLED
philpem@0 802 && (irom_select_a == `TRUE)
philpem@0 803 `endif
philpem@0 804 )
philpem@0 805 begin
philpem@0 806 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 807 bus_error_f <= `FALSE;
philpem@0 808 `endif
philpem@0 809 end
philpem@0 810 end
philpem@0 811 end
philpem@0 812 end
philpem@0 813 end
philpem@0 814 `endif
philpem@0 815 `endif
philpem@0 816
philpem@0 817 // Instruction register
philpem@0 818 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 819 begin
philpem@0 820 if (rst_i == `TRUE)
philpem@0 821 begin
philpem@0 822 instruction_d <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 823 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 824 bus_error_d <= `FALSE;
philpem@0 825 `endif
philpem@0 826 end
philpem@0 827 else
philpem@0 828 begin
philpem@0 829 if (stall_d == `FALSE)
philpem@0 830 begin
philpem@0 831 instruction_d <= instruction_f;
philpem@0 832 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 833 bus_error_d <= bus_error_f;
philpem@0 834 `endif
philpem@0 835 end
philpem@0 836 end
philpem@0 837 end
philpem@0 838
philpem@0 839 endmodule