├── .gitignore ├── README.md └── soc ├── .gitignore ├── Makefile ├── attosoc.v ├── debug_insert.py ├── firmware.hex ├── versa.lpf ├── versa5g_openocd.cfg └── wrapper.v /.gitignore: -------------------------------------------------------------------------------- 1 | *.bit 2 | *.json 3 | *.pyc 4 | *.config 5 | *.log 6 | *.svf 7 | *.dat 8 | *.tmp 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HRT - Hot ReconfiguraTion 2 | 3 | FPL 2022 demo special edition! 4 | 5 | This is a _very_ basic proof-of-concept of loading a modified FPGA design without losing state, using the partial reconfiguration-like features of the ECP5. 6 | 7 | It demonstrates debug insertion on a simple picorv32 based SoC. In the base design the LEDs are connected to a MMIO register and display computed primes; this is reconfigured at runtime by hot-reconfiguring routing bits to output the current PC register content on the LEDs instead. All this without even stopping the clock! 8 | 9 | To run the demo, first run `make prog` to load the base design to the board. Then run `make prog_dbg` to apply the debug insertion patch (without stopping or resetting the SoC) and `make prog_reset` to remove the patch and restore the original routing. 10 | 11 | This requires an ECP5 Versa-5G board (frame addressing for densities other than the ECP5-45k hasn't been reverse engineered yet). 12 | -------------------------------------------------------------------------------- /soc/.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | *.bit 3 | *.config 4 | *.log 5 | -------------------------------------------------------------------------------- /soc/Makefile: -------------------------------------------------------------------------------- 1 | all: soc.svf 2 | 3 | soc.json: attosoc.v wrapper.v 4 | yosys -p "synth_ecp5 -top top -nowidelut -nobram -nolutram -json $@" $^ 5 | soc.config: soc.json versa.lpf 6 | nextpnr-ecp5 --json soc.json --textcfg $@ --lpf versa.lpf --um5g-45k --package CABGA381 --write soc_pnr.json --disable-router-lutperm 7 | soc.svf: soc.config 8 | ecppack --compress --background --svf $@ $^ 9 | prog: soc.svf 10 | openocd -f versa5g_openocd.cfg -c "transport select jtag; init; svf quiet $<; exit" 11 | 12 | soc_dbg.config: soc_pnr.json 13 | nextpnr-ecp5 --um5g-45k --package CABGA381 --json soc_pnr.json --no-pack --no-place --pre-route debug_insert.py --textcfg $@ 14 | 15 | soc_dbg_unrouted.config: soc_dbg.config 16 | 17 | soc_dbg_unrouted.svf: soc.config soc_dbg_unrouted.config 18 | ecppack --background --svf $@ --delta $^ 19 | 20 | soc_dbg.svf: soc_dbg_unrouted.config soc_dbg.config 21 | ecppack --background --svf $@ --delta $^ 22 | 23 | prog_dbg: soc_dbg_unrouted.svf soc_dbg.svf 24 | openocd -f versa5g_openocd.cfg -c "transport select jtag; init; svf quiet soc_dbg_unrouted.svf; exit" 25 | openocd -f versa5g_openocd.cfg -c "transport select jtag; init; svf quiet soc_dbg.svf; exit" 26 | 27 | soc_unrouted_dbg.svf: soc_dbg.config soc_dbg_unrouted.config 28 | ecppack --background --svf $@ --delta $^ 29 | 30 | soc_rerouted.svf: soc_dbg_unrouted.config soc.config 31 | ecppack --background --svf $@ --delta $^ 32 | 33 | prog_reset: soc_unrouted_dbg.svf soc_rerouted.svf 34 | openocd -f versa5g_openocd.cfg -c "transport select jtag; init; svf quiet soc_unrouted_dbg.svf; exit" 35 | openocd -f versa5g_openocd.cfg -c "transport select jtag; init; svf quiet soc_rerouted.svf; exit" 36 | 37 | 38 | clean: 39 | rm *.config *.svf *.json 40 | 41 | .PHONY: prog 42 | .PRECIOUS: soc.json soc.config -------------------------------------------------------------------------------- /soc/attosoc.v: -------------------------------------------------------------------------------- 1 | /* 2 | * ECP5 PicoRV32 demo 3 | * 4 | * Copyright (C) 2017 Claire Xenia Wolf 5 | * Copyright (C) 2018 gatecat 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | `ifdef PICORV32_V 22 | `error "attosoc.v must be read before picorv32.v!" 23 | `endif 24 | 25 | `define PICORV32_REGS picosoc_regs 26 | 27 | module attosoc ( 28 | input clk, reset, 29 | output reg [7:0] led 30 | ); 31 | 32 | reg [5:0] reset_cnt = 0; 33 | wire resetn = &reset_cnt; 34 | 35 | always @(posedge clk) begin 36 | if (reset) 37 | reset_cnt <= 0; 38 | else 39 | reset_cnt <= reset_cnt + !resetn; 40 | end 41 | 42 | parameter integer MEM_WORDS = 256; 43 | parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory 44 | parameter [31:0] PROGADDR_RESET = 32'h 0000_0000; // ROM at 0x0 45 | parameter integer ROM_BYTES = 256; 46 | 47 | reg [7:0] rom [0:ROM_BYTES-1]; 48 | wire [31:0] rom_rdata = {rom[mem_addr+3], rom[mem_addr+2], rom[mem_addr+1], rom[mem_addr+0]}; 49 | initial $readmemh("firmware.hex", rom); 50 | 51 | wire mem_valid; 52 | wire mem_instr; 53 | wire mem_ready; 54 | wire [31:0] mem_addr; 55 | wire [31:0] mem_wdata; 56 | wire [3:0] mem_wstrb; 57 | wire [31:0] mem_rdata; 58 | 59 | wire rom_ready = mem_valid && mem_addr[31:24] == 8'h00; 60 | 61 | wire iomem_valid; 62 | wire iomem_ready; 63 | wire [31:0] iomem_addr; 64 | wire [31:0] iomem_wdata; 65 | wire [3:0] iomem_wstrb; 66 | wire [31:0] iomem_rdata; 67 | 68 | assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01); 69 | assign iomem_ready = 1'b1; 70 | assign iomem_wstrb = mem_wstrb; 71 | assign iomem_addr = mem_addr; 72 | assign iomem_wdata = mem_wdata; 73 | 74 | wire [31:0] spimemio_cfgreg_do; 75 | 76 | 77 | always @(posedge clk) 78 | if (iomem_valid && iomem_wstrb[0]) 79 | led <= iomem_wdata[7:0]; 80 | 81 | assign mem_ready = (iomem_valid && iomem_ready) || rom_ready; 82 | 83 | assign mem_rdata = rom_rdata; 84 | 85 | picorv32 #( 86 | .STACKADDR(STACKADDR), 87 | .PROGADDR_RESET(PROGADDR_RESET), 88 | .PROGADDR_IRQ(32'h 0000_0000), 89 | .BARREL_SHIFTER(0), 90 | .COMPRESSED_ISA(0), 91 | .ENABLE_MUL(0), 92 | .ENABLE_DIV(0), 93 | .ENABLE_IRQ(0), 94 | .ENABLE_IRQ_QREGS(0) 95 | ) cpu ( 96 | .clk (clk ), 97 | .resetn (resetn ), 98 | .mem_valid (mem_valid ), 99 | .mem_instr (mem_instr ), 100 | .mem_ready (mem_ready ), 101 | .mem_addr (mem_addr ), 102 | .mem_wdata (mem_wdata ), 103 | .mem_wstrb (mem_wstrb ), 104 | .mem_rdata (mem_rdata ) 105 | ); 106 | 107 | 108 | 109 | endmodule 110 | 111 | // Implementation note: 112 | // Replace the following two modules with wrappers for your SRAM cells. 113 | 114 | module picosoc_regs ( 115 | input clk, wen, 116 | input [5:0] waddr, 117 | input [5:0] raddr1, 118 | input [5:0] raddr2, 119 | input [31:0] wdata, 120 | output [31:0] rdata1, 121 | output [31:0] rdata2 122 | ); 123 | reg [31:0] regs [0:31]; 124 | 125 | always @(posedge clk) 126 | if (wen) regs[waddr[4:0]] <= wdata; 127 | 128 | assign rdata1 = regs[raddr1[4:0]]; 129 | assign rdata2 = regs[raddr2[4:0]]; 130 | endmodule 131 | 132 | 133 | `ifdef DEBUG 134 | `define debug(debug_command) debug_command 135 | `else 136 | `define debug(debug_command) 137 | `endif 138 | 139 | `ifdef FORMAL 140 | `define FORMAL_KEEP (* keep *) 141 | `define assert(assert_expr) assert(assert_expr) 142 | `else 143 | `ifdef DEBUGNETS 144 | `define FORMAL_KEEP (* keep *) 145 | `else 146 | `define FORMAL_KEEP 147 | `endif 148 | `define assert(assert_expr) empty_statement 149 | `endif 150 | 151 | // uncomment this for register file in extra module 152 | // `define PICORV32_REGS picorv32_regs 153 | 154 | // this macro can be used to check if the verilog files in your 155 | // design are read in the correct order. 156 | `define PICORV32_V 157 | 158 | 159 | /*************************************************************** 160 | * picorv32 161 | ***************************************************************/ 162 | 163 | module picorv32 #( 164 | parameter [ 0:0] ENABLE_COUNTERS = 1, 165 | parameter [ 0:0] ENABLE_COUNTERS64 = 1, 166 | parameter [ 0:0] ENABLE_REGS_16_31 = 1, 167 | parameter [ 0:0] ENABLE_REGS_DUALPORT = 1, 168 | parameter [ 0:0] LATCHED_MEM_RDATA = 0, 169 | parameter [ 0:0] TWO_STAGE_SHIFT = 1, 170 | parameter [ 0:0] BARREL_SHIFTER = 0, 171 | parameter [ 0:0] TWO_CYCLE_COMPARE = 0, 172 | parameter [ 0:0] TWO_CYCLE_ALU = 0, 173 | parameter [ 0:0] COMPRESSED_ISA = 0, 174 | parameter [ 0:0] CATCH_MISALIGN = 1, 175 | parameter [ 0:0] CATCH_ILLINSN = 1, 176 | parameter [ 0:0] ENABLE_PCPI = 0, 177 | parameter [ 0:0] ENABLE_MUL = 0, 178 | parameter [ 0:0] ENABLE_FAST_MUL = 0, 179 | parameter [ 0:0] ENABLE_DIV = 0, 180 | parameter [ 0:0] ENABLE_IRQ = 0, 181 | parameter [ 0:0] ENABLE_IRQ_QREGS = 1, 182 | parameter [ 0:0] ENABLE_IRQ_TIMER = 1, 183 | parameter [ 0:0] ENABLE_TRACE = 0, 184 | parameter [ 0:0] REGS_INIT_ZERO = 0, 185 | parameter [31:0] MASKED_IRQ = 32'h 0000_0000, 186 | parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff, 187 | parameter [31:0] PROGADDR_RESET = 32'h 0000_0000, 188 | parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010, 189 | parameter [31:0] STACKADDR = 32'h ffff_ffff 190 | ) ( 191 | input clk, resetn, 192 | output reg trap, 193 | 194 | output reg mem_valid, 195 | output reg mem_instr, 196 | input mem_ready, 197 | 198 | output reg [31:0] mem_addr, 199 | output reg [31:0] mem_wdata, 200 | output reg [ 3:0] mem_wstrb, 201 | input [31:0] mem_rdata, 202 | 203 | // Look-Ahead Interface 204 | output mem_la_read, 205 | output mem_la_write, 206 | output [31:0] mem_la_addr, 207 | output reg [31:0] mem_la_wdata, 208 | output reg [ 3:0] mem_la_wstrb, 209 | 210 | // Pico Co-Processor Interface (PCPI) 211 | output reg pcpi_valid, 212 | output reg [31:0] pcpi_insn, 213 | output [31:0] pcpi_rs1, 214 | output [31:0] pcpi_rs2, 215 | input pcpi_wr, 216 | input [31:0] pcpi_rd, 217 | input pcpi_wait, 218 | input pcpi_ready, 219 | 220 | // IRQ Interface 221 | input [31:0] irq, 222 | output reg [31:0] eoi, 223 | 224 | `ifdef RISCV_FORMAL 225 | output reg rvfi_valid, 226 | output reg [63:0] rvfi_order, 227 | output reg [31:0] rvfi_insn, 228 | output reg rvfi_trap, 229 | output reg rvfi_halt, 230 | output reg rvfi_intr, 231 | output reg [ 4:0] rvfi_rs1_addr, 232 | output reg [ 4:0] rvfi_rs2_addr, 233 | output reg [31:0] rvfi_rs1_rdata, 234 | output reg [31:0] rvfi_rs2_rdata, 235 | output reg [ 4:0] rvfi_rd_addr, 236 | output reg [31:0] rvfi_rd_wdata, 237 | output reg [31:0] rvfi_pc_rdata, 238 | output reg [31:0] rvfi_pc_wdata, 239 | output reg [31:0] rvfi_mem_addr, 240 | output reg [ 3:0] rvfi_mem_rmask, 241 | output reg [ 3:0] rvfi_mem_wmask, 242 | output reg [31:0] rvfi_mem_rdata, 243 | output reg [31:0] rvfi_mem_wdata, 244 | `endif 245 | 246 | // Trace Interface 247 | output reg trace_valid, 248 | output reg [35:0] trace_data 249 | ); 250 | localparam integer irq_timer = 0; 251 | localparam integer irq_ebreak = 1; 252 | localparam integer irq_buserror = 2; 253 | 254 | localparam integer irqregs_offset = ENABLE_REGS_16_31 ? 32 : 16; 255 | localparam integer regfile_size = (ENABLE_REGS_16_31 ? 32 : 16) + 4*ENABLE_IRQ*ENABLE_IRQ_QREGS; 256 | localparam integer regindex_bits = (ENABLE_REGS_16_31 ? 5 : 4) + ENABLE_IRQ*ENABLE_IRQ_QREGS; 257 | 258 | localparam WITH_PCPI = ENABLE_PCPI || ENABLE_MUL || ENABLE_FAST_MUL || ENABLE_DIV; 259 | 260 | localparam [35:0] TRACE_BRANCH = {4'b 0001, 32'b 0}; 261 | localparam [35:0] TRACE_ADDR = {4'b 0010, 32'b 0}; 262 | localparam [35:0] TRACE_IRQ = {4'b 1000, 32'b 0}; 263 | 264 | reg [63:0] count_cycle, count_instr; 265 | reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out; 266 | reg [4:0] reg_sh; 267 | 268 | reg [31:0] next_insn_opcode; 269 | reg [31:0] dbg_insn_opcode; 270 | reg [31:0] dbg_insn_addr; 271 | 272 | wire dbg_mem_valid = mem_valid; 273 | wire dbg_mem_instr = mem_instr; 274 | wire dbg_mem_ready = mem_ready; 275 | wire [31:0] dbg_mem_addr = mem_addr; 276 | wire [31:0] dbg_mem_wdata = mem_wdata; 277 | wire [ 3:0] dbg_mem_wstrb = mem_wstrb; 278 | wire [31:0] dbg_mem_rdata = mem_rdata; 279 | 280 | assign pcpi_rs1 = reg_op1; 281 | assign pcpi_rs2 = reg_op2; 282 | 283 | wire [31:0] next_pc; 284 | 285 | reg irq_delay; 286 | reg irq_active; 287 | reg [31:0] irq_mask; 288 | reg [31:0] irq_pending; 289 | reg [31:0] timer; 290 | 291 | `ifndef PICORV32_REGS 292 | reg [31:0] cpuregs [0:regfile_size-1]; 293 | 294 | integer i; 295 | initial begin 296 | if (REGS_INIT_ZERO) begin 297 | for (i = 0; i < regfile_size; i = i+1) 298 | cpuregs[i] = 0; 299 | end 300 | end 301 | `endif 302 | 303 | task empty_statement; 304 | // This task is used by the `assert directive in non-formal mode to 305 | // avoid empty statement (which are unsupported by plain Verilog syntax). 306 | begin end 307 | endtask 308 | 309 | `ifdef DEBUGREGS 310 | wire [31:0] dbg_reg_x0 = 0; 311 | wire [31:0] dbg_reg_x1 = cpuregs[1]; 312 | wire [31:0] dbg_reg_x2 = cpuregs[2]; 313 | wire [31:0] dbg_reg_x3 = cpuregs[3]; 314 | wire [31:0] dbg_reg_x4 = cpuregs[4]; 315 | wire [31:0] dbg_reg_x5 = cpuregs[5]; 316 | wire [31:0] dbg_reg_x6 = cpuregs[6]; 317 | wire [31:0] dbg_reg_x7 = cpuregs[7]; 318 | wire [31:0] dbg_reg_x8 = cpuregs[8]; 319 | wire [31:0] dbg_reg_x9 = cpuregs[9]; 320 | wire [31:0] dbg_reg_x10 = cpuregs[10]; 321 | wire [31:0] dbg_reg_x11 = cpuregs[11]; 322 | wire [31:0] dbg_reg_x12 = cpuregs[12]; 323 | wire [31:0] dbg_reg_x13 = cpuregs[13]; 324 | wire [31:0] dbg_reg_x14 = cpuregs[14]; 325 | wire [31:0] dbg_reg_x15 = cpuregs[15]; 326 | wire [31:0] dbg_reg_x16 = cpuregs[16]; 327 | wire [31:0] dbg_reg_x17 = cpuregs[17]; 328 | wire [31:0] dbg_reg_x18 = cpuregs[18]; 329 | wire [31:0] dbg_reg_x19 = cpuregs[19]; 330 | wire [31:0] dbg_reg_x20 = cpuregs[20]; 331 | wire [31:0] dbg_reg_x21 = cpuregs[21]; 332 | wire [31:0] dbg_reg_x22 = cpuregs[22]; 333 | wire [31:0] dbg_reg_x23 = cpuregs[23]; 334 | wire [31:0] dbg_reg_x24 = cpuregs[24]; 335 | wire [31:0] dbg_reg_x25 = cpuregs[25]; 336 | wire [31:0] dbg_reg_x26 = cpuregs[26]; 337 | wire [31:0] dbg_reg_x27 = cpuregs[27]; 338 | wire [31:0] dbg_reg_x28 = cpuregs[28]; 339 | wire [31:0] dbg_reg_x29 = cpuregs[29]; 340 | wire [31:0] dbg_reg_x30 = cpuregs[30]; 341 | wire [31:0] dbg_reg_x31 = cpuregs[31]; 342 | `endif 343 | 344 | // Internal PCPI Cores 345 | 346 | wire pcpi_mul_wr; 347 | wire [31:0] pcpi_mul_rd; 348 | wire pcpi_mul_wait; 349 | wire pcpi_mul_ready; 350 | 351 | wire pcpi_div_wr; 352 | wire [31:0] pcpi_div_rd; 353 | wire pcpi_div_wait; 354 | wire pcpi_div_ready; 355 | 356 | reg pcpi_int_wr; 357 | reg [31:0] pcpi_int_rd; 358 | reg pcpi_int_wait; 359 | reg pcpi_int_ready; 360 | 361 | generate if (ENABLE_FAST_MUL) begin 362 | picorv32_pcpi_fast_mul pcpi_mul ( 363 | .clk (clk ), 364 | .resetn (resetn ), 365 | .pcpi_valid(pcpi_valid ), 366 | .pcpi_insn (pcpi_insn ), 367 | .pcpi_rs1 (pcpi_rs1 ), 368 | .pcpi_rs2 (pcpi_rs2 ), 369 | .pcpi_wr (pcpi_mul_wr ), 370 | .pcpi_rd (pcpi_mul_rd ), 371 | .pcpi_wait (pcpi_mul_wait ), 372 | .pcpi_ready(pcpi_mul_ready ) 373 | ); 374 | end else if (ENABLE_MUL) begin 375 | picorv32_pcpi_mul pcpi_mul ( 376 | .clk (clk ), 377 | .resetn (resetn ), 378 | .pcpi_valid(pcpi_valid ), 379 | .pcpi_insn (pcpi_insn ), 380 | .pcpi_rs1 (pcpi_rs1 ), 381 | .pcpi_rs2 (pcpi_rs2 ), 382 | .pcpi_wr (pcpi_mul_wr ), 383 | .pcpi_rd (pcpi_mul_rd ), 384 | .pcpi_wait (pcpi_mul_wait ), 385 | .pcpi_ready(pcpi_mul_ready ) 386 | ); 387 | end else begin 388 | assign pcpi_mul_wr = 0; 389 | assign pcpi_mul_rd = 32'bx; 390 | assign pcpi_mul_wait = 0; 391 | assign pcpi_mul_ready = 0; 392 | end endgenerate 393 | 394 | generate if (ENABLE_DIV) begin 395 | picorv32_pcpi_div pcpi_div ( 396 | .clk (clk ), 397 | .resetn (resetn ), 398 | .pcpi_valid(pcpi_valid ), 399 | .pcpi_insn (pcpi_insn ), 400 | .pcpi_rs1 (pcpi_rs1 ), 401 | .pcpi_rs2 (pcpi_rs2 ), 402 | .pcpi_wr (pcpi_div_wr ), 403 | .pcpi_rd (pcpi_div_rd ), 404 | .pcpi_wait (pcpi_div_wait ), 405 | .pcpi_ready(pcpi_div_ready ) 406 | ); 407 | end else begin 408 | assign pcpi_div_wr = 0; 409 | assign pcpi_div_rd = 32'bx; 410 | assign pcpi_div_wait = 0; 411 | assign pcpi_div_ready = 0; 412 | end endgenerate 413 | 414 | always @* begin 415 | pcpi_int_wr = 0; 416 | pcpi_int_rd = 32'bx; 417 | pcpi_int_wait = |{ENABLE_PCPI && pcpi_wait, (ENABLE_MUL || ENABLE_FAST_MUL) && pcpi_mul_wait, ENABLE_DIV && pcpi_div_wait}; 418 | pcpi_int_ready = |{ENABLE_PCPI && pcpi_ready, (ENABLE_MUL || ENABLE_FAST_MUL) && pcpi_mul_ready, ENABLE_DIV && pcpi_div_ready}; 419 | 420 | (* parallel_case *) 421 | case (1'b1) 422 | ENABLE_PCPI && pcpi_ready: begin 423 | pcpi_int_wr = ENABLE_PCPI ? pcpi_wr : 0; 424 | pcpi_int_rd = ENABLE_PCPI ? pcpi_rd : 0; 425 | end 426 | (ENABLE_MUL || ENABLE_FAST_MUL) && pcpi_mul_ready: begin 427 | pcpi_int_wr = pcpi_mul_wr; 428 | pcpi_int_rd = pcpi_mul_rd; 429 | end 430 | ENABLE_DIV && pcpi_div_ready: begin 431 | pcpi_int_wr = pcpi_div_wr; 432 | pcpi_int_rd = pcpi_div_rd; 433 | end 434 | endcase 435 | end 436 | 437 | 438 | // Memory Interface 439 | 440 | reg [1:0] mem_state; 441 | reg [1:0] mem_wordsize; 442 | reg [31:0] mem_rdata_word; 443 | reg [31:0] mem_rdata_q; 444 | reg mem_do_prefetch; 445 | reg mem_do_rinst; 446 | reg mem_do_rdata; 447 | reg mem_do_wdata; 448 | 449 | wire mem_xfer; 450 | reg mem_la_secondword, mem_la_firstword_reg, last_mem_valid; 451 | wire mem_la_firstword = COMPRESSED_ISA && (mem_do_prefetch || mem_do_rinst) && next_pc[1] && !mem_la_secondword; 452 | wire mem_la_firstword_xfer = COMPRESSED_ISA && mem_xfer && (!last_mem_valid ? mem_la_firstword : mem_la_firstword_reg); 453 | 454 | reg prefetched_high_word; 455 | reg clear_prefetched_high_word; 456 | reg [15:0] mem_16bit_buffer; 457 | 458 | wire [31:0] mem_rdata_latched_noshuffle; 459 | wire [31:0] mem_rdata_latched; 460 | 461 | wire mem_la_use_prefetched_high_word = COMPRESSED_ISA && mem_la_firstword && prefetched_high_word && !clear_prefetched_high_word; 462 | assign mem_xfer = (mem_valid && mem_ready) || (mem_la_use_prefetched_high_word && mem_do_rinst); 463 | 464 | wire mem_busy = |{mem_do_prefetch, mem_do_rinst, mem_do_rdata, mem_do_wdata}; 465 | wire mem_done = resetn && ((mem_xfer && |mem_state && (mem_do_rinst || mem_do_rdata || mem_do_wdata)) || (&mem_state && mem_do_rinst)) && 466 | (!mem_la_firstword || (~&mem_rdata_latched[1:0] && mem_xfer)); 467 | 468 | assign mem_la_write = resetn && !mem_state && mem_do_wdata; 469 | assign mem_la_read = resetn && ((!mem_la_use_prefetched_high_word && !mem_state && (mem_do_rinst || mem_do_prefetch || mem_do_rdata)) || 470 | (COMPRESSED_ISA && mem_xfer && (!last_mem_valid ? mem_la_firstword : mem_la_firstword_reg) && !mem_la_secondword && &mem_rdata_latched[1:0])); 471 | assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + mem_la_firstword_xfer, 2'b00} : {reg_op1[31:2], 2'b00}; 472 | 473 | assign mem_rdata_latched_noshuffle = (mem_xfer || LATCHED_MEM_RDATA) ? mem_rdata : mem_rdata_q; 474 | 475 | assign mem_rdata_latched = COMPRESSED_ISA && mem_la_use_prefetched_high_word ? {16'bx, mem_16bit_buffer} : 476 | COMPRESSED_ISA && mem_la_secondword ? {mem_rdata_latched_noshuffle[15:0], mem_16bit_buffer} : 477 | COMPRESSED_ISA && mem_la_firstword ? {16'bx, mem_rdata_latched_noshuffle[31:16]} : mem_rdata_latched_noshuffle; 478 | 479 | always @(posedge clk) begin 480 | if (!resetn) begin 481 | mem_la_firstword_reg <= 0; 482 | last_mem_valid <= 0; 483 | end else begin 484 | if (!last_mem_valid) 485 | mem_la_firstword_reg <= mem_la_firstword; 486 | last_mem_valid <= mem_valid && !mem_ready; 487 | end 488 | end 489 | 490 | always @* begin 491 | (* full_case *) 492 | case (mem_wordsize) 493 | 0: begin 494 | mem_la_wdata = reg_op2; 495 | mem_la_wstrb = 4'b1111; 496 | mem_rdata_word = mem_rdata; 497 | end 498 | 1: begin 499 | mem_la_wdata = {2{reg_op2[15:0]}}; 500 | mem_la_wstrb = reg_op1[1] ? 4'b1100 : 4'b0011; 501 | case (reg_op1[1]) 502 | 1'b0: mem_rdata_word = {16'b0, mem_rdata[15: 0]}; 503 | 1'b1: mem_rdata_word = {16'b0, mem_rdata[31:16]}; 504 | endcase 505 | end 506 | 2: begin 507 | mem_la_wdata = {4{reg_op2[7:0]}}; 508 | mem_la_wstrb = 4'b0001 << reg_op1[1:0]; 509 | case (reg_op1[1:0]) 510 | 2'b00: mem_rdata_word = {24'b0, mem_rdata[ 7: 0]}; 511 | 2'b01: mem_rdata_word = {24'b0, mem_rdata[15: 8]}; 512 | 2'b10: mem_rdata_word = {24'b0, mem_rdata[23:16]}; 513 | 2'b11: mem_rdata_word = {24'b0, mem_rdata[31:24]}; 514 | endcase 515 | end 516 | endcase 517 | end 518 | 519 | always @(posedge clk) begin 520 | if (mem_xfer) begin 521 | mem_rdata_q <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata; 522 | next_insn_opcode <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata; 523 | end 524 | 525 | if (COMPRESSED_ISA && mem_done && (mem_do_prefetch || mem_do_rinst)) begin 526 | case (mem_rdata_latched[1:0]) 527 | 2'b00: begin // Quadrant 0 528 | case (mem_rdata_latched[15:13]) 529 | 3'b000: begin // C.ADDI4SPN 530 | mem_rdata_q[14:12] <= 3'b000; 531 | mem_rdata_q[31:20] <= {2'b0, mem_rdata_latched[10:7], mem_rdata_latched[12:11], mem_rdata_latched[5], mem_rdata_latched[6], 2'b00}; 532 | end 533 | 3'b010: begin // C.LW 534 | mem_rdata_q[31:20] <= {5'b0, mem_rdata_latched[5], mem_rdata_latched[12:10], mem_rdata_latched[6], 2'b00}; 535 | mem_rdata_q[14:12] <= 3'b 010; 536 | end 537 | 3'b 110: begin // C.SW 538 | {mem_rdata_q[31:25], mem_rdata_q[11:7]} <= {5'b0, mem_rdata_latched[5], mem_rdata_latched[12:10], mem_rdata_latched[6], 2'b00}; 539 | mem_rdata_q[14:12] <= 3'b 010; 540 | end 541 | endcase 542 | end 543 | 2'b01: begin // Quadrant 1 544 | case (mem_rdata_latched[15:13]) 545 | 3'b 000: begin // C.ADDI 546 | mem_rdata_q[14:12] <= 3'b000; 547 | mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]}); 548 | end 549 | 3'b 010: begin // C.LI 550 | mem_rdata_q[14:12] <= 3'b000; 551 | mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]}); 552 | end 553 | 3'b 011: begin 554 | if (mem_rdata_latched[11:7] == 2) begin // C.ADDI16SP 555 | mem_rdata_q[14:12] <= 3'b000; 556 | mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[4:3], 557 | mem_rdata_latched[5], mem_rdata_latched[2], mem_rdata_latched[6], 4'b 0000}); 558 | end else begin // C.LUI 559 | mem_rdata_q[31:12] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]}); 560 | end 561 | end 562 | 3'b100: begin 563 | if (mem_rdata_latched[11:10] == 2'b00) begin // C.SRLI 564 | mem_rdata_q[31:25] <= 7'b0000000; 565 | mem_rdata_q[14:12] <= 3'b 101; 566 | end 567 | if (mem_rdata_latched[11:10] == 2'b01) begin // C.SRAI 568 | mem_rdata_q[31:25] <= 7'b0100000; 569 | mem_rdata_q[14:12] <= 3'b 101; 570 | end 571 | if (mem_rdata_latched[11:10] == 2'b10) begin // C.ANDI 572 | mem_rdata_q[14:12] <= 3'b111; 573 | mem_rdata_q[31:20] <= $signed({mem_rdata_latched[12], mem_rdata_latched[6:2]}); 574 | end 575 | if (mem_rdata_latched[12:10] == 3'b011) begin // C.SUB, C.XOR, C.OR, C.AND 576 | if (mem_rdata_latched[6:5] == 2'b00) mem_rdata_q[14:12] <= 3'b000; 577 | if (mem_rdata_latched[6:5] == 2'b01) mem_rdata_q[14:12] <= 3'b100; 578 | if (mem_rdata_latched[6:5] == 2'b10) mem_rdata_q[14:12] <= 3'b110; 579 | if (mem_rdata_latched[6:5] == 2'b11) mem_rdata_q[14:12] <= 3'b111; 580 | mem_rdata_q[31:25] <= mem_rdata_latched[6:5] == 2'b00 ? 7'b0100000 : 7'b0000000; 581 | end 582 | end 583 | 3'b 110: begin // C.BEQZ 584 | mem_rdata_q[14:12] <= 3'b000; 585 | { mem_rdata_q[31], mem_rdata_q[7], mem_rdata_q[30:25], mem_rdata_q[11:8] } <= 586 | $signed({mem_rdata_latched[12], mem_rdata_latched[6:5], mem_rdata_latched[2], 587 | mem_rdata_latched[11:10], mem_rdata_latched[4:3]}); 588 | end 589 | 3'b 111: begin // C.BNEZ 590 | mem_rdata_q[14:12] <= 3'b001; 591 | { mem_rdata_q[31], mem_rdata_q[7], mem_rdata_q[30:25], mem_rdata_q[11:8] } <= 592 | $signed({mem_rdata_latched[12], mem_rdata_latched[6:5], mem_rdata_latched[2], 593 | mem_rdata_latched[11:10], mem_rdata_latched[4:3]}); 594 | end 595 | endcase 596 | end 597 | 2'b10: begin // Quadrant 2 598 | case (mem_rdata_latched[15:13]) 599 | 3'b000: begin // C.SLLI 600 | mem_rdata_q[31:25] <= 7'b0000000; 601 | mem_rdata_q[14:12] <= 3'b 001; 602 | end 603 | 3'b010: begin // C.LWSP 604 | mem_rdata_q[31:20] <= {4'b0, mem_rdata_latched[3:2], mem_rdata_latched[12], mem_rdata_latched[6:4], 2'b00}; 605 | mem_rdata_q[14:12] <= 3'b 010; 606 | end 607 | 3'b100: begin 608 | if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] == 0) begin // C.JR 609 | mem_rdata_q[14:12] <= 3'b000; 610 | mem_rdata_q[31:20] <= 12'b0; 611 | end 612 | if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] != 0) begin // C.MV 613 | mem_rdata_q[14:12] <= 3'b000; 614 | mem_rdata_q[31:25] <= 7'b0000000; 615 | end 616 | if (mem_rdata_latched[12] != 0 && mem_rdata_latched[11:7] != 0 && mem_rdata_latched[6:2] == 0) begin // C.JALR 617 | mem_rdata_q[14:12] <= 3'b000; 618 | mem_rdata_q[31:20] <= 12'b0; 619 | end 620 | if (mem_rdata_latched[12] != 0 && mem_rdata_latched[6:2] != 0) begin // C.ADD 621 | mem_rdata_q[14:12] <= 3'b000; 622 | mem_rdata_q[31:25] <= 7'b0000000; 623 | end 624 | end 625 | 3'b110: begin // C.SWSP 626 | {mem_rdata_q[31:25], mem_rdata_q[11:7]} <= {4'b0, mem_rdata_latched[8:7], mem_rdata_latched[12:9], 2'b00}; 627 | mem_rdata_q[14:12] <= 3'b 010; 628 | end 629 | endcase 630 | end 631 | endcase 632 | end 633 | end 634 | 635 | always @(posedge clk) begin 636 | if (resetn && !trap) begin 637 | if (mem_do_prefetch || mem_do_rinst || mem_do_rdata) 638 | `assert(!mem_do_wdata); 639 | 640 | if (mem_do_prefetch || mem_do_rinst) 641 | `assert(!mem_do_rdata); 642 | 643 | if (mem_do_rdata) 644 | `assert(!mem_do_prefetch && !mem_do_rinst); 645 | 646 | if (mem_do_wdata) 647 | `assert(!(mem_do_prefetch || mem_do_rinst || mem_do_rdata)); 648 | 649 | if (mem_state == 2 || mem_state == 3) 650 | `assert(mem_valid || mem_do_prefetch); 651 | end 652 | end 653 | 654 | always @(posedge clk) begin 655 | if (!resetn || trap) begin 656 | if (!resetn) 657 | mem_state <= 0; 658 | if (!resetn || mem_ready) 659 | mem_valid <= 0; 660 | mem_la_secondword <= 0; 661 | prefetched_high_word <= 0; 662 | end else begin 663 | if (mem_la_read || mem_la_write) begin 664 | mem_addr <= mem_la_addr; 665 | mem_wstrb <= mem_la_wstrb & {4{mem_la_write}}; 666 | end 667 | if (mem_la_write) begin 668 | mem_wdata <= mem_la_wdata; 669 | end 670 | case (mem_state) 671 | 0: begin 672 | if (mem_do_prefetch || mem_do_rinst || mem_do_rdata) begin 673 | mem_valid <= !mem_la_use_prefetched_high_word; 674 | mem_instr <= mem_do_prefetch || mem_do_rinst; 675 | mem_wstrb <= 0; 676 | mem_state <= 1; 677 | end 678 | if (mem_do_wdata) begin 679 | mem_valid <= 1; 680 | mem_instr <= 0; 681 | mem_state <= 2; 682 | end 683 | end 684 | 1: begin 685 | `assert(mem_wstrb == 0); 686 | `assert(mem_do_prefetch || mem_do_rinst || mem_do_rdata); 687 | `assert(mem_valid == !mem_la_use_prefetched_high_word); 688 | `assert(mem_instr == (mem_do_prefetch || mem_do_rinst)); 689 | if (mem_xfer) begin 690 | if (COMPRESSED_ISA && mem_la_read) begin 691 | mem_valid <= 1; 692 | mem_la_secondword <= 1; 693 | if (!mem_la_use_prefetched_high_word) 694 | mem_16bit_buffer <= mem_rdata[31:16]; 695 | end else begin 696 | mem_valid <= 0; 697 | mem_la_secondword <= 0; 698 | if (COMPRESSED_ISA && !mem_do_rdata) begin 699 | if (~&mem_rdata[1:0] || mem_la_secondword) begin 700 | mem_16bit_buffer <= mem_rdata[31:16]; 701 | prefetched_high_word <= 1; 702 | end else begin 703 | prefetched_high_word <= 0; 704 | end 705 | end 706 | mem_state <= mem_do_rinst || mem_do_rdata ? 0 : 3; 707 | end 708 | end 709 | end 710 | 2: begin 711 | `assert(mem_wstrb != 0); 712 | `assert(mem_do_wdata); 713 | if (mem_xfer) begin 714 | mem_valid <= 0; 715 | mem_state <= 0; 716 | end 717 | end 718 | 3: begin 719 | `assert(mem_wstrb == 0); 720 | `assert(mem_do_prefetch); 721 | if (mem_do_rinst) begin 722 | mem_state <= 0; 723 | end 724 | end 725 | endcase 726 | end 727 | 728 | if (clear_prefetched_high_word) 729 | prefetched_high_word <= 0; 730 | end 731 | 732 | 733 | // Instruction Decoder 734 | 735 | reg instr_lui, instr_auipc, instr_jal, instr_jalr; 736 | reg instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu; 737 | reg instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw; 738 | reg instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai; 739 | reg instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and; 740 | reg instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh, instr_ecall_ebreak; 741 | reg instr_getq, instr_setq, instr_retirq, instr_maskirq, instr_waitirq, instr_timer; 742 | wire instr_trap; 743 | 744 | reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2; 745 | reg [31:0] decoded_imm, decoded_imm_uj; 746 | reg decoder_trigger; 747 | reg decoder_trigger_q; 748 | reg decoder_pseudo_trigger; 749 | reg decoder_pseudo_trigger_q; 750 | reg compressed_instr; 751 | 752 | reg is_lui_auipc_jal; 753 | reg is_lb_lh_lw_lbu_lhu; 754 | reg is_slli_srli_srai; 755 | reg is_jalr_addi_slti_sltiu_xori_ori_andi; 756 | reg is_sb_sh_sw; 757 | reg is_sll_srl_sra; 758 | reg is_lui_auipc_jal_jalr_addi_add_sub; 759 | reg is_slti_blt_slt; 760 | reg is_sltiu_bltu_sltu; 761 | reg is_beq_bne_blt_bge_bltu_bgeu; 762 | reg is_lbu_lhu_lw; 763 | reg is_alu_reg_imm; 764 | reg is_alu_reg_reg; 765 | reg is_compare; 766 | 767 | assign instr_trap = (CATCH_ILLINSN || WITH_PCPI) && !{instr_lui, instr_auipc, instr_jal, instr_jalr, 768 | instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu, 769 | instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw, 770 | instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai, 771 | instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and, 772 | instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh, 773 | instr_getq, instr_setq, instr_retirq, instr_maskirq, instr_waitirq, instr_timer}; 774 | 775 | wire is_rdcycle_rdcycleh_rdinstr_rdinstrh; 776 | assign is_rdcycle_rdcycleh_rdinstr_rdinstrh = |{instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh}; 777 | 778 | reg [63:0] new_ascii_instr; 779 | `FORMAL_KEEP reg [63:0] dbg_ascii_instr; 780 | `FORMAL_KEEP reg [31:0] dbg_insn_imm; 781 | `FORMAL_KEEP reg [4:0] dbg_insn_rs1; 782 | `FORMAL_KEEP reg [4:0] dbg_insn_rs2; 783 | `FORMAL_KEEP reg [4:0] dbg_insn_rd; 784 | `FORMAL_KEEP reg [31:0] dbg_rs1val; 785 | `FORMAL_KEEP reg [31:0] dbg_rs2val; 786 | `FORMAL_KEEP reg dbg_rs1val_valid; 787 | `FORMAL_KEEP reg dbg_rs2val_valid; 788 | 789 | always @* begin 790 | new_ascii_instr = ""; 791 | 792 | if (instr_lui) new_ascii_instr = "lui"; 793 | if (instr_auipc) new_ascii_instr = "auipc"; 794 | if (instr_jal) new_ascii_instr = "jal"; 795 | if (instr_jalr) new_ascii_instr = "jalr"; 796 | 797 | if (instr_beq) new_ascii_instr = "beq"; 798 | if (instr_bne) new_ascii_instr = "bne"; 799 | if (instr_blt) new_ascii_instr = "blt"; 800 | if (instr_bge) new_ascii_instr = "bge"; 801 | if (instr_bltu) new_ascii_instr = "bltu"; 802 | if (instr_bgeu) new_ascii_instr = "bgeu"; 803 | 804 | if (instr_lb) new_ascii_instr = "lb"; 805 | if (instr_lh) new_ascii_instr = "lh"; 806 | if (instr_lw) new_ascii_instr = "lw"; 807 | if (instr_lbu) new_ascii_instr = "lbu"; 808 | if (instr_lhu) new_ascii_instr = "lhu"; 809 | if (instr_sb) new_ascii_instr = "sb"; 810 | if (instr_sh) new_ascii_instr = "sh"; 811 | if (instr_sw) new_ascii_instr = "sw"; 812 | 813 | if (instr_addi) new_ascii_instr = "addi"; 814 | if (instr_slti) new_ascii_instr = "slti"; 815 | if (instr_sltiu) new_ascii_instr = "sltiu"; 816 | if (instr_xori) new_ascii_instr = "xori"; 817 | if (instr_ori) new_ascii_instr = "ori"; 818 | if (instr_andi) new_ascii_instr = "andi"; 819 | if (instr_slli) new_ascii_instr = "slli"; 820 | if (instr_srli) new_ascii_instr = "srli"; 821 | if (instr_srai) new_ascii_instr = "srai"; 822 | 823 | if (instr_add) new_ascii_instr = "add"; 824 | if (instr_sub) new_ascii_instr = "sub"; 825 | if (instr_sll) new_ascii_instr = "sll"; 826 | if (instr_slt) new_ascii_instr = "slt"; 827 | if (instr_sltu) new_ascii_instr = "sltu"; 828 | if (instr_xor) new_ascii_instr = "xor"; 829 | if (instr_srl) new_ascii_instr = "srl"; 830 | if (instr_sra) new_ascii_instr = "sra"; 831 | if (instr_or) new_ascii_instr = "or"; 832 | if (instr_and) new_ascii_instr = "and"; 833 | 834 | if (instr_rdcycle) new_ascii_instr = "rdcycle"; 835 | if (instr_rdcycleh) new_ascii_instr = "rdcycleh"; 836 | if (instr_rdinstr) new_ascii_instr = "rdinstr"; 837 | if (instr_rdinstrh) new_ascii_instr = "rdinstrh"; 838 | 839 | if (instr_getq) new_ascii_instr = "getq"; 840 | if (instr_setq) new_ascii_instr = "setq"; 841 | if (instr_retirq) new_ascii_instr = "retirq"; 842 | if (instr_maskirq) new_ascii_instr = "maskirq"; 843 | if (instr_waitirq) new_ascii_instr = "waitirq"; 844 | if (instr_timer) new_ascii_instr = "timer"; 845 | end 846 | 847 | reg [63:0] q_ascii_instr; 848 | reg [31:0] q_insn_imm; 849 | reg [31:0] q_insn_opcode; 850 | reg [4:0] q_insn_rs1; 851 | reg [4:0] q_insn_rs2; 852 | reg [4:0] q_insn_rd; 853 | reg dbg_next; 854 | 855 | wire launch_next_insn; 856 | reg dbg_valid_insn; 857 | 858 | reg [63:0] cached_ascii_instr; 859 | reg [31:0] cached_insn_imm; 860 | reg [31:0] cached_insn_opcode; 861 | reg [4:0] cached_insn_rs1; 862 | reg [4:0] cached_insn_rs2; 863 | reg [4:0] cached_insn_rd; 864 | 865 | always @(posedge clk) begin 866 | q_ascii_instr <= dbg_ascii_instr; 867 | q_insn_imm <= dbg_insn_imm; 868 | q_insn_opcode <= dbg_insn_opcode; 869 | q_insn_rs1 <= dbg_insn_rs1; 870 | q_insn_rs2 <= dbg_insn_rs2; 871 | q_insn_rd <= dbg_insn_rd; 872 | dbg_next <= launch_next_insn; 873 | 874 | if (!resetn || trap) 875 | dbg_valid_insn <= 0; 876 | else if (launch_next_insn) 877 | dbg_valid_insn <= 1; 878 | 879 | if (decoder_trigger_q) begin 880 | cached_ascii_instr <= new_ascii_instr; 881 | cached_insn_imm <= decoded_imm; 882 | if (&next_insn_opcode[1:0]) 883 | cached_insn_opcode <= next_insn_opcode; 884 | else 885 | cached_insn_opcode <= {16'b0, next_insn_opcode[15:0]}; 886 | cached_insn_rs1 <= decoded_rs1; 887 | cached_insn_rs2 <= decoded_rs2; 888 | cached_insn_rd <= decoded_rd; 889 | end 890 | 891 | if (launch_next_insn) begin 892 | dbg_insn_addr <= next_pc; 893 | end 894 | end 895 | 896 | always @* begin 897 | dbg_ascii_instr = q_ascii_instr; 898 | dbg_insn_imm = q_insn_imm; 899 | dbg_insn_opcode = q_insn_opcode; 900 | dbg_insn_rs1 = q_insn_rs1; 901 | dbg_insn_rs2 = q_insn_rs2; 902 | dbg_insn_rd = q_insn_rd; 903 | 904 | if (dbg_next) begin 905 | if (decoder_pseudo_trigger_q) begin 906 | dbg_ascii_instr = cached_ascii_instr; 907 | dbg_insn_imm = cached_insn_imm; 908 | dbg_insn_opcode = cached_insn_opcode; 909 | dbg_insn_rs1 = cached_insn_rs1; 910 | dbg_insn_rs2 = cached_insn_rs2; 911 | dbg_insn_rd = cached_insn_rd; 912 | end else begin 913 | dbg_ascii_instr = new_ascii_instr; 914 | if (&next_insn_opcode[1:0]) 915 | dbg_insn_opcode = next_insn_opcode; 916 | else 917 | dbg_insn_opcode = {16'b0, next_insn_opcode[15:0]}; 918 | dbg_insn_imm = decoded_imm; 919 | dbg_insn_rs1 = decoded_rs1; 920 | dbg_insn_rs2 = decoded_rs2; 921 | dbg_insn_rd = decoded_rd; 922 | end 923 | end 924 | end 925 | 926 | `ifdef DEBUGASM 927 | always @(posedge clk) begin 928 | if (dbg_next) begin 929 | $display("debugasm %x %x %s", dbg_insn_addr, dbg_insn_opcode, dbg_ascii_instr ? dbg_ascii_instr : "*"); 930 | end 931 | end 932 | `endif 933 | 934 | `ifdef DEBUG 935 | always @(posedge clk) begin 936 | if (dbg_next) begin 937 | if (&dbg_insn_opcode[1:0]) 938 | $display("DECODE: 0x%08x 0x%08x %-0s", dbg_insn_addr, dbg_insn_opcode, dbg_ascii_instr ? dbg_ascii_instr : "UNKNOWN"); 939 | else 940 | $display("DECODE: 0x%08x 0x%04x %-0s", dbg_insn_addr, dbg_insn_opcode[15:0], dbg_ascii_instr ? dbg_ascii_instr : "UNKNOWN"); 941 | end 942 | end 943 | `endif 944 | 945 | always @(posedge clk) begin 946 | is_lui_auipc_jal <= |{instr_lui, instr_auipc, instr_jal}; 947 | is_lui_auipc_jal_jalr_addi_add_sub <= |{instr_lui, instr_auipc, instr_jal, instr_jalr, instr_addi, instr_add, instr_sub}; 948 | is_slti_blt_slt <= |{instr_slti, instr_blt, instr_slt}; 949 | is_sltiu_bltu_sltu <= |{instr_sltiu, instr_bltu, instr_sltu}; 950 | is_lbu_lhu_lw <= |{instr_lbu, instr_lhu, instr_lw}; 951 | is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu}; 952 | 953 | if (mem_do_rinst && mem_done) begin 954 | instr_lui <= mem_rdata_latched[6:0] == 7'b0110111; 955 | instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111; 956 | instr_jal <= mem_rdata_latched[6:0] == 7'b1101111; 957 | instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111 && mem_rdata_latched[14:12] == 3'b000; 958 | instr_retirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ; 959 | instr_waitirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000100 && ENABLE_IRQ; 960 | 961 | is_beq_bne_blt_bge_bltu_bgeu <= mem_rdata_latched[6:0] == 7'b1100011; 962 | is_lb_lh_lw_lbu_lhu <= mem_rdata_latched[6:0] == 7'b0000011; 963 | is_sb_sh_sw <= mem_rdata_latched[6:0] == 7'b0100011; 964 | is_alu_reg_imm <= mem_rdata_latched[6:0] == 7'b0010011; 965 | is_alu_reg_reg <= mem_rdata_latched[6:0] == 7'b0110011; 966 | 967 | { decoded_imm_uj[31:20], decoded_imm_uj[10:1], decoded_imm_uj[11], decoded_imm_uj[19:12], decoded_imm_uj[0] } <= $signed({mem_rdata_latched[31:12], 1'b0}); 968 | 969 | decoded_rd <= mem_rdata_latched[11:7]; 970 | decoded_rs1 <= mem_rdata_latched[19:15]; 971 | decoded_rs2 <= mem_rdata_latched[24:20]; 972 | 973 | if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000000 && ENABLE_IRQ && ENABLE_IRQ_QREGS) 974 | decoded_rs1[regindex_bits-1] <= 1; // instr_getq 975 | 976 | if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ) 977 | decoded_rs1 <= ENABLE_IRQ_QREGS ? irqregs_offset : 3; // instr_retirq 978 | 979 | compressed_instr <= 0; 980 | if (COMPRESSED_ISA && mem_rdata_latched[1:0] != 2'b11) begin 981 | compressed_instr <= 1; 982 | decoded_rd <= 0; 983 | decoded_rs1 <= 0; 984 | decoded_rs2 <= 0; 985 | 986 | { decoded_imm_uj[31:11], decoded_imm_uj[4], decoded_imm_uj[9:8], decoded_imm_uj[10], decoded_imm_uj[6], 987 | decoded_imm_uj[7], decoded_imm_uj[3:1], decoded_imm_uj[5], decoded_imm_uj[0] } <= $signed({mem_rdata_latched[12:2], 1'b0}); 988 | 989 | case (mem_rdata_latched[1:0]) 990 | 2'b00: begin // Quadrant 0 991 | case (mem_rdata_latched[15:13]) 992 | 3'b000: begin // C.ADDI4SPN 993 | is_alu_reg_imm <= |mem_rdata_latched[12:5]; 994 | decoded_rs1 <= 2; 995 | decoded_rd <= 8 + mem_rdata_latched[4:2]; 996 | end 997 | 3'b010: begin // C.LW 998 | is_lb_lh_lw_lbu_lhu <= 1; 999 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1000 | decoded_rd <= 8 + mem_rdata_latched[4:2]; 1001 | end 1002 | 3'b110: begin // C.SW 1003 | is_sb_sh_sw <= 1; 1004 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1005 | decoded_rs2 <= 8 + mem_rdata_latched[4:2]; 1006 | end 1007 | endcase 1008 | end 1009 | 2'b01: begin // Quadrant 1 1010 | case (mem_rdata_latched[15:13]) 1011 | 3'b000: begin // C.NOP / C.ADDI 1012 | is_alu_reg_imm <= 1; 1013 | decoded_rd <= mem_rdata_latched[11:7]; 1014 | decoded_rs1 <= mem_rdata_latched[11:7]; 1015 | end 1016 | 3'b001: begin // C.JAL 1017 | instr_jal <= 1; 1018 | decoded_rd <= 1; 1019 | end 1020 | 3'b 010: begin // C.LI 1021 | is_alu_reg_imm <= 1; 1022 | decoded_rd <= mem_rdata_latched[11:7]; 1023 | decoded_rs1 <= 0; 1024 | end 1025 | 3'b 011: begin 1026 | if (mem_rdata_latched[12] || mem_rdata_latched[6:2]) begin 1027 | if (mem_rdata_latched[11:7] == 2) begin // C.ADDI16SP 1028 | is_alu_reg_imm <= 1; 1029 | decoded_rd <= mem_rdata_latched[11:7]; 1030 | decoded_rs1 <= mem_rdata_latched[11:7]; 1031 | end else begin // C.LUI 1032 | instr_lui <= 1; 1033 | decoded_rd <= mem_rdata_latched[11:7]; 1034 | decoded_rs1 <= 0; 1035 | end 1036 | end 1037 | end 1038 | 3'b100: begin 1039 | if (!mem_rdata_latched[11] && !mem_rdata_latched[12]) begin // C.SRLI, C.SRAI 1040 | is_alu_reg_imm <= 1; 1041 | decoded_rd <= 8 + mem_rdata_latched[9:7]; 1042 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1043 | decoded_rs2 <= {mem_rdata_latched[12], mem_rdata_latched[6:2]}; 1044 | end 1045 | if (mem_rdata_latched[11:10] == 2'b10) begin // C.ANDI 1046 | is_alu_reg_imm <= 1; 1047 | decoded_rd <= 8 + mem_rdata_latched[9:7]; 1048 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1049 | end 1050 | if (mem_rdata_latched[12:10] == 3'b011) begin // C.SUB, C.XOR, C.OR, C.AND 1051 | is_alu_reg_reg <= 1; 1052 | decoded_rd <= 8 + mem_rdata_latched[9:7]; 1053 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1054 | decoded_rs2 <= 8 + mem_rdata_latched[4:2]; 1055 | end 1056 | end 1057 | 3'b101: begin // C.J 1058 | instr_jal <= 1; 1059 | end 1060 | 3'b110: begin // C.BEQZ 1061 | is_beq_bne_blt_bge_bltu_bgeu <= 1; 1062 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1063 | decoded_rs2 <= 0; 1064 | end 1065 | 3'b111: begin // C.BNEZ 1066 | is_beq_bne_blt_bge_bltu_bgeu <= 1; 1067 | decoded_rs1 <= 8 + mem_rdata_latched[9:7]; 1068 | decoded_rs2 <= 0; 1069 | end 1070 | endcase 1071 | end 1072 | 2'b10: begin // Quadrant 2 1073 | case (mem_rdata_latched[15:13]) 1074 | 3'b000: begin // C.SLLI 1075 | if (!mem_rdata_latched[12]) begin 1076 | is_alu_reg_imm <= 1; 1077 | decoded_rd <= mem_rdata_latched[11:7]; 1078 | decoded_rs1 <= mem_rdata_latched[11:7]; 1079 | decoded_rs2 <= {mem_rdata_latched[12], mem_rdata_latched[6:2]}; 1080 | end 1081 | end 1082 | 3'b010: begin // C.LWSP 1083 | if (mem_rdata_latched[11:7]) begin 1084 | is_lb_lh_lw_lbu_lhu <= 1; 1085 | decoded_rd <= mem_rdata_latched[11:7]; 1086 | decoded_rs1 <= 2; 1087 | end 1088 | end 1089 | 3'b100: begin 1090 | if (mem_rdata_latched[12] == 0 && mem_rdata_latched[11:7] != 0 && mem_rdata_latched[6:2] == 0) begin // C.JR 1091 | instr_jalr <= 1; 1092 | decoded_rd <= 0; 1093 | decoded_rs1 <= mem_rdata_latched[11:7]; 1094 | end 1095 | if (mem_rdata_latched[12] == 0 && mem_rdata_latched[6:2] != 0) begin // C.MV 1096 | is_alu_reg_reg <= 1; 1097 | decoded_rd <= mem_rdata_latched[11:7]; 1098 | decoded_rs1 <= 0; 1099 | decoded_rs2 <= mem_rdata_latched[6:2]; 1100 | end 1101 | if (mem_rdata_latched[12] != 0 && mem_rdata_latched[11:7] != 0 && mem_rdata_latched[6:2] == 0) begin // C.JALR 1102 | instr_jalr <= 1; 1103 | decoded_rd <= 1; 1104 | decoded_rs1 <= mem_rdata_latched[11:7]; 1105 | end 1106 | if (mem_rdata_latched[12] != 0 && mem_rdata_latched[6:2] != 0) begin // C.ADD 1107 | is_alu_reg_reg <= 1; 1108 | decoded_rd <= mem_rdata_latched[11:7]; 1109 | decoded_rs1 <= mem_rdata_latched[11:7]; 1110 | decoded_rs2 <= mem_rdata_latched[6:2]; 1111 | end 1112 | end 1113 | 3'b110: begin // C.SWSP 1114 | is_sb_sh_sw <= 1; 1115 | decoded_rs1 <= 2; 1116 | decoded_rs2 <= mem_rdata_latched[6:2]; 1117 | end 1118 | endcase 1119 | end 1120 | endcase 1121 | end 1122 | end 1123 | 1124 | if (decoder_trigger && !decoder_pseudo_trigger) begin 1125 | pcpi_insn <= WITH_PCPI ? mem_rdata_q : 'bx; 1126 | 1127 | instr_beq <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b000; 1128 | instr_bne <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b001; 1129 | instr_blt <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b100; 1130 | instr_bge <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b101; 1131 | instr_bltu <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b110; 1132 | instr_bgeu <= is_beq_bne_blt_bge_bltu_bgeu && mem_rdata_q[14:12] == 3'b111; 1133 | 1134 | instr_lb <= is_lb_lh_lw_lbu_lhu && mem_rdata_q[14:12] == 3'b000; 1135 | instr_lh <= is_lb_lh_lw_lbu_lhu && mem_rdata_q[14:12] == 3'b001; 1136 | instr_lw <= is_lb_lh_lw_lbu_lhu && mem_rdata_q[14:12] == 3'b010; 1137 | instr_lbu <= is_lb_lh_lw_lbu_lhu && mem_rdata_q[14:12] == 3'b100; 1138 | instr_lhu <= is_lb_lh_lw_lbu_lhu && mem_rdata_q[14:12] == 3'b101; 1139 | 1140 | instr_sb <= is_sb_sh_sw && mem_rdata_q[14:12] == 3'b000; 1141 | instr_sh <= is_sb_sh_sw && mem_rdata_q[14:12] == 3'b001; 1142 | instr_sw <= is_sb_sh_sw && mem_rdata_q[14:12] == 3'b010; 1143 | 1144 | instr_addi <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b000; 1145 | instr_slti <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b010; 1146 | instr_sltiu <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b011; 1147 | instr_xori <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b100; 1148 | instr_ori <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b110; 1149 | instr_andi <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b111; 1150 | 1151 | instr_slli <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000; 1152 | instr_srli <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000; 1153 | instr_srai <= is_alu_reg_imm && mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000; 1154 | 1155 | instr_add <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b000 && mem_rdata_q[31:25] == 7'b0000000; 1156 | instr_sub <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b000 && mem_rdata_q[31:25] == 7'b0100000; 1157 | instr_sll <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000; 1158 | instr_slt <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b010 && mem_rdata_q[31:25] == 7'b0000000; 1159 | instr_sltu <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b011 && mem_rdata_q[31:25] == 7'b0000000; 1160 | instr_xor <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b100 && mem_rdata_q[31:25] == 7'b0000000; 1161 | instr_srl <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000; 1162 | instr_sra <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000; 1163 | instr_or <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b110 && mem_rdata_q[31:25] == 7'b0000000; 1164 | instr_and <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b111 && mem_rdata_q[31:25] == 7'b0000000; 1165 | 1166 | instr_rdcycle <= ((mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11000000000000000010) || 1167 | (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11000000000100000010)) && ENABLE_COUNTERS; 1168 | instr_rdcycleh <= ((mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11001000000000000010) || 1169 | (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11001000000100000010)) && ENABLE_COUNTERS && ENABLE_COUNTERS64; 1170 | instr_rdinstr <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11000000001000000010) && ENABLE_COUNTERS; 1171 | instr_rdinstrh <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11001000001000000010) && ENABLE_COUNTERS && ENABLE_COUNTERS64; 1172 | 1173 | instr_ecall_ebreak <= ((mem_rdata_q[6:0] == 7'b1110011 && !mem_rdata_q[31:21] && !mem_rdata_q[19:7]) || 1174 | (COMPRESSED_ISA && mem_rdata_q[15:0] == 16'h9002)); 1175 | 1176 | instr_getq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000000 && ENABLE_IRQ && ENABLE_IRQ_QREGS; 1177 | instr_setq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000001 && ENABLE_IRQ && ENABLE_IRQ_QREGS; 1178 | instr_maskirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000011 && ENABLE_IRQ; 1179 | instr_timer <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000101 && ENABLE_IRQ && ENABLE_IRQ_TIMER; 1180 | 1181 | is_slli_srli_srai <= is_alu_reg_imm && |{ 1182 | mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000, 1183 | mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000, 1184 | mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000 1185 | }; 1186 | 1187 | is_jalr_addi_slti_sltiu_xori_ori_andi <= instr_jalr || is_alu_reg_imm && |{ 1188 | mem_rdata_q[14:12] == 3'b000, 1189 | mem_rdata_q[14:12] == 3'b010, 1190 | mem_rdata_q[14:12] == 3'b011, 1191 | mem_rdata_q[14:12] == 3'b100, 1192 | mem_rdata_q[14:12] == 3'b110, 1193 | mem_rdata_q[14:12] == 3'b111 1194 | }; 1195 | 1196 | is_sll_srl_sra <= is_alu_reg_reg && |{ 1197 | mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000, 1198 | mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000, 1199 | mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000 1200 | }; 1201 | 1202 | is_lui_auipc_jal_jalr_addi_add_sub <= 0; 1203 | is_compare <= 0; 1204 | 1205 | (* parallel_case *) 1206 | case (1'b1) 1207 | instr_jal: 1208 | decoded_imm <= decoded_imm_uj; 1209 | |{instr_lui, instr_auipc}: 1210 | decoded_imm <= mem_rdata_q[31:12] << 12; 1211 | |{instr_jalr, is_lb_lh_lw_lbu_lhu, is_alu_reg_imm}: 1212 | decoded_imm <= $signed(mem_rdata_q[31:20]); 1213 | is_beq_bne_blt_bge_bltu_bgeu: 1214 | decoded_imm <= $signed({mem_rdata_q[31], mem_rdata_q[7], mem_rdata_q[30:25], mem_rdata_q[11:8], 1'b0}); 1215 | is_sb_sh_sw: 1216 | decoded_imm <= $signed({mem_rdata_q[31:25], mem_rdata_q[11:7]}); 1217 | default: 1218 | decoded_imm <= 1'bx; 1219 | endcase 1220 | end 1221 | 1222 | if (!resetn) begin 1223 | is_beq_bne_blt_bge_bltu_bgeu <= 0; 1224 | is_compare <= 0; 1225 | 1226 | instr_beq <= 0; 1227 | instr_bne <= 0; 1228 | instr_blt <= 0; 1229 | instr_bge <= 0; 1230 | instr_bltu <= 0; 1231 | instr_bgeu <= 0; 1232 | 1233 | instr_addi <= 0; 1234 | instr_slti <= 0; 1235 | instr_sltiu <= 0; 1236 | instr_xori <= 0; 1237 | instr_ori <= 0; 1238 | instr_andi <= 0; 1239 | 1240 | instr_add <= 0; 1241 | instr_sub <= 0; 1242 | instr_sll <= 0; 1243 | instr_slt <= 0; 1244 | instr_sltu <= 0; 1245 | instr_xor <= 0; 1246 | instr_srl <= 0; 1247 | instr_sra <= 0; 1248 | instr_or <= 0; 1249 | instr_and <= 0; 1250 | end 1251 | end 1252 | 1253 | 1254 | // Main State Machine 1255 | 1256 | localparam cpu_state_trap = 8'b10000000; 1257 | localparam cpu_state_fetch = 8'b01000000; 1258 | localparam cpu_state_ld_rs1 = 8'b00100000; 1259 | localparam cpu_state_ld_rs2 = 8'b00010000; 1260 | localparam cpu_state_exec = 8'b00001000; 1261 | localparam cpu_state_shift = 8'b00000100; 1262 | localparam cpu_state_stmem = 8'b00000010; 1263 | localparam cpu_state_ldmem = 8'b00000001; 1264 | 1265 | reg [7:0] cpu_state; 1266 | reg [1:0] irq_state; 1267 | 1268 | `FORMAL_KEEP reg [127:0] dbg_ascii_state; 1269 | 1270 | always @* begin 1271 | dbg_ascii_state = ""; 1272 | if (cpu_state == cpu_state_trap) dbg_ascii_state = "trap"; 1273 | if (cpu_state == cpu_state_fetch) dbg_ascii_state = "fetch"; 1274 | if (cpu_state == cpu_state_ld_rs1) dbg_ascii_state = "ld_rs1"; 1275 | if (cpu_state == cpu_state_ld_rs2) dbg_ascii_state = "ld_rs2"; 1276 | if (cpu_state == cpu_state_exec) dbg_ascii_state = "exec"; 1277 | if (cpu_state == cpu_state_shift) dbg_ascii_state = "shift"; 1278 | if (cpu_state == cpu_state_stmem) dbg_ascii_state = "stmem"; 1279 | if (cpu_state == cpu_state_ldmem) dbg_ascii_state = "ldmem"; 1280 | end 1281 | 1282 | reg set_mem_do_rinst; 1283 | reg set_mem_do_rdata; 1284 | reg set_mem_do_wdata; 1285 | 1286 | reg latched_store; 1287 | reg latched_stalu; 1288 | reg latched_branch; 1289 | reg latched_compr; 1290 | reg latched_trace; 1291 | reg latched_is_lu; 1292 | reg latched_is_lh; 1293 | reg latched_is_lb; 1294 | reg [regindex_bits-1:0] latched_rd; 1295 | 1296 | reg [31:0] current_pc; 1297 | assign next_pc = latched_store && latched_branch ? reg_out & ~1 : reg_next_pc; 1298 | 1299 | reg [3:0] pcpi_timeout_counter; 1300 | reg pcpi_timeout; 1301 | 1302 | reg [31:0] next_irq_pending; 1303 | reg do_waitirq; 1304 | 1305 | reg [31:0] alu_out, alu_out_q; 1306 | reg alu_out_0, alu_out_0_q; 1307 | reg alu_wait, alu_wait_2; 1308 | 1309 | reg [31:0] alu_add_sub; 1310 | reg [31:0] alu_shl, alu_shr; 1311 | reg alu_eq, alu_ltu, alu_lts; 1312 | 1313 | generate if (TWO_CYCLE_ALU) begin 1314 | always @(posedge clk) begin 1315 | alu_add_sub <= instr_sub ? reg_op1 - reg_op2 : reg_op1 + reg_op2; 1316 | alu_eq <= reg_op1 == reg_op2; 1317 | alu_lts <= $signed(reg_op1) < $signed(reg_op2); 1318 | alu_ltu <= reg_op1 < reg_op2; 1319 | alu_shl <= reg_op1 << reg_op2[4:0]; 1320 | alu_shr <= $signed({instr_sra || instr_srai ? reg_op1[31] : 1'b0, reg_op1}) >>> reg_op2[4:0]; 1321 | end 1322 | end else begin 1323 | always @* begin 1324 | alu_add_sub = instr_sub ? reg_op1 - reg_op2 : reg_op1 + reg_op2; 1325 | alu_eq = reg_op1 == reg_op2; 1326 | alu_lts = $signed(reg_op1) < $signed(reg_op2); 1327 | alu_ltu = reg_op1 < reg_op2; 1328 | alu_shl = reg_op1 << reg_op2[4:0]; 1329 | alu_shr = $signed({instr_sra || instr_srai ? reg_op1[31] : 1'b0, reg_op1}) >>> reg_op2[4:0]; 1330 | end 1331 | end endgenerate 1332 | 1333 | always @* begin 1334 | alu_out_0 = 'bx; 1335 | (* parallel_case, full_case *) 1336 | case (1'b1) 1337 | instr_beq: 1338 | alu_out_0 = alu_eq; 1339 | instr_bne: 1340 | alu_out_0 = !alu_eq; 1341 | instr_bge: 1342 | alu_out_0 = !alu_lts; 1343 | instr_bgeu: 1344 | alu_out_0 = !alu_ltu; 1345 | is_slti_blt_slt && (!TWO_CYCLE_COMPARE || !{instr_beq,instr_bne,instr_bge,instr_bgeu}): 1346 | alu_out_0 = alu_lts; 1347 | is_sltiu_bltu_sltu && (!TWO_CYCLE_COMPARE || !{instr_beq,instr_bne,instr_bge,instr_bgeu}): 1348 | alu_out_0 = alu_ltu; 1349 | endcase 1350 | 1351 | alu_out = 'bx; 1352 | (* parallel_case, full_case *) 1353 | case (1'b1) 1354 | is_lui_auipc_jal_jalr_addi_add_sub: 1355 | alu_out = alu_add_sub; 1356 | is_compare: 1357 | alu_out = alu_out_0; 1358 | instr_xori || instr_xor: 1359 | alu_out = reg_op1 ^ reg_op2; 1360 | instr_ori || instr_or: 1361 | alu_out = reg_op1 | reg_op2; 1362 | instr_andi || instr_and: 1363 | alu_out = reg_op1 & reg_op2; 1364 | BARREL_SHIFTER && (instr_sll || instr_slli): 1365 | alu_out = alu_shl; 1366 | BARREL_SHIFTER && (instr_srl || instr_srli || instr_sra || instr_srai): 1367 | alu_out = alu_shr; 1368 | endcase 1369 | 1370 | `ifdef RISCV_FORMAL_BLACKBOX_ALU 1371 | alu_out_0 = $anyseq; 1372 | alu_out = $anyseq; 1373 | `endif 1374 | end 1375 | 1376 | reg clear_prefetched_high_word_q; 1377 | always @(posedge clk) clear_prefetched_high_word_q <= clear_prefetched_high_word; 1378 | 1379 | always @* begin 1380 | clear_prefetched_high_word = clear_prefetched_high_word_q; 1381 | if (!prefetched_high_word) 1382 | clear_prefetched_high_word = 0; 1383 | if (latched_branch || irq_state || !resetn) 1384 | clear_prefetched_high_word = COMPRESSED_ISA; 1385 | end 1386 | 1387 | reg cpuregs_write; 1388 | reg [31:0] cpuregs_wrdata; 1389 | reg [31:0] cpuregs_rs1; 1390 | reg [31:0] cpuregs_rs2; 1391 | reg [regindex_bits-1:0] decoded_rs; 1392 | 1393 | always @* begin 1394 | cpuregs_write = 0; 1395 | cpuregs_wrdata = 'bx; 1396 | 1397 | if (cpu_state == cpu_state_fetch) begin 1398 | (* parallel_case *) 1399 | case (1'b1) 1400 | latched_branch: begin 1401 | cpuregs_wrdata = reg_pc + (latched_compr ? 2 : 4); 1402 | cpuregs_write = 1; 1403 | end 1404 | latched_store && !latched_branch: begin 1405 | cpuregs_wrdata = latched_stalu ? alu_out_q : reg_out; 1406 | cpuregs_write = 1; 1407 | end 1408 | ENABLE_IRQ && irq_state[0]: begin 1409 | cpuregs_wrdata = reg_next_pc | latched_compr; 1410 | cpuregs_write = 1; 1411 | end 1412 | ENABLE_IRQ && irq_state[1]: begin 1413 | cpuregs_wrdata = irq_pending & ~irq_mask; 1414 | cpuregs_write = 1; 1415 | end 1416 | endcase 1417 | end 1418 | end 1419 | 1420 | `ifndef PICORV32_REGS 1421 | always @(posedge clk) begin 1422 | if (resetn && cpuregs_write && latched_rd) 1423 | cpuregs[latched_rd] <= cpuregs_wrdata; 1424 | end 1425 | 1426 | always @* begin 1427 | decoded_rs = 'bx; 1428 | if (ENABLE_REGS_DUALPORT) begin 1429 | `ifndef RISCV_FORMAL_BLACKBOX_REGS 1430 | cpuregs_rs1 = decoded_rs1 ? cpuregs[decoded_rs1] : 0; 1431 | cpuregs_rs2 = decoded_rs2 ? cpuregs[decoded_rs2] : 0; 1432 | `else 1433 | cpuregs_rs1 = decoded_rs1 ? $anyseq : 0; 1434 | cpuregs_rs2 = decoded_rs2 ? $anyseq : 0; 1435 | `endif 1436 | end else begin 1437 | decoded_rs = (cpu_state == cpu_state_ld_rs2) ? decoded_rs2 : decoded_rs1; 1438 | `ifndef RISCV_FORMAL_BLACKBOX_REGS 1439 | cpuregs_rs1 = decoded_rs ? cpuregs[decoded_rs] : 0; 1440 | `else 1441 | cpuregs_rs1 = decoded_rs ? $anyseq : 0; 1442 | `endif 1443 | cpuregs_rs2 = cpuregs_rs1; 1444 | end 1445 | end 1446 | `else 1447 | wire[31:0] cpuregs_rdata1; 1448 | wire[31:0] cpuregs_rdata2; 1449 | 1450 | wire [5:0] cpuregs_waddr = latched_rd; 1451 | wire [5:0] cpuregs_raddr1 = ENABLE_REGS_DUALPORT ? decoded_rs1 : decoded_rs; 1452 | wire [5:0] cpuregs_raddr2 = ENABLE_REGS_DUALPORT ? decoded_rs2 : 0; 1453 | 1454 | `PICORV32_REGS cpuregs ( 1455 | .clk(clk), 1456 | .wen(resetn && cpuregs_write && latched_rd), 1457 | .waddr(cpuregs_waddr), 1458 | .raddr1(cpuregs_raddr1), 1459 | .raddr2(cpuregs_raddr2), 1460 | .wdata(cpuregs_wrdata), 1461 | .rdata1(cpuregs_rdata1), 1462 | .rdata2(cpuregs_rdata2) 1463 | ); 1464 | 1465 | always @* begin 1466 | decoded_rs = 'bx; 1467 | if (ENABLE_REGS_DUALPORT) begin 1468 | cpuregs_rs1 = decoded_rs1 ? cpuregs_rdata1 : 0; 1469 | cpuregs_rs2 = decoded_rs2 ? cpuregs_rdata2 : 0; 1470 | end else begin 1471 | decoded_rs = (cpu_state == cpu_state_ld_rs2) ? decoded_rs2 : decoded_rs1; 1472 | cpuregs_rs1 = decoded_rs ? cpuregs_rdata1 : 0; 1473 | cpuregs_rs2 = cpuregs_rs1; 1474 | end 1475 | end 1476 | `endif 1477 | 1478 | assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (!ENABLE_IRQ || irq_delay || irq_active || !(irq_pending & ~irq_mask)); 1479 | 1480 | always @(posedge clk) begin 1481 | trap <= 0; 1482 | reg_sh <= 'bx; 1483 | reg_out <= 'bx; 1484 | set_mem_do_rinst = 0; 1485 | set_mem_do_rdata = 0; 1486 | set_mem_do_wdata = 0; 1487 | 1488 | alu_out_0_q <= alu_out_0; 1489 | alu_out_q <= alu_out; 1490 | 1491 | alu_wait <= 0; 1492 | alu_wait_2 <= 0; 1493 | 1494 | if (launch_next_insn) begin 1495 | dbg_rs1val <= 'bx; 1496 | dbg_rs2val <= 'bx; 1497 | dbg_rs1val_valid <= 0; 1498 | dbg_rs2val_valid <= 0; 1499 | end 1500 | 1501 | if (WITH_PCPI && CATCH_ILLINSN) begin 1502 | if (resetn && pcpi_valid && !pcpi_int_wait) begin 1503 | if (pcpi_timeout_counter) 1504 | pcpi_timeout_counter <= pcpi_timeout_counter - 1; 1505 | end else 1506 | pcpi_timeout_counter <= ~0; 1507 | pcpi_timeout <= !pcpi_timeout_counter; 1508 | end 1509 | 1510 | if (ENABLE_COUNTERS) begin 1511 | count_cycle <= resetn ? count_cycle + 1 : 0; 1512 | if (!ENABLE_COUNTERS64) count_cycle[63:32] <= 0; 1513 | end else begin 1514 | count_cycle <= 'bx; 1515 | count_instr <= 'bx; 1516 | end 1517 | 1518 | next_irq_pending = ENABLE_IRQ ? irq_pending & LATCHED_IRQ : 'bx; 1519 | 1520 | if (ENABLE_IRQ && ENABLE_IRQ_TIMER && timer) begin 1521 | if (timer - 1 == 0) 1522 | next_irq_pending[irq_timer] = 1; 1523 | timer <= timer - 1; 1524 | end 1525 | 1526 | if (ENABLE_IRQ) begin 1527 | next_irq_pending = next_irq_pending | irq; 1528 | end 1529 | 1530 | decoder_trigger <= mem_do_rinst && mem_done; 1531 | decoder_trigger_q <= decoder_trigger; 1532 | decoder_pseudo_trigger <= 0; 1533 | decoder_pseudo_trigger_q <= decoder_pseudo_trigger; 1534 | do_waitirq <= 0; 1535 | 1536 | trace_valid <= 0; 1537 | 1538 | if (!ENABLE_TRACE) 1539 | trace_data <= 'bx; 1540 | 1541 | if (!resetn) begin 1542 | reg_pc <= PROGADDR_RESET; 1543 | reg_next_pc <= PROGADDR_RESET; 1544 | if (ENABLE_COUNTERS) 1545 | count_instr <= 0; 1546 | latched_store <= 0; 1547 | latched_stalu <= 0; 1548 | latched_branch <= 0; 1549 | latched_trace <= 0; 1550 | latched_is_lu <= 0; 1551 | latched_is_lh <= 0; 1552 | latched_is_lb <= 0; 1553 | pcpi_valid <= 0; 1554 | pcpi_timeout <= 0; 1555 | irq_active <= 0; 1556 | irq_delay <= 0; 1557 | irq_mask <= ~0; 1558 | next_irq_pending = 0; 1559 | irq_state <= 0; 1560 | eoi <= 0; 1561 | timer <= 0; 1562 | if (~STACKADDR) begin 1563 | latched_store <= 1; 1564 | latched_rd <= 2; 1565 | reg_out <= STACKADDR; 1566 | end 1567 | cpu_state <= cpu_state_fetch; 1568 | end else 1569 | (* parallel_case, full_case *) 1570 | case (cpu_state) 1571 | cpu_state_trap: begin 1572 | trap <= 1; 1573 | end 1574 | 1575 | cpu_state_fetch: begin 1576 | mem_do_rinst <= !decoder_trigger && !do_waitirq; 1577 | mem_wordsize <= 0; 1578 | 1579 | current_pc = reg_next_pc; 1580 | 1581 | (* parallel_case *) 1582 | case (1'b1) 1583 | latched_branch: begin 1584 | current_pc = latched_store ? (latched_stalu ? alu_out_q : reg_out) & ~1 : reg_next_pc; 1585 | `debug($display("ST_RD: %2d 0x%08x, BRANCH 0x%08x", latched_rd, reg_pc + (latched_compr ? 2 : 4), current_pc);) 1586 | end 1587 | latched_store && !latched_branch: begin 1588 | `debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? alu_out_q : reg_out);) 1589 | end 1590 | ENABLE_IRQ && irq_state[0]: begin 1591 | current_pc = PROGADDR_IRQ; 1592 | irq_active <= 1; 1593 | mem_do_rinst <= 1; 1594 | end 1595 | ENABLE_IRQ && irq_state[1]: begin 1596 | eoi <= irq_pending & ~irq_mask; 1597 | next_irq_pending = next_irq_pending & irq_mask; 1598 | end 1599 | endcase 1600 | 1601 | if (ENABLE_TRACE && latched_trace) begin 1602 | latched_trace <= 0; 1603 | trace_valid <= 1; 1604 | if (latched_branch) 1605 | trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_BRANCH | (current_pc & 32'hfffffffe); 1606 | else 1607 | trace_data <= (irq_active ? TRACE_IRQ : 0) | (latched_stalu ? alu_out_q : reg_out); 1608 | end 1609 | 1610 | reg_pc <= current_pc; 1611 | reg_next_pc <= current_pc; 1612 | 1613 | latched_store <= 0; 1614 | latched_stalu <= 0; 1615 | latched_branch <= 0; 1616 | latched_is_lu <= 0; 1617 | latched_is_lh <= 0; 1618 | latched_is_lb <= 0; 1619 | latched_rd <= decoded_rd; 1620 | latched_compr <= compressed_instr; 1621 | 1622 | if (ENABLE_IRQ && ((decoder_trigger && !irq_active && !irq_delay && |(irq_pending & ~irq_mask)) || irq_state)) begin 1623 | irq_state <= 1624 | irq_state == 2'b00 ? 2'b01 : 1625 | irq_state == 2'b01 ? 2'b10 : 2'b00; 1626 | latched_compr <= latched_compr; 1627 | if (ENABLE_IRQ_QREGS) 1628 | latched_rd <= irqregs_offset | irq_state[0]; 1629 | else 1630 | latched_rd <= irq_state[0] ? 4 : 3; 1631 | end else 1632 | if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin 1633 | if (irq_pending) begin 1634 | latched_store <= 1; 1635 | reg_out <= irq_pending; 1636 | reg_next_pc <= current_pc + (compressed_instr ? 2 : 4); 1637 | mem_do_rinst <= 1; 1638 | end else 1639 | do_waitirq <= 1; 1640 | end else 1641 | if (decoder_trigger) begin 1642 | `debug($display("-- %-0t", $time);) 1643 | irq_delay <= irq_active; 1644 | reg_next_pc <= current_pc + (compressed_instr ? 2 : 4); 1645 | if (ENABLE_TRACE) 1646 | latched_trace <= 1; 1647 | if (ENABLE_COUNTERS) begin 1648 | count_instr <= count_instr + 1; 1649 | if (!ENABLE_COUNTERS64) count_instr[63:32] <= 0; 1650 | end 1651 | if (instr_jal) begin 1652 | mem_do_rinst <= 1; 1653 | reg_next_pc <= current_pc + decoded_imm_uj; 1654 | latched_branch <= 1; 1655 | end else begin 1656 | mem_do_rinst <= 0; 1657 | mem_do_prefetch <= !instr_jalr && !instr_retirq; 1658 | cpu_state <= cpu_state_ld_rs1; 1659 | end 1660 | end 1661 | end 1662 | 1663 | cpu_state_ld_rs1: begin 1664 | reg_op1 <= 'bx; 1665 | reg_op2 <= 'bx; 1666 | 1667 | (* parallel_case *) 1668 | case (1'b1) 1669 | (CATCH_ILLINSN || WITH_PCPI) && instr_trap: begin 1670 | if (WITH_PCPI) begin 1671 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1672 | reg_op1 <= cpuregs_rs1; 1673 | dbg_rs1val <= cpuregs_rs1; 1674 | dbg_rs1val_valid <= 1; 1675 | if (ENABLE_REGS_DUALPORT) begin 1676 | pcpi_valid <= 1; 1677 | `debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, cpuregs_rs2);) 1678 | reg_sh <= cpuregs_rs2; 1679 | reg_op2 <= cpuregs_rs2; 1680 | dbg_rs2val <= cpuregs_rs2; 1681 | dbg_rs2val_valid <= 1; 1682 | if (pcpi_int_ready) begin 1683 | mem_do_rinst <= 1; 1684 | pcpi_valid <= 0; 1685 | reg_out <= pcpi_int_rd; 1686 | latched_store <= pcpi_int_wr; 1687 | cpu_state <= cpu_state_fetch; 1688 | end else 1689 | if (CATCH_ILLINSN && (pcpi_timeout || instr_ecall_ebreak)) begin 1690 | pcpi_valid <= 0; 1691 | `debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);) 1692 | if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin 1693 | next_irq_pending[irq_ebreak] = 1; 1694 | cpu_state <= cpu_state_fetch; 1695 | end else 1696 | cpu_state <= cpu_state_trap; 1697 | end 1698 | end else begin 1699 | cpu_state <= cpu_state_ld_rs2; 1700 | end 1701 | end else begin 1702 | `debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);) 1703 | if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin 1704 | next_irq_pending[irq_ebreak] = 1; 1705 | cpu_state <= cpu_state_fetch; 1706 | end else 1707 | cpu_state <= cpu_state_trap; 1708 | end 1709 | end 1710 | ENABLE_COUNTERS && is_rdcycle_rdcycleh_rdinstr_rdinstrh: begin 1711 | (* parallel_case, full_case *) 1712 | case (1'b1) 1713 | instr_rdcycle: 1714 | reg_out <= count_cycle[31:0]; 1715 | instr_rdcycleh && ENABLE_COUNTERS64: 1716 | reg_out <= count_cycle[63:32]; 1717 | instr_rdinstr: 1718 | reg_out <= count_instr[31:0]; 1719 | instr_rdinstrh && ENABLE_COUNTERS64: 1720 | reg_out <= count_instr[63:32]; 1721 | endcase 1722 | latched_store <= 1; 1723 | cpu_state <= cpu_state_fetch; 1724 | end 1725 | is_lui_auipc_jal: begin 1726 | reg_op1 <= instr_lui ? 0 : reg_pc; 1727 | reg_op2 <= decoded_imm; 1728 | if (TWO_CYCLE_ALU) 1729 | alu_wait <= 1; 1730 | else 1731 | mem_do_rinst <= mem_do_prefetch; 1732 | cpu_state <= cpu_state_exec; 1733 | end 1734 | ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_getq: begin 1735 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1736 | reg_out <= cpuregs_rs1; 1737 | dbg_rs1val <= cpuregs_rs1; 1738 | dbg_rs1val_valid <= 1; 1739 | latched_store <= 1; 1740 | cpu_state <= cpu_state_fetch; 1741 | end 1742 | ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_setq: begin 1743 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1744 | reg_out <= cpuregs_rs1; 1745 | dbg_rs1val <= cpuregs_rs1; 1746 | dbg_rs1val_valid <= 1; 1747 | latched_rd <= latched_rd | irqregs_offset; 1748 | latched_store <= 1; 1749 | cpu_state <= cpu_state_fetch; 1750 | end 1751 | ENABLE_IRQ && instr_retirq: begin 1752 | eoi <= 0; 1753 | irq_active <= 0; 1754 | latched_branch <= 1; 1755 | latched_store <= 1; 1756 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1757 | reg_out <= CATCH_MISALIGN ? (cpuregs_rs1 & 32'h fffffffe) : cpuregs_rs1; 1758 | dbg_rs1val <= cpuregs_rs1; 1759 | dbg_rs1val_valid <= 1; 1760 | cpu_state <= cpu_state_fetch; 1761 | end 1762 | ENABLE_IRQ && instr_maskirq: begin 1763 | latched_store <= 1; 1764 | reg_out <= irq_mask; 1765 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1766 | irq_mask <= cpuregs_rs1 | MASKED_IRQ; 1767 | dbg_rs1val <= cpuregs_rs1; 1768 | dbg_rs1val_valid <= 1; 1769 | cpu_state <= cpu_state_fetch; 1770 | end 1771 | ENABLE_IRQ && ENABLE_IRQ_TIMER && instr_timer: begin 1772 | latched_store <= 1; 1773 | reg_out <= timer; 1774 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1775 | timer <= cpuregs_rs1; 1776 | dbg_rs1val <= cpuregs_rs1; 1777 | dbg_rs1val_valid <= 1; 1778 | cpu_state <= cpu_state_fetch; 1779 | end 1780 | is_lb_lh_lw_lbu_lhu && !instr_trap: begin 1781 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1782 | reg_op1 <= cpuregs_rs1; 1783 | dbg_rs1val <= cpuregs_rs1; 1784 | dbg_rs1val_valid <= 1; 1785 | cpu_state <= cpu_state_ldmem; 1786 | mem_do_rinst <= 1; 1787 | end 1788 | is_slli_srli_srai && !BARREL_SHIFTER: begin 1789 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1790 | reg_op1 <= cpuregs_rs1; 1791 | dbg_rs1val <= cpuregs_rs1; 1792 | dbg_rs1val_valid <= 1; 1793 | reg_sh <= decoded_rs2; 1794 | cpu_state <= cpu_state_shift; 1795 | end 1796 | is_jalr_addi_slti_sltiu_xori_ori_andi, is_slli_srli_srai && BARREL_SHIFTER: begin 1797 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1798 | reg_op1 <= cpuregs_rs1; 1799 | dbg_rs1val <= cpuregs_rs1; 1800 | dbg_rs1val_valid <= 1; 1801 | reg_op2 <= is_slli_srli_srai && BARREL_SHIFTER ? decoded_rs2 : decoded_imm; 1802 | if (TWO_CYCLE_ALU) 1803 | alu_wait <= 1; 1804 | else 1805 | mem_do_rinst <= mem_do_prefetch; 1806 | cpu_state <= cpu_state_exec; 1807 | end 1808 | default: begin 1809 | `debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);) 1810 | reg_op1 <= cpuregs_rs1; 1811 | dbg_rs1val <= cpuregs_rs1; 1812 | dbg_rs1val_valid <= 1; 1813 | if (ENABLE_REGS_DUALPORT) begin 1814 | `debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, cpuregs_rs2);) 1815 | reg_sh <= cpuregs_rs2; 1816 | reg_op2 <= cpuregs_rs2; 1817 | dbg_rs2val <= cpuregs_rs2; 1818 | dbg_rs2val_valid <= 1; 1819 | (* parallel_case *) 1820 | case (1'b1) 1821 | is_sb_sh_sw: begin 1822 | cpu_state <= cpu_state_stmem; 1823 | mem_do_rinst <= 1; 1824 | end 1825 | is_sll_srl_sra && !BARREL_SHIFTER: begin 1826 | cpu_state <= cpu_state_shift; 1827 | end 1828 | default: begin 1829 | if (TWO_CYCLE_ALU || (TWO_CYCLE_COMPARE && is_beq_bne_blt_bge_bltu_bgeu)) begin 1830 | alu_wait_2 <= TWO_CYCLE_ALU && (TWO_CYCLE_COMPARE && is_beq_bne_blt_bge_bltu_bgeu); 1831 | alu_wait <= 1; 1832 | end else 1833 | mem_do_rinst <= mem_do_prefetch; 1834 | cpu_state <= cpu_state_exec; 1835 | end 1836 | endcase 1837 | end else 1838 | cpu_state <= cpu_state_ld_rs2; 1839 | end 1840 | endcase 1841 | end 1842 | 1843 | cpu_state_ld_rs2: begin 1844 | `debug($display("LD_RS2: %2d 0x%08x", decoded_rs2, cpuregs_rs2);) 1845 | reg_sh <= cpuregs_rs2; 1846 | reg_op2 <= cpuregs_rs2; 1847 | dbg_rs2val <= cpuregs_rs2; 1848 | dbg_rs2val_valid <= 1; 1849 | 1850 | (* parallel_case *) 1851 | case (1'b1) 1852 | WITH_PCPI && instr_trap: begin 1853 | pcpi_valid <= 1; 1854 | if (pcpi_int_ready) begin 1855 | mem_do_rinst <= 1; 1856 | pcpi_valid <= 0; 1857 | reg_out <= pcpi_int_rd; 1858 | latched_store <= pcpi_int_wr; 1859 | cpu_state <= cpu_state_fetch; 1860 | end else 1861 | if (CATCH_ILLINSN && (pcpi_timeout || instr_ecall_ebreak)) begin 1862 | pcpi_valid <= 0; 1863 | `debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);) 1864 | if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin 1865 | next_irq_pending[irq_ebreak] = 1; 1866 | cpu_state <= cpu_state_fetch; 1867 | end else 1868 | cpu_state <= cpu_state_trap; 1869 | end 1870 | end 1871 | is_sb_sh_sw: begin 1872 | cpu_state <= cpu_state_stmem; 1873 | mem_do_rinst <= 1; 1874 | end 1875 | is_sll_srl_sra && !BARREL_SHIFTER: begin 1876 | cpu_state <= cpu_state_shift; 1877 | end 1878 | default: begin 1879 | if (TWO_CYCLE_ALU || (TWO_CYCLE_COMPARE && is_beq_bne_blt_bge_bltu_bgeu)) begin 1880 | alu_wait_2 <= TWO_CYCLE_ALU && (TWO_CYCLE_COMPARE && is_beq_bne_blt_bge_bltu_bgeu); 1881 | alu_wait <= 1; 1882 | end else 1883 | mem_do_rinst <= mem_do_prefetch; 1884 | cpu_state <= cpu_state_exec; 1885 | end 1886 | endcase 1887 | end 1888 | 1889 | cpu_state_exec: begin 1890 | reg_out <= reg_pc + decoded_imm; 1891 | if ((TWO_CYCLE_ALU || TWO_CYCLE_COMPARE) && (alu_wait || alu_wait_2)) begin 1892 | mem_do_rinst <= mem_do_prefetch && !alu_wait_2; 1893 | alu_wait <= alu_wait_2; 1894 | end else 1895 | if (is_beq_bne_blt_bge_bltu_bgeu) begin 1896 | latched_rd <= 0; 1897 | latched_store <= TWO_CYCLE_COMPARE ? alu_out_0_q : alu_out_0; 1898 | latched_branch <= TWO_CYCLE_COMPARE ? alu_out_0_q : alu_out_0; 1899 | if (mem_done) 1900 | cpu_state <= cpu_state_fetch; 1901 | if (TWO_CYCLE_COMPARE ? alu_out_0_q : alu_out_0) begin 1902 | decoder_trigger <= 0; 1903 | set_mem_do_rinst = 1; 1904 | end 1905 | end else begin 1906 | latched_branch <= instr_jalr; 1907 | latched_store <= 1; 1908 | latched_stalu <= 1; 1909 | cpu_state <= cpu_state_fetch; 1910 | end 1911 | end 1912 | 1913 | cpu_state_shift: begin 1914 | latched_store <= 1; 1915 | if (reg_sh == 0) begin 1916 | reg_out <= reg_op1; 1917 | mem_do_rinst <= mem_do_prefetch; 1918 | cpu_state <= cpu_state_fetch; 1919 | end else if (TWO_STAGE_SHIFT && reg_sh >= 4) begin 1920 | (* parallel_case, full_case *) 1921 | case (1'b1) 1922 | instr_slli || instr_sll: reg_op1 <= reg_op1 << 4; 1923 | instr_srli || instr_srl: reg_op1 <= reg_op1 >> 4; 1924 | instr_srai || instr_sra: reg_op1 <= $signed(reg_op1) >>> 4; 1925 | endcase 1926 | reg_sh <= reg_sh - 4; 1927 | end else begin 1928 | (* parallel_case, full_case *) 1929 | case (1'b1) 1930 | instr_slli || instr_sll: reg_op1 <= reg_op1 << 1; 1931 | instr_srli || instr_srl: reg_op1 <= reg_op1 >> 1; 1932 | instr_srai || instr_sra: reg_op1 <= $signed(reg_op1) >>> 1; 1933 | endcase 1934 | reg_sh <= reg_sh - 1; 1935 | end 1936 | end 1937 | 1938 | cpu_state_stmem: begin 1939 | if (ENABLE_TRACE) 1940 | reg_out <= reg_op2; 1941 | if (!mem_do_prefetch || mem_done) begin 1942 | if (!mem_do_wdata) begin 1943 | (* parallel_case, full_case *) 1944 | case (1'b1) 1945 | instr_sb: mem_wordsize <= 2; 1946 | instr_sh: mem_wordsize <= 1; 1947 | instr_sw: mem_wordsize <= 0; 1948 | endcase 1949 | if (ENABLE_TRACE) begin 1950 | trace_valid <= 1; 1951 | trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff); 1952 | end 1953 | reg_op1 <= reg_op1 + decoded_imm; 1954 | set_mem_do_wdata = 1; 1955 | end 1956 | if (!mem_do_prefetch && mem_done) begin 1957 | cpu_state <= cpu_state_fetch; 1958 | decoder_trigger <= 1; 1959 | decoder_pseudo_trigger <= 1; 1960 | end 1961 | end 1962 | end 1963 | 1964 | cpu_state_ldmem: begin 1965 | latched_store <= 1; 1966 | if (!mem_do_prefetch || mem_done) begin 1967 | if (!mem_do_rdata) begin 1968 | (* parallel_case, full_case *) 1969 | case (1'b1) 1970 | instr_lb || instr_lbu: mem_wordsize <= 2; 1971 | instr_lh || instr_lhu: mem_wordsize <= 1; 1972 | instr_lw: mem_wordsize <= 0; 1973 | endcase 1974 | latched_is_lu <= is_lbu_lhu_lw; 1975 | latched_is_lh <= instr_lh; 1976 | latched_is_lb <= instr_lb; 1977 | if (ENABLE_TRACE) begin 1978 | trace_valid <= 1; 1979 | trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff); 1980 | end 1981 | reg_op1 <= reg_op1 + decoded_imm; 1982 | set_mem_do_rdata = 1; 1983 | end 1984 | if (!mem_do_prefetch && mem_done) begin 1985 | (* parallel_case, full_case *) 1986 | case (1'b1) 1987 | latched_is_lu: reg_out <= mem_rdata_word; 1988 | latched_is_lh: reg_out <= $signed(mem_rdata_word[15:0]); 1989 | latched_is_lb: reg_out <= $signed(mem_rdata_word[7:0]); 1990 | endcase 1991 | decoder_trigger <= 1; 1992 | decoder_pseudo_trigger <= 1; 1993 | cpu_state <= cpu_state_fetch; 1994 | end 1995 | end 1996 | end 1997 | endcase 1998 | 1999 | if (CATCH_MISALIGN && resetn && (mem_do_rdata || mem_do_wdata)) begin 2000 | if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin 2001 | `debug($display("MISALIGNED WORD: 0x%08x", reg_op1);) 2002 | if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin 2003 | next_irq_pending[irq_buserror] = 1; 2004 | end else 2005 | cpu_state <= cpu_state_trap; 2006 | end 2007 | if (mem_wordsize == 1 && reg_op1[0] != 0) begin 2008 | `debug($display("MISALIGNED HALFWORD: 0x%08x", reg_op1);) 2009 | if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin 2010 | next_irq_pending[irq_buserror] = 1; 2011 | end else 2012 | cpu_state <= cpu_state_trap; 2013 | end 2014 | end 2015 | if (CATCH_MISALIGN && resetn && mem_do_rinst && (COMPRESSED_ISA ? reg_pc[0] : |reg_pc[1:0])) begin 2016 | `debug($display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);) 2017 | if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin 2018 | next_irq_pending[irq_buserror] = 1; 2019 | end else 2020 | cpu_state <= cpu_state_trap; 2021 | end 2022 | if (!CATCH_ILLINSN && decoder_trigger_q && !decoder_pseudo_trigger_q && instr_ecall_ebreak) begin 2023 | cpu_state <= cpu_state_trap; 2024 | end 2025 | 2026 | if (!resetn || mem_done) begin 2027 | mem_do_prefetch <= 0; 2028 | mem_do_rinst <= 0; 2029 | mem_do_rdata <= 0; 2030 | mem_do_wdata <= 0; 2031 | end 2032 | 2033 | if (set_mem_do_rinst) 2034 | mem_do_rinst <= 1; 2035 | if (set_mem_do_rdata) 2036 | mem_do_rdata <= 1; 2037 | if (set_mem_do_wdata) 2038 | mem_do_wdata <= 1; 2039 | 2040 | irq_pending <= next_irq_pending & ~MASKED_IRQ; 2041 | 2042 | if (!CATCH_MISALIGN) begin 2043 | if (COMPRESSED_ISA) begin 2044 | reg_pc[0] <= 0; 2045 | reg_next_pc[0] <= 0; 2046 | end else begin 2047 | reg_pc[1:0] <= 0; 2048 | reg_next_pc[1:0] <= 0; 2049 | end 2050 | end 2051 | current_pc = 'bx; 2052 | end 2053 | 2054 | `ifdef RISCV_FORMAL 2055 | reg dbg_irq_call; 2056 | reg dbg_irq_enter; 2057 | reg [31:0] dbg_irq_ret; 2058 | always @(posedge clk) begin 2059 | rvfi_valid <= resetn && (launch_next_insn || trap) && dbg_valid_insn; 2060 | rvfi_order <= resetn ? rvfi_order + rvfi_valid : 0; 2061 | 2062 | rvfi_insn <= dbg_insn_opcode; 2063 | rvfi_rs1_addr <= dbg_rs1val_valid ? dbg_insn_rs1 : 0; 2064 | rvfi_rs2_addr <= dbg_rs2val_valid ? dbg_insn_rs2 : 0; 2065 | rvfi_pc_rdata <= dbg_insn_addr; 2066 | rvfi_rs1_rdata <= dbg_rs1val_valid ? dbg_rs1val : 0; 2067 | rvfi_rs2_rdata <= dbg_rs2val_valid ? dbg_rs2val : 0; 2068 | rvfi_trap <= trap; 2069 | rvfi_halt <= trap; 2070 | rvfi_intr <= dbg_irq_enter; 2071 | 2072 | if (!resetn) begin 2073 | dbg_irq_call <= 0; 2074 | dbg_irq_enter <= 0; 2075 | end else 2076 | if (rvfi_valid) begin 2077 | dbg_irq_call <= 0; 2078 | dbg_irq_enter <= dbg_irq_call; 2079 | end else 2080 | if (irq_state == 1) begin 2081 | dbg_irq_call <= 1; 2082 | dbg_irq_ret <= next_pc; 2083 | end 2084 | 2085 | if (!resetn) begin 2086 | rvfi_rd_addr <= 0; 2087 | rvfi_rd_wdata <= 0; 2088 | end else 2089 | if (cpuregs_write && !irq_state) begin 2090 | rvfi_rd_addr <= latched_rd; 2091 | rvfi_rd_wdata <= latched_rd ? cpuregs_wrdata : 0; 2092 | end else 2093 | if (rvfi_valid) begin 2094 | rvfi_rd_addr <= 0; 2095 | rvfi_rd_wdata <= 0; 2096 | end 2097 | 2098 | casez (dbg_insn_opcode) 2099 | 32'b 0000000_?????_000??_???_?????_0001011: begin // getq 2100 | rvfi_rs1_addr <= 0; 2101 | rvfi_rs1_rdata <= 0; 2102 | end 2103 | 32'b 0000001_?????_?????_???_000??_0001011: begin // setq 2104 | rvfi_rd_addr <= 0; 2105 | rvfi_rd_wdata <= 0; 2106 | end 2107 | 32'b 0000010_?????_00000_???_00000_0001011: begin // retirq 2108 | rvfi_rs1_addr <= 0; 2109 | rvfi_rs1_rdata <= 0; 2110 | end 2111 | endcase 2112 | 2113 | if (!dbg_irq_call) begin 2114 | if (dbg_mem_instr) begin 2115 | rvfi_mem_addr <= 0; 2116 | rvfi_mem_rmask <= 0; 2117 | rvfi_mem_wmask <= 0; 2118 | rvfi_mem_rdata <= 0; 2119 | rvfi_mem_wdata <= 0; 2120 | end else 2121 | if (dbg_mem_valid && dbg_mem_ready) begin 2122 | rvfi_mem_addr <= dbg_mem_addr; 2123 | rvfi_mem_rmask <= dbg_mem_wstrb ? 0 : ~0; 2124 | rvfi_mem_wmask <= dbg_mem_wstrb; 2125 | rvfi_mem_rdata <= dbg_mem_rdata; 2126 | rvfi_mem_wdata <= dbg_mem_wdata; 2127 | end 2128 | end 2129 | end 2130 | 2131 | always @* begin 2132 | rvfi_pc_wdata = dbg_irq_call ? dbg_irq_ret : dbg_insn_addr; 2133 | end 2134 | `endif 2135 | 2136 | // Formal Verification 2137 | `ifdef FORMAL 2138 | reg [3:0] last_mem_nowait; 2139 | always @(posedge clk) 2140 | last_mem_nowait <= {last_mem_nowait, mem_ready || !mem_valid}; 2141 | 2142 | // stall the memory interface for max 4 cycles 2143 | restrict property (|last_mem_nowait || mem_ready || !mem_valid); 2144 | 2145 | // resetn low in first cycle, after that resetn high 2146 | restrict property (resetn != $initstate); 2147 | 2148 | // this just makes it much easier to read traces. uncomment as needed. 2149 | // assume property (mem_valid || !mem_ready); 2150 | 2151 | reg ok; 2152 | always @* begin 2153 | if (resetn) begin 2154 | // instruction fetches are read-only 2155 | if (mem_valid && mem_instr) 2156 | assert (mem_wstrb == 0); 2157 | 2158 | // cpu_state must be valid 2159 | ok = 0; 2160 | if (cpu_state == cpu_state_trap) ok = 1; 2161 | if (cpu_state == cpu_state_fetch) ok = 1; 2162 | if (cpu_state == cpu_state_ld_rs1) ok = 1; 2163 | if (cpu_state == cpu_state_ld_rs2) ok = !ENABLE_REGS_DUALPORT; 2164 | if (cpu_state == cpu_state_exec) ok = 1; 2165 | if (cpu_state == cpu_state_shift) ok = 1; 2166 | if (cpu_state == cpu_state_stmem) ok = 1; 2167 | if (cpu_state == cpu_state_ldmem) ok = 1; 2168 | assert (ok); 2169 | end 2170 | end 2171 | 2172 | reg last_mem_la_read = 0; 2173 | reg last_mem_la_write = 0; 2174 | reg [31:0] last_mem_la_addr; 2175 | reg [31:0] last_mem_la_wdata; 2176 | reg [3:0] last_mem_la_wstrb = 0; 2177 | 2178 | always @(posedge clk) begin 2179 | last_mem_la_read <= mem_la_read; 2180 | last_mem_la_write <= mem_la_write; 2181 | last_mem_la_addr <= mem_la_addr; 2182 | last_mem_la_wdata <= mem_la_wdata; 2183 | last_mem_la_wstrb <= mem_la_wstrb; 2184 | 2185 | if (last_mem_la_read) begin 2186 | assert(mem_valid); 2187 | assert(mem_addr == last_mem_la_addr); 2188 | assert(mem_wstrb == 0); 2189 | end 2190 | if (last_mem_la_write) begin 2191 | assert(mem_valid); 2192 | assert(mem_addr == last_mem_la_addr); 2193 | assert(mem_wdata == last_mem_la_wdata); 2194 | assert(mem_wstrb == last_mem_la_wstrb); 2195 | end 2196 | if (mem_la_read || mem_la_write) begin 2197 | assert(!mem_valid || mem_ready); 2198 | end 2199 | end 2200 | `endif 2201 | endmodule 2202 | 2203 | // This is a simple example implementation of PICORV32_REGS. 2204 | // Use the PICORV32_REGS mechanism if you want to use custom 2205 | // memory resources to implement the processor register file. 2206 | // Note that your implementation must match the requirements of 2207 | // the PicoRV32 configuration. (e.g. QREGS, etc) 2208 | module picorv32_regs ( 2209 | input clk, wen, 2210 | input [5:0] waddr, 2211 | input [5:0] raddr1, 2212 | input [5:0] raddr2, 2213 | input [31:0] wdata, 2214 | output [31:0] rdata1, 2215 | output [31:0] rdata2 2216 | ); 2217 | reg [31:0] regs [0:30]; 2218 | 2219 | always @(posedge clk) 2220 | if (wen) regs[~waddr[4:0]] <= wdata; 2221 | 2222 | assign rdata1 = regs[~raddr1[4:0]]; 2223 | assign rdata2 = regs[~raddr2[4:0]]; 2224 | endmodule 2225 | 2226 | -------------------------------------------------------------------------------- /soc/debug_insert.py: -------------------------------------------------------------------------------- 1 | sinks = [] 2 | # Rip the LED net up 3 | for i in range(8): 4 | ctx.ripupNet(f"soc_led[{i}]") 5 | sinks.append(ctx.nets[f"soc_led[{i}]"].users[0]) 6 | write_bitstream(ctx, "", "soc_dbg_unrouted.config") 7 | 8 | # Lock all other nets 9 | for net, net_data in ctx.nets: 10 | ctx.lockNetRouting(net) 11 | 12 | # Rewire to target debug register 13 | for i in range(8): 14 | ctx.disconnectPort(sinks[i].cell.name, sinks[i].port) 15 | ctx.connectPort(f"soc_i.cpu.reg_next_pc[{i+2}]", sinks[i].cell.name, sinks[i].port) -------------------------------------------------------------------------------- /soc/firmware.hex: -------------------------------------------------------------------------------- 1 | @00000000 2 | 13 04 10 00 B7 04 00 02 93 09 00 10 13 04 14 00 3 | 63 44 34 01 13 04 20 00 13 09 20 00 63 5E 89 00 4 | 13 05 04 00 93 05 09 00 EF 00 80 01 63 08 05 00 5 | 13 09 19 00 6F F0 9F FE 23 A0 84 00 6F F0 1F FD 6 | 93 02 10 00 33 05 B5 40 E3 5E 55 FE 67 80 00 00 -------------------------------------------------------------------------------- /soc/versa.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clkin" SITE "P3"; 2 | IOBUF PORT "clkin" IO_TYPE=LVDS; 3 | 4 | LOCATE COMP "led[0]" SITE "E16"; 5 | LOCATE COMP "led[1]" SITE "D17"; 6 | LOCATE COMP "led[2]" SITE "D18"; 7 | LOCATE COMP "led[3]" SITE "E18"; 8 | LOCATE COMP "led[4]" SITE "F17"; 9 | LOCATE COMP "led[5]" SITE "F18"; 10 | LOCATE COMP "led[6]" SITE "E17"; 11 | LOCATE COMP "led[7]" SITE "F16"; 12 | 13 | IOBUF PORT "led[0]" IO_TYPE=LVCMOS25; 14 | IOBUF PORT "led[1]" IO_TYPE=LVCMOS25; 15 | IOBUF PORT "led[2]" IO_TYPE=LVCMOS25; 16 | IOBUF PORT "led[3]" IO_TYPE=LVCMOS25; 17 | IOBUF PORT "led[4]" IO_TYPE=LVCMOS25; 18 | IOBUF PORT "led[5]" IO_TYPE=LVCMOS25; 19 | IOBUF PORT "led[6]" IO_TYPE=LVCMOS25; 20 | IOBUF PORT "led[7]" IO_TYPE=LVCMOS25; 21 | 22 | LOCATE COMP "disp[0]" SITE "M20"; 23 | LOCATE COMP "disp[1]" SITE "L18"; 24 | LOCATE COMP "disp[2]" SITE "M19"; 25 | LOCATE COMP "disp[3]" SITE "L16"; 26 | LOCATE COMP "disp[4]" SITE "L17"; 27 | LOCATE COMP "disp[5]" SITE "M18"; 28 | LOCATE COMP "disp[6]" SITE "N16"; 29 | LOCATE COMP "disp[7]" SITE "M17"; 30 | LOCATE COMP "disp[8]" SITE "N18"; 31 | LOCATE COMP "disp[9]" SITE "P17"; 32 | LOCATE COMP "disp[10]" SITE "N17"; 33 | LOCATE COMP "disp[11]" SITE "P16"; 34 | LOCATE COMP "disp[12]" SITE "R16"; 35 | LOCATE COMP "disp[13]" SITE "R17"; 36 | 37 | IOBUF PORT "disp[0]" IO_TYPE=LVCMOS25; 38 | IOBUF PORT "disp[1]" IO_TYPE=LVCMOS25; 39 | IOBUF PORT "disp[2]" IO_TYPE=LVCMOS25; 40 | IOBUF PORT "disp[3]" IO_TYPE=LVCMOS25; 41 | IOBUF PORT "disp[4]" IO_TYPE=LVCMOS25; 42 | IOBUF PORT "disp[5]" IO_TYPE=LVCMOS25; 43 | IOBUF PORT "disp[6]" IO_TYPE=LVCMOS25; 44 | IOBUF PORT "disp[7]" IO_TYPE=LVCMOS25; 45 | IOBUF PORT "disp[8]" IO_TYPE=LVCMOS25; 46 | IOBUF PORT "disp[9]" IO_TYPE=LVCMOS25; 47 | IOBUF PORT "disp[10]" IO_TYPE=LVCMOS25; 48 | IOBUF PORT "disp[11]" IO_TYPE=LVCMOS25; 49 | IOBUF PORT "disp[12]" IO_TYPE=LVCMOS25; 50 | IOBUF PORT "disp[13]" IO_TYPE=LVCMOS25; 51 | 52 | LOCATE COMP "uart_tx" SITE "A11"; 53 | LOCATE COMP "uart_rx" SITE "C11"; 54 | IOBUF PORT "uart_tx" IO_TYPE=LVCMOS33; 55 | IOBUF PORT "uart_rx" IO_TYPE=LVCMOS33; 56 | 57 | LOCATE COMP "gsrn" SITE "T1"; 58 | IOBUF PORT "gsrn" IO_TYPE=LVCMOS33; 59 | -------------------------------------------------------------------------------- /soc/versa5g_openocd.cfg: -------------------------------------------------------------------------------- 1 | # this supports ECP5 Versa board 2 | 3 | interface ftdi 4 | ftdi_device_desc "Lattice ECP5_5G VERSA Board" 5 | ftdi_vid_pid 0x0403 0x6010 6 | # channel 1 does not have any functionality 7 | ftdi_channel 0 8 | # just TCK TDI TDO TMS, no reset 9 | ftdi_layout_init 0xfff8 0xfffb 10 | reset_config none 11 | 12 | # default speed 13 | adapter_khz 25000 14 | 15 | # ispCLOCK device (should be bypassed by jumpers as it causes problems) 16 | #jtag newtap ispclock tap -irlen 8 -expected-id 0x00191043 17 | # ECP5 device - LFE5UM5G-45F 18 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 19 | -------------------------------------------------------------------------------- /soc/wrapper.v: -------------------------------------------------------------------------------- 1 | module top( 2 | input clkin, gsrn, 3 | output [7:0] led 4 | ); 5 | 6 | wire [7:0] soc_led; 7 | 8 | /* 9 | Run the SoC at a very slow clock for demonstration purposes 10 | */ 11 | reg [13:0] clkdiv; 12 | always @(posedge clkin) 13 | clkdiv <= clkdiv + 1'b1; 14 | 15 | attosoc soc_i ( 16 | .clk(clkdiv[13]), 17 | .reset(~gsrn), 18 | .led(soc_led), 19 | ); 20 | 21 | genvar ii; 22 | generate 23 | for (ii = 0; ii < 8; ii = ii + 1'b1) begin: led_buf 24 | LUT4 #(.INIT(16'h5555)) inv_i(.A(soc_led[ii]), .B(1'b1), .C(1'b1), .D(1'b1), .Z(led[ii])); 25 | end 26 | endgenerate 27 | 28 | endmodule --------------------------------------------------------------------------------