diff --git a/rtl/ip/spram_model.v b/rtl/ip/spram_model.v index 95210d96..a3484948 100644 --- a/rtl/ip/spram_model.v +++ b/rtl/ip/spram_model.v @@ -2,7 +2,7 @@ module spram_model ( input clk, input [ 3:0] wen, - input [21:0] addr, + input [13:0] addr, input [31:0] wdata, output [31:0] rdata ); diff --git a/rtl/picorv32.v b/rtl/picorv32.v index f49c3c47..f4b78eee 100644 --- a/rtl/picorv32.v +++ b/rtl/picorv32.v @@ -48,7 +48,7 @@ `endif // uncomment this for register file in extra module -// `define PICORV32_REGS picorv32_regs +`define PICORV32_REGS retrosoc_regs // this macro can be used to check if the verilog files in your // design are read in the correct order. @@ -2189,6 +2189,25 @@ module picorv32_regs ( assign rdata2 = regs[~raddr2[4:0]]; endmodule +// implementation note: +// replace the following two modules with wrappers for your SRAM cells. +module retrosoc_regs ( + input clk, + input wen, + input [ 5:0] waddr, + input [ 5:0] raddr1, + input [ 5:0] raddr2, + input [31:0] wdata, + output [31:0] rdata1, + output [31:0] rdata2 +); + reg [31:0] regs[0:31]; + + always @(posedge clk) if (wen) regs[waddr[4:0]] <= wdata; + + assign rdata1 = regs[raddr1[4:0]]; + assign rdata2 = regs[raddr2[4:0]]; +endmodule /*************************************************************** * picorv32_pcpi_mul diff --git a/rtl/retrosoc.v b/rtl/retrosoc.v index a0b629d4..3173b4d8 100644 --- a/rtl/retrosoc.v +++ b/rtl/retrosoc.v @@ -1,8 +1,10 @@ /* - * PicoSoC - A simple example SoC using PicoRV32 - * - * Copyright (C) 2017 Claire Xenia Wolf + * retroSoC - A simple example SoC using PicoRV32 * + * Copyright (C) 2017 Clifford Wolf + * Copyright (C) 2018,2019 Tim Edwards + * Copyright (C) 2025 Yuchi Miao + * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -17,51 +19,85 @@ * */ -`ifndef PICORV32_REGS -`ifdef PICORV32_V -// `error "picosoc.v must be read before picorv32.v!" -`endif +// `ifdef PICORV32_V +// `error "retrosoc.v must be read before picorv32.v!" +// `endif -`define PICORV32_REGS picosoc_regs -`endif +/* Note: Synthesize register memory from flops */ +/* Inefficient, but not terribly so */ -`ifndef PICOSOC_MEM -`define PICOSOC_MEM picosoc_mem -`endif - -// this macro can be used to check if the verilog files in your -// design are read in the correct order. -`define PICOSOC_V +/* Also note: To avoid having a hard macro in the place & route */ +/* (method not finished yet in qflow), SRAM pins are brought out to */ +/* the retrosoc I/O so that raven_soc.v itself is fully */ +/* synthesizable and routable with qflow as-is. */ +// `define PICORV32_REGS retrosoc_regs module retrosoc #( - parameter integer MEM_WORDS = 256, - parameter [ 0:0] BARREL_SHIFTER = 1, - parameter [ 0:0] COMPRESSED_ISA = 1, - parameter [ 0:0] ENABLE_MUL = 0, - parameter [ 0:0] ENABLE_FAST_MUL = 1, - parameter [ 0:0] ENABLE_DIV = 1, - parameter [ 0:0] ENABLE_IRQ = 0, - parameter [ 0:0] ENABLE_IRQ_QREGS = 1, - parameter [31:0] STACKADDR = (4 * MEM_WORDS), // end of memory - parameter [31:0] PROGADDR_RESET = 32'h0010_0000, // 1 MB into flash - parameter [31:0] PROGADDR_IRQ = 32'h0000_0000 + /* parameter integer MEM_WORDS = 256; */ + /* Increase scratchpad memory to 4K words */ + // parameter integer MEM_WORDS = 4096; + parameter integer MEM_WORDS = 16384, + parameter [31:0] STACKADDR = (4 * MEM_WORDS), // end of memory + parameter [31:0] PROGADDR_RESET = 32'h0010_0000 // 1 MB into flash ) ( input clk_i, input rst_n_i, - output iomem_valid_o, - input iomem_ready_i, - output [ 3:0] iomem_wstrb_o, - output [31:0] iomem_addr_o, - output [31:0] iomem_wdata_o, - input [31:0] iomem_rdata_i, + input xtal_in_i, + input clk_pll_i, + input clk_ext_sel_i, + // pass-through mode from housekeeping SPI + input hk_pt_i, + input hk_pt_csb_i, + input hk_pt_sck_i, + input hk_pt_sdi_i, + output hk_pt_sdo_o, + //sram if including clk_i and rst_n_i above + output [ 3:0] ram_wenb_o, + output [13:0] ram_addr_o, + output [31:0] ram_wdata_o, + input [31:0] ram_rdata_o, + // memory mapped I/O signals + output [15:0] gpio_out_o, + input [15:0] gpio_in_i, + output [15:0] gpio_pullupb_o, + output [15:0] gpio_pulldownb_o, + output [15:0] gpio_outenb_o, + input [ 7:0] spi_slv_ro_config_i, + input spi_slv_ro_xtal_ena_i, + input spi_slv_ro_reg_ena_i, + input spi_slv_ro_pll_cp_ena_i, + input spi_slv_ro_pll_vco_ena_i, + input spi_slv_ro_pll_bias_ena_i, + input [ 3:0] spi_slv_ro_pll_trim_i, + input [11:0] spi_slv_ro_mfgr_id_i, + input [ 7:0] spi_slv_ro_prod_id_i, + input [ 3:0] spi_slv_ro_mask_rev_i, output uart_tx_o, input uart_rx_i, + input i2c_scl_i, + output i2c_scl_o, + output i2c_scl_oeb_o, + input i2c_sda_i, + output i2c_sda_o, + output i2c_sda_oeb_o, + output spi_mst_sdo_o, + output spi_mst_csb_o, + output spi_mst_sck_o, + input spi_mst_sdi_i, + output spi_mst_oenb_o, + // irq + input irq_pin_i, + input irq_spi_i, + output trap_o, + // spi flash output flash_csb_o, output flash_clk_o, - output flash_io0_oe_o, - output flash_io1_oe_o, - output flash_io2_oe_o, - output flash_io3_oe_o, + output flash_clk_oeb_o, + output flash_csb_oeb_o, + output flash_io0_oeb_o, + output flash_io1_oeb_o, + output flash_io2_oeb_o, + output flash_io3_oeb_o, output flash_io0_do_o, output flash_io1_do_o, output flash_io2_do_o, @@ -72,6 +108,126 @@ module retrosoc #( input flash_io3_di_i ); + wire s_iomem_valid; + reg r_iomem_ready; + wire [ 3:0] s_iomem_wstrb; + wire [31:0] s_iomem_addr; + wire [31:0] s_iomem_wdata; + reg [31:0] r_iomem_rdata; + // memory-mapped I/O control registers + reg [15:0] r_gpio; + reg [15:0] r_gpio_pu; + reg [15:0] r_gpio_pd; + reg [15:0] r_gpio_oeb; + reg [ 1:0] r_pll_out_dest; + reg [ 1:0] r_xtal_out_dest; + reg [ 1:0] r_trap_out_dest; + reg [ 1:0] r_irq_7_in_src; + reg [ 1:0] r_irq_8_in_src; + + + // GPIO assignments + assign gpio_out_o[0] = r_gpio[0]; + assign gpio_out_o[1] = r_gpio[1]; + assign gpio_out_o[2] = r_gpio[2]; + assign gpio_out_o[3] = r_gpio[3]; + assign gpio_out_o[4] = r_gpio[4]; + assign gpio_out_o[5] = r_xtal_out_dest == 2'b01 ? xtal_in_i : r_gpio[5]; + assign gpio_out_o[6] = r_xtal_out_dest == 2'b10 ? xtal_in_i : r_gpio[6]; + assign gpio_out_o[7] = r_xtal_out_dest == 2'b11 ? xtal_in_i : r_gpio[7]; + assign gpio_out_o[8] = r_pll_out_dest == 2'b01 ? clk_pll_i : r_gpio[8]; + assign gpio_out_o[9] = r_pll_out_dest == 2'b10 ? clk_i : r_gpio[9]; + assign gpio_out_o[10] = r_gpio[10]; + assign gpio_out_o[11] = r_trap_out_dest == 2'b01 ? trap_o : r_gpio[11]; + assign gpio_out_o[12] = r_trap_out_dest == 2'b10 ? trap_o : r_gpio[12]; + assign gpio_out_o[13] = r_trap_out_dest == 2'b11 ? trap_o : r_gpio[13]; + assign gpio_out_o[14] = r_gpio[14]; + assign gpio_out_o[15] = r_gpio[15]; + + assign gpio_outenb_o[0] = ~rst_n_i | r_gpio_oeb[0]; + assign gpio_outenb_o[1] = ~rst_n_i | r_gpio_oeb[1]; + assign gpio_outenb_o[2] = ~rst_n_i | r_gpio_oeb[2]; + assign gpio_outenb_o[3] = ~rst_n_i | r_gpio_oeb[3]; + assign gpio_outenb_o[4] = ~rst_n_i | r_gpio_oeb[4]; + assign gpio_outenb_o[5] = ~rst_n_i | (r_xtal_out_dest == 2'b00 ? r_gpio_oeb[5] : 1'b0); + assign gpio_outenb_o[6] = ~rst_n_i | (r_xtal_out_dest == 2'b00 ? r_gpio_oeb[6] : 1'b0); + assign gpio_outenb_o[7] = ~rst_n_i | (r_xtal_out_dest == 2'b00 ? r_gpio_oeb[7] : 1'b0); + assign gpio_outenb_o[8] = ~rst_n_i | (r_pll_out_dest == 2'b00 ? r_gpio_oeb[8] : 1'b0); + assign gpio_outenb_o[9] = ~rst_n_i | (r_pll_out_dest == 2'b00 ? r_gpio_oeb[9] : 1'b0); + assign gpio_outenb_o[10] = ~rst_n_i | (r_pll_out_dest == 2'b00 ? r_gpio_oeb[10] : 1'b0); + assign gpio_outenb_o[11] = ~rst_n_i | (r_trap_out_dest == 2'b00 ? r_gpio_oeb[11] : 1'b0); + assign gpio_outenb_o[12] = ~rst_n_i | (r_trap_out_dest == 2'b00 ? r_gpio_oeb[12] : 1'b0); + assign gpio_outenb_o[13] = ~rst_n_i | (r_trap_out_dest == 2'b00 ? r_gpio_oeb[13] : 1'b0); + assign gpio_outenb_o[14] = ~rst_n_i | r_gpio_oeb[14]; + assign gpio_outenb_o[15] = ~rst_n_i | r_gpio_oeb[15]; + + assign gpio_pullupb_o[0] = r_gpio_pu[0]; + assign gpio_pullupb_o[1] = r_gpio_pu[1]; + assign gpio_pullupb_o[2] = r_gpio_pu[2]; + assign gpio_pullupb_o[3] = r_gpio_pu[3]; + assign gpio_pullupb_o[4] = r_gpio_pu[4]; + assign gpio_pullupb_o[5] = r_xtal_out_dest == 2'b00 ? r_gpio_pu[5] : 1'b1; + assign gpio_pullupb_o[6] = r_xtal_out_dest == 2'b00 ? r_gpio_pu[6] : 1'b1; + assign gpio_pullupb_o[7] = r_xtal_out_dest == 2'b00 ? r_gpio_pu[7] : 1'b1; + assign gpio_pullupb_o[8] = r_pll_out_dest == 2'b00 ? r_gpio_pu[8] : 1'b1; + assign gpio_pullupb_o[9] = r_pll_out_dest == 2'b00 ? r_gpio_pu[9] : 1'b1; + assign gpio_pullupb_o[10] = r_pll_out_dest == 2'b00 ? r_gpio_pu[10] : 1'b1; + assign gpio_pullupb_o[11] = r_trap_out_dest == 2'b00 ? r_gpio_pu[11] : 1'b1; + assign gpio_pullupb_o[12] = r_trap_out_dest == 2'b00 ? r_gpio_pu[12] : 1'b1; + assign gpio_pullupb_o[13] = r_trap_out_dest == 2'b00 ? r_gpio_pu[13] : 1'b1; + assign gpio_pullupb_o[14] = r_gpio_pu[14]; + assign gpio_pullupb_o[15] = r_gpio_pu[15]; + + assign gpio_pulldownb_o[0] = r_gpio_pd[0]; + assign gpio_pulldownb_o[1] = r_gpio_pd[1]; + assign gpio_pulldownb_o[2] = r_gpio_pd[2]; + assign gpio_pulldownb_o[3] = r_gpio_pd[3]; + assign gpio_pulldownb_o[4] = r_gpio_pd[4]; + assign gpio_pulldownb_o[5] = r_xtal_out_dest == 2'b00 ? r_gpio_pd[5] : 1'b1; + assign gpio_pulldownb_o[6] = r_xtal_out_dest == 2'b00 ? r_gpio_pd[6] : 1'b1; + assign gpio_pulldownb_o[7] = r_xtal_out_dest == 2'b00 ? r_gpio_pd[7] : 1'b1; + assign gpio_pulldownb_o[8] = r_pll_out_dest == 2'b00 ? r_gpio_pd[8] : 1'b1; + assign gpio_pulldownb_o[9] = r_pll_out_dest == 2'b00 ? r_gpio_pd[9] : 1'b1; + assign gpio_pulldownb_o[10] = r_pll_out_dest == 2'b00 ? r_gpio_pd[10] : 1'b1; + assign gpio_pulldownb_o[11] = r_trap_out_dest == 2'b00 ? r_gpio_pd[11] : 1'b1; + assign gpio_pulldownb_o[12] = r_trap_out_dest == 2'b00 ? r_gpio_pd[12] : 1'b1; + assign gpio_pulldownb_o[13] = r_trap_out_dest == 2'b00 ? r_gpio_pd[13] : 1'b1; + assign gpio_pulldownb_o[14] = r_gpio_pd[14]; + assign gpio_pulldownb_o[15] = r_gpio_pd[15]; + + wire s_irq_7, s_irq_8; + assign s_irq_7 = (r_irq_7_in_src == 2'b01) ? gpio_in_i[0] : + (r_irq_7_in_src == 2'b10) ? gpio_in_i[1] : + (r_irq_7_in_src == 2'b11) ? gpio_in_i[2] : 1'b0; + assign s_irq_8 = (r_irq_8_in_src == 2'b01) ? gpio_in_i[3] : + (r_irq_8_in_src == 2'b10) ? gpio_in_i[4] : + (r_irq_8_in_src == 2'b11) ? gpio_in_i[5] : 1'b0; + + assign ram_wenb_o = (s_mem_valid && !s_mem_ready && s_mem_addr < 4*MEM_WORDS) ? + {~s_mem_wstrb[3], ~s_mem_wstrb[2], ~s_mem_wstrb[1], ~s_mem_wstrb[0]} : 4'hf; + assign ram_addr_o = s_mem_addr[15:2]; + assign ram_wdata_o = s_mem_wdata; // just for naming conventions + + wire [31:0] s_irq; + wire s_irq_stall = 0; // not impl + wire s_irq_uart; + wire s_irq_i2c; + wire s_irq_spi_mst; + wire s_irq_tim0; + + assign s_irq[2:0] = 3'd0; + assign s_irq[3] = s_irq_stall; + assign s_irq[4] = s_irq_uart; + assign s_irq[5] = irq_pin_i; + assign s_irq[6] = irq_spi_i; + assign s_irq[7] = s_irq_7; + assign s_irq[8] = s_irq_8; + assign s_irq[9] = 1'd0; + assign s_irq[10] = 1'd0; + assign s_irq[11] = s_irq_i2c; + assign s_irq[12] = s_irq_spi_mst; + assign s_irq[13] = s_irq_tim0; + wire s_mem_valid; wire s_mem_instr; wire s_mem_ready; @@ -81,40 +237,123 @@ module retrosoc #( wire [31:0] s_mem_rdata; wire s_spimem_ready; wire [31:0] s_spimem_rdata; - reg s_ram_ready; - wire [31:0] s_ram_rdata; + reg r_ram_ready; - assign iomem_valid_o = s_mem_valid && (s_mem_addr[31:24] > 8'h01); - assign iomem_wstrb_o = s_mem_wstrb; - assign iomem_addr_o = s_mem_addr; - assign iomem_wdata_o = s_mem_wdata; + assign s_iomem_valid = s_mem_valid && (s_mem_addr[31:24] > 8'h02); + assign s_iomem_wstrb = s_mem_wstrb; + assign s_iomem_addr = s_mem_addr; + assign s_iomem_wdata = s_mem_wdata; + // spi flash wire s_spimemio_cfgreg_sel = s_mem_valid && (s_mem_addr == 32'h0200_0000); - wire [31:0] s_spimemio_cfgreg_do; - wire s_simpleuart_reg_div_sel = s_mem_valid && (s_mem_addr == 32'h0200_0004); - wire [31:0] s_simpleuart_reg_div_do; - wire s_simpleuart_reg_dat_sel = s_mem_valid && (s_mem_addr == 32'h0200_0008); - wire [31:0] s_simpleuart_reg_dat_do; + wire [31:0] s_spimemio_cfgreg_dout; + // uart + wire s_simpleuart_reg_div_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_0078); + wire s_simpleuart_reg_dat_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_007c); + wire [31:0] s_simpleuart_reg_div_dout; + wire [31:0] s_simpleuart_reg_dat_dout; wire s_simpleuart_reg_dat_wait; + // i2c + wire s_simplei2c_reg_cfg1_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00d4); + wire s_simplei2c_reg_cfg2_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00d8); + wire s_simplei2c_reg_dat_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00dc); + wire [31:0] s_simplei2c_reg_cfg1_dout; + wire [31:0] s_simplei2c_reg_cfg2_dout; + wire [31:0] s_simplei2c_reg_dat_dout; + // spi mst + wire s_simplespi_reg_cfg_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00b8); + wire s_simplespi_reg_dat_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00bc); + wire [31:0] s_simplespi_reg_cfg_dout; + wire [31:0] s_simplespi_reg_dat_dout; + wire s_simplespi_reg_dat_wait; + // tim + wire s_tim0_reg_cfg_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00f4); + wire s_tim0_reg_val_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00f8); + wire s_tim0_reg_dat_sel = s_iomem_valid && (s_iomem_addr == 32'h0300_00fc); + wire [31:0] s_tim0_reg_cfg_dout; + wire [31:0] s_tim0_reg_val_dout; + wire [31:0] s_tim0_reg_dat_dout; - assign s_mem_ready = (iomem_valid_o && iomem_ready_i) || s_spimem_ready || s_ram_ready || s_spimemio_cfgreg_sel || - s_simpleuart_reg_div_sel || (s_simpleuart_reg_dat_sel && !s_simpleuart_reg_dat_wait); + assign s_mem_ready = (s_iomem_valid && r_iomem_ready) || + s_spimem_ready || r_ram_ready || s_spimemio_cfgreg_sel; - assign s_mem_rdata = (iomem_valid_o && iomem_ready_i) ? iomem_rdata_i : s_spimem_ready ? s_spimem_rdata : s_ram_ready ? s_ram_rdata : - s_spimemio_cfgreg_sel ? s_spimemio_cfgreg_do : s_simpleuart_reg_div_sel ? s_simpleuart_reg_div_do : - s_simpleuart_reg_dat_sel ? s_simpleuart_reg_dat_do : 32'h 0000_0000; + assign s_mem_rdata = (s_iomem_valid && r_iomem_ready) ? r_iomem_rdata : + s_spimem_ready ? s_spimem_rdata : + r_ram_ready ? ram_rdata_o : + s_spimemio_cfgreg_sel ? s_spimemio_cfgreg_dout : + 32'h0000_0000; + + // retroSoC memory mapped IP + // 1 crystal oscillator + // 1 I2C master + // 1 SPI master + // 1 32-bit counter/timer + // 1 QSPI flash controller + // 1 UART + + // NOTE: Signals affecting critical core functions are controlled through + // an independent SPI having read-only access through the picorv32 core. + // SPI pins are independent of picorv32 SPI master. Signals controlled + // by the SPI are: + // 1) crystal oscillator enable (default on) + // 2) PLL enables (default on) + // 3) PLL trim (default TBD) + // NOTE: SPI should have a pass-through mode that configures SDO as a + // copy of a chosen signal for as long as CSB is held low. This can be + // an SPI command, allows other internal signals to be passed to the + // output and viewed, including the RC oscillator output, comparator + // output, and other edge-based signals. + + // Memory map: + // GPIO: 32 channels total + // addr 0x03000000-1 data (16 bits) + // addr 0x03000004-5 out (=0) or in (=1) (default 1) + // addr 0x03000008-9 pu (=0) or none (=1) (default 1) + // addr 0x0300000c-d pd (=0) or none (=1) (default 1) + // + // UART: + // addr 0x03000078 clock divider + // addr 0x0300007c data + // + // SPI SLV: + // addr 0x03000080 SPI configuration + // addr 0x03000084 xtal osc, reg, bg enables + // addr 0x03000088 PLL enables, trim + // addr 0x0300008c-d manufacturer ID + // addr 0x03000090 product ID + // addr 0x03000094 product mask revision + // addr 0x03000098 external clock select + // addr 0x030000a0 xtal osc output dest (ext r_gpio pin 5-7) + // addr 0x030000a4 PLL output dest (ext r_gpio pin 8-10) + // addr 0x030000a8 trap_o output dest (ext r_gpio pin 11-13) + // addr 0x030000b0 IRQ 7 source (ext r_gpio pin 0-3) + // addr 0x030000b4 IRQ 8 source (ext r_gpio pin 4-7) + // + // SPI MST: + // addr 0x030000b8 configuration + // addr 0x030000bc data + // + // I2C: + // addr 0x030000d4 configuration (1) + // addr 0x030000d8 configuration (2) + // addr 0x030000dc data + // + // TIM: + // addr 0x030000f4 configuration + // addr 0x030000f8-b count resetn value + // addr 0x030000fc-f count current value picorv32 #( - .BARREL_SHIFTER (BARREL_SHIFTER), - .COMPRESSED_ISA (COMPRESSED_ISA), - .ENABLE_MUL (ENABLE_MUL), - .ENABLE_FAST_MUL (ENABLE_FAST_MUL), - .ENABLE_DIV (ENABLE_DIV), - .ENABLE_IRQ (1), - .ENABLE_IRQ_QREGS(ENABLE_IRQ_QREGS), - .STACKADDR (STACKADDR), .PROGADDR_RESET (PROGADDR_RESET), - .PROGADDR_IRQ (PROGADDR_IRQ) + .PROGADDR_IRQ (32'h0000_0000), + .STACKADDR (STACKADDR), + .BARREL_SHIFTER (1), + .COMPRESSED_ISA (1), + .ENABLE_MUL (1), + .ENABLE_FAST_MUL (1), + .ENABLE_DIV (1), + .ENABLE_IRQ (1), + .ENABLE_IRQ_QREGS(0) ) u_picorv32 ( .clk (clk_i), .resetn (rst_n_i), @@ -125,33 +364,41 @@ module retrosoc #( .mem_wdata(s_mem_wdata), .mem_wstrb(s_mem_wstrb), .mem_rdata(s_mem_rdata), - .irq (32'd0) + .irq (s_irq), + .trap (trap_o) ); spimemio u_spimemio ( - .clk (clk_i), - .resetn (rst_n_i), - .valid (s_mem_valid && s_mem_addr >= 4 * MEM_WORDS && s_mem_addr < 32'h0200_0000), - .ready (s_spimem_ready), - .addr (s_mem_addr[23:0]), - .rdata (s_spimem_rdata), - .flash_csb (flash_csb_o), - .flash_clk (flash_clk_o), - .flash_io0_oe(flash_io0_oe_o), - .flash_io1_oe(flash_io1_oe_o), - .flash_io2_oe(flash_io2_oe_o), - .flash_io3_oe(flash_io3_oe_o), - .flash_io0_do(flash_io0_do_o), - .flash_io1_do(flash_io1_do_o), - .flash_io2_do(flash_io2_do_o), - .flash_io3_do(flash_io3_do_o), - .flash_io0_di(flash_io0_di_i), - .flash_io1_di(flash_io1_di_i), - .flash_io2_di(flash_io2_di_i), - .flash_io3_di(flash_io3_di_i), - .cfgreg_we (s_spimemio_cfgreg_sel ? s_mem_wstrb : 4'b0000), - .cfgreg_di (s_mem_wdata), - .cfgreg_do (s_spimemio_cfgreg_do) + .clk (clk_i), + .resetn (rst_n_i), + .valid (s_mem_valid && s_mem_addr >= 4 * MEM_WORDS && s_mem_addr < 32'h0200_0000), + .ready (s_spimem_ready), + .addr (s_mem_addr[23:0]), + .rdata (s_spimem_rdata), + .pass_thru (hk_pt_i), + .pass_thru_csb(hk_pt_csb_i), + .pass_thru_sck(hk_pt_sck_i), + .pass_thru_sdi(hk_pt_sdi_i), + .pass_thru_sdo(hk_pt_sdo_o), + .flash_csb (flash_csb_o), + .flash_clk (flash_clk_o), + .flash_csb_oeb(flash_csb_oeb_o), + .flash_clk_oeb(flash_clk_oeb_o), + .flash_io0_oeb(flash_io0_oeb_o), + .flash_io1_oeb(flash_io1_oeb_o), + .flash_io2_oeb(flash_io2_oeb_o), + .flash_io3_oeb(flash_io3_oeb_o), + .flash_io0_do (flash_io0_do_o), + .flash_io1_do (flash_io1_do_o), + .flash_io2_do (flash_io2_do_o), + .flash_io3_do (flash_io3_do_o), + .flash_io0_di (flash_io0_di_i), + .flash_io1_di (flash_io1_di_i), + .flash_io2_di (flash_io2_di_i), + .flash_io3_di (flash_io3_di_i), + .cfgreg_we (s_spimemio_cfgreg_sel ? s_mem_wstrb : 4'b0000), + .cfgreg_di (s_mem_wdata), + .cfgreg_do (s_spimemio_cfgreg_dout) ); simpleuart u_simpleuart ( @@ -159,69 +406,186 @@ module retrosoc #( .resetn (rst_n_i), .ser_tx (uart_tx_o), .ser_rx (uart_rx_i), - .reg_div_we (s_simpleuart_reg_div_sel ? s_mem_wstrb : 4'b0000), - .reg_div_di (s_mem_wdata), - .reg_div_do (s_simpleuart_reg_div_do), - .reg_dat_we (s_simpleuart_reg_dat_sel ? s_mem_wstrb[0] : 1'b0), - .reg_dat_re (s_simpleuart_reg_dat_sel && !s_mem_wstrb), - .reg_dat_di (s_mem_wdata), - .reg_dat_do (s_simpleuart_reg_dat_do), - .reg_dat_wait(s_simpleuart_reg_dat_wait) + .reg_div_we (s_simpleuart_reg_div_sel ? s_iomem_wstrb : 4'b0000), + .reg_div_di (s_iomem_wdata), + .reg_div_do (s_simpleuart_reg_div_dout), + .reg_dat_we (s_simpleuart_reg_dat_sel ? s_iomem_wstrb[0] : 1'b0), + .reg_dat_re (s_simpleuart_reg_dat_sel && !s_iomem_wstrb), + .reg_dat_di (s_iomem_wdata), + .reg_dat_do (s_simpleuart_reg_dat_dout), + .reg_dat_wait(s_simpleuart_reg_dat_wait), + .irq_out (s_irq_uart) ); - always @(posedge clk_i) s_ram_ready <= s_mem_valid && !s_mem_ready && s_mem_addr < 4 * MEM_WORDS; - - `PICOSOC_MEM u_picosoc_mem ( - .clk (clk_i), - .wen ((s_mem_valid && !s_mem_ready && s_mem_addr < 4 * MEM_WORDS) ? s_mem_wstrb : 4'b0), - .addr (s_mem_addr[23:2]), - .wdata(s_mem_wdata), - .rdata(s_ram_rdata) + simple_i2c_master u_simplei2c_master ( + .clk (clk_i), + .resetn (rst_n_i), + .reg_cfg1_we (s_simplei2c_reg_cfg1_sel ? s_iomem_wstrb[2:0] : 3'b000), + .reg_cfg1_di (s_iomem_wdata), + .reg_cfg1_do (s_simplei2c_reg_cfg1_dout), + .reg_cfg2_we (s_simplei2c_reg_cfg2_sel ? s_iomem_wstrb[0] : 1'b0), + .reg_cfg2_di (s_iomem_wdata), + .reg_cfg2_do (s_simplei2c_reg_cfg2_dout), + .reg_dat_we (s_simplei2c_reg_dat_sel ? s_iomem_wstrb[0] : 1'b0), + .reg_dat_re (s_simplei2c_reg_dat_sel && !s_iomem_wstrb), + .reg_dat_di (s_iomem_wdata), + .reg_dat_do (s_simplei2c_reg_dat_dout), + .scl_pad_i (i2c_scl_i), + .scl_pad_o (i2c_scl_o), + .scl_padoeb_o(i2c_scl_oeb_o), + .sda_pad_i (i2c_sda_i), + .sda_pad_o (i2c_sda_o), + .sda_padoeb_o(i2c_sda_oeb_o), + .irq_o (s_irq_i2c) ); -endmodule -// Implementation note: -// Replace the following two modules with wrappers for your SRAM cells. - -module picosoc_regs ( - input clk, - input wen, - input [ 5:0] waddr, - input [ 5:0] raddr1, - input [ 5:0] raddr2, - input [31:0] wdata, - output [31:0] rdata1, - output [31:0] rdata2 -); - reg [31:0] regs[0:31]; - - always @(posedge clk) if (wen) regs[waddr[4:0]] <= wdata; - - assign rdata1 = regs[raddr1[4:0]]; - assign rdata2 = regs[raddr2[4:0]]; -endmodule - -module picosoc_mem ( - input clk, - input [ 3:0] wen, - input [21:0] addr, - input [31:0] wdata, - output reg [31:0] rdata -); - // reg [31:0] mem[0:256-1]; - // always @(posedge clk) begin - // rdata <= mem[addr]; - // if (wen[0]) mem[addr][7:0] <= wdata[7:0]; - // if (wen[1]) mem[addr][15:8] <= wdata[15:8]; - // if (wen[2]) mem[addr][23:16] <= wdata[23:16]; - // if (wen[3]) mem[addr][31:24] <= wdata[31:24]; - // end - spram_model u_spram_model ( - .clk (clk), - .wen (wen), - .addr (addr), - .wdata(wdata), - .rdata(rdata) + simple_spi_master u_simple_spi_master ( + .resetn (rst_n_i), + .clk (clk_i), + .reg_cfg_we (s_simplespi_reg_cfg_sel ? s_iomem_wstrb[1:0] : 2'b00), + .reg_cfg_di (s_iomem_wdata), + .reg_cfg_do (s_simplespi_reg_cfg_dout), + .reg_dat_we (s_simplespi_reg_dat_sel ? s_iomem_wstrb[0] : 1'b0), + .reg_dat_re (s_simplespi_reg_dat_sel && !s_iomem_wstrb), + .reg_dat_di (s_iomem_wdata), + .reg_dat_do (s_simplespi_reg_dat_dout), + .reg_dat_wait(s_simplespi_reg_dat_wait), + .irq_out (s_irq_spi_mst), + .sdi (spi_mst_sdi_i), + .csb (spi_mst_csb_o), + .sck (spi_mst_sck_o), + .sdo (spi_mst_sdo_o), + .sdoenb (spi_mst_oenb_o) ); + + counter_timer u_counter_timer ( + .resetn (rst_n_i), + .clkin (clk_i), + .reg_val_we(s_tim0_reg_val_sel ? s_iomem_wstrb[3:0] : 4'h0), + .reg_val_di(s_iomem_wdata), + .reg_val_do(s_tim0_reg_val_dout), + .reg_cfg_we(s_tim0_reg_cfg_sel ? s_iomem_wstrb[0] : 1'b0), + .reg_cfg_di(s_iomem_wdata), + .reg_cfg_do(s_tim0_reg_cfg_dout), + .reg_dat_we(s_tim0_reg_dat_sel ? s_iomem_wstrb[3:0] : 4'h0), + .reg_dat_di(s_iomem_wdata), + .reg_dat_do(s_tim0_reg_dat_dout), + .irq_out (s_irq_tim0) + ); + + always @(posedge clk_i) begin + r_ram_ready <= s_mem_valid && !s_mem_ready && s_mem_addr < 4 * MEM_WORDS; + end + + always @(posedge clk_i) begin + if (!rst_n_i) begin + r_gpio <= 0; + r_gpio_oeb <= 16'hffff; + r_gpio_pu <= 0; + r_gpio_pd <= 0; + r_pll_out_dest <= 0; + r_xtal_out_dest <= 0; + r_trap_out_dest <= 0; + r_irq_7_in_src <= 0; + r_irq_8_in_src <= 0; + end else begin + if (s_iomem_valid && !r_iomem_ready && s_iomem_addr[31:8] == 24'h030000) begin + // Handle r_iomem_ready based on wait states + case (s_iomem_addr[7:0]) + 8'h7c: r_iomem_ready = ~s_simpleuart_reg_dat_wait; + 8'hbc: r_iomem_ready = ~s_simplespi_reg_dat_wait; + default: r_iomem_ready = 1'b1; + endcase + case (s_iomem_addr[7:0]) + 8'h00: begin + r_iomem_rdata <= {gpio_out_o, gpio_in_i}; + if (s_iomem_wstrb[0]) r_gpio[7:0] <= s_iomem_wdata[7:0]; + if (s_iomem_wstrb[1]) r_gpio[15:8] <= s_iomem_wdata[15:8]; + end + 8'h04: begin + r_iomem_rdata <= {16'd0, r_gpio_oeb}; + if (s_iomem_wstrb[0]) r_gpio_oeb[7:0] <= s_iomem_wdata[7:0]; + if (s_iomem_wstrb[1]) r_gpio_oeb[15:8] <= s_iomem_wdata[15:8]; + end + 8'h08: begin + r_iomem_rdata <= {16'd0, r_gpio_pu}; + if (s_iomem_wstrb[0]) r_gpio_pu[7:0] <= s_iomem_wdata[7:0]; + if (s_iomem_wstrb[1]) r_gpio_pu[15:8] <= s_iomem_wdata[15:8]; + end + 8'h0c: begin + r_iomem_rdata <= {16'd0, r_gpio_pu}; + if (s_iomem_wstrb[0]) r_gpio_pd[7:0] <= s_iomem_wdata[7:0]; + if (s_iomem_wstrb[1]) r_gpio_pd[15:8] <= s_iomem_wdata[15:8]; + end + 8'h78: r_iomem_rdata <= s_simpleuart_reg_div_dout; + 8'h7c: r_iomem_rdata <= s_simpleuart_reg_dat_dout; + 8'h80: r_iomem_rdata <= {24'd0, spi_slv_ro_config_i}; + 8'h84: r_iomem_rdata <= {30'd0, spi_slv_ro_xtal_ena_i, spi_slv_ro_reg_ena_i}; + 8'h88: begin + r_iomem_rdata <= { + 25'd0, + spi_slv_ro_pll_trim_i, + spi_slv_ro_pll_cp_ena_i, + spi_slv_ro_pll_vco_ena_i, + spi_slv_ro_pll_bias_ena_i + }; + end + 8'h8c: r_iomem_rdata <= {20'd0, spi_slv_ro_mfgr_id_i}; + 8'h90: r_iomem_rdata <= {24'd0, spi_slv_ro_prod_id_i}; + 8'h94: r_iomem_rdata <= {28'd0, spi_slv_ro_mask_rev_i}; + 8'h98: r_iomem_rdata <= {31'd0, clk_ext_sel_i}; + 8'ha0: begin + r_iomem_rdata <= {30'd0, r_xtal_out_dest}; + if (s_iomem_wstrb[0]) r_xtal_out_dest <= s_iomem_wdata[1:0]; + end + 8'ha4: begin + r_iomem_rdata <= {30'd0, r_pll_out_dest}; + if (s_iomem_wstrb[0]) r_pll_out_dest <= s_iomem_wdata[1:0]; + end + 8'ha8: begin + r_iomem_rdata <= {30'd0, r_trap_out_dest}; + if (s_iomem_wstrb[0]) r_trap_out_dest <= s_iomem_wdata[1:0]; + end + 8'hb0: begin + r_iomem_rdata <= {30'd0, r_irq_7_in_src}; + if (s_iomem_wstrb[0]) r_irq_7_in_src <= s_iomem_wdata[1:0]; + end + 8'hb4: begin + r_iomem_rdata <= {30'd0, r_irq_8_in_src}; + if (s_iomem_wstrb[0]) r_irq_8_in_src <= s_iomem_wdata[1:0]; + end + 8'hb8: r_iomem_rdata <= s_simplespi_reg_cfg_dout; + 8'hbc: r_iomem_rdata <= s_simplespi_reg_dat_dout; + 8'hd4: r_iomem_rdata <= s_simplei2c_reg_cfg1_dout; + 8'hd8: r_iomem_rdata <= s_simplei2c_reg_cfg2_dout; + 8'hdc: r_iomem_rdata <= s_simplei2c_reg_dat_dout; + 8'hf4: r_iomem_rdata <= {28'd0, s_tim0_reg_cfg_dout}; + 8'hf8: r_iomem_rdata <= s_tim0_reg_val_dout; + 8'hfc: r_iomem_rdata <= s_tim0_reg_dat_dout; + endcase + end else begin + r_iomem_ready = 1'b0; + end + end + end endmodule +// implementation note: +// replace the following two modules with wrappers for your SRAM cells. +// module retrosoc_regs ( +// input clk, +// input wen, +// input [ 5:0] waddr, +// input [ 5:0] raddr1, +// input [ 5:0] raddr2, +// input [31:0] wdata, +// output [31:0] rdata1, +// output [31:0] rdata2 +// ); +// reg [31:0] regs[0:31]; + +// always @(posedge clk) if (wen) regs[waddr[4:0]] <= wdata; + +// assign rdata1 = regs[raddr1[4:0]]; +// assign rdata2 = regs[raddr2[4:0]]; +// endmodule \ No newline at end of file diff --git a/rtl/retrosoc_asic.v b/rtl/retrosoc_asic.v index 9a6048e2..1d5a2e6c 100644 --- a/rtl/retrosoc_asic.v +++ b/rtl/retrosoc_asic.v @@ -1,7 +1,9 @@ /* - * PicoSoC - A simple example SoC using PicoRV32 + * retrosoc_asic - A full example SoC using PicoRV32 in ASIC * - * Copyright (C) 2017 Claire Xenia Wolf + * Copyright (C) 2017 Clifford Wolf + * Copyright (C) 2018,2019 Tim Edwards + * Copyright (C) 2025 Yuchi Miao * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,117 +19,300 @@ * */ -`ifdef PICOSOC_V -// `error "retrosoc_asic.v must be read before retrosoc.v!" -`endif +`timescale 1 ns / 1 ps -`define PICOSOC_MEM spram_model - -module retrosoc_asic #( - // We limit the amount of memory in simulation - // in order to avoid reduce simulation time - // required for intialization of RAM - parameter integer MEM_WORDS = 256 -) ( - input clk_i, - input rst_n_i, - output uart_tx_o_pad, - input uart_rx_i_pad, +module retrosoc_asic ( + input xi_i_pad, + output xo_o_pad, + input xclk_i_pad, + input rst_n_i_pad, + // HOUSEKEEPING SPI + input hk_sdi_i_pad, + output hk_sdo_o_pad, + input hk_csb_i_pad, + input hk_sck_i_pad, + // SPI MST + input spi_mst_sdi_i_pad, + output spi_mst_csb_o_pad, + output spi_mst_sck_o_pad, + output spi_mst_sdo_o_pad, + // SPI FLASH output flash_csb_o_pad, output flash_clk_o_pad, inout flash_io0_io_pad, inout flash_io1_io_pad, inout flash_io2_io_pad, inout flash_io3_io_pad, - output led1_o_pad, - output led2_o_pad, - output led3_o_pad, - output led4_o_pad, - output led5_o_pad, - output led6_o_pad, - output led7_o_pad + // UART + output uart_tx_o_pad, + input uart_rx_i_pad, + // I2C + inout i2c_sda_io_pad, + inout i2c_scl_io_pad, + // GPIO + output gpio_0_o_pad, + output gpio_1_o_pad, + output gpio_2_o_pad, + output gpio_3_o_pad, + output gpio_4_o_pad, + output gpio_5_o_pad, + output gpio_6_o_pad, + output gpio_7_o_pad, + output gpio_8_o_pad, + output gpio_9_o_pad, + output gpio_10_o_pad, + output gpio_11_o_pad, + output gpio_12_o_pad, + output gpio_13_o_pad, + output gpio_14_o_pad, + output gpio_15_o_pad, + // IRQ + input irq_pin_i_pad ); - - wire s_flash_csb_o, s_flash_clk_o; - wire s_uart_rx_i, s_uart_tx_o; - wire s_flash_io0_oe, s_flash_io0_do, s_flash_io0_di; - wire s_flash_io1_oe, s_flash_io1_do, s_flash_io1_di; - wire s_flash_io2_oe, s_flash_io2_do, s_flash_io2_di; - wire s_flash_io3_oe, s_flash_io3_do, s_flash_io3_di; - wire s_iomem_valid; - reg r_iomem_ready; - wire [ 3:0] s_iomem_wstrb; - wire [31:0] s_iomem_addr; - wire [31:0] s_iomem_wdata; - reg [31:0] r_iomem_rdata; - wire [ 7:0] s_leds; - reg [31:0] r_gpio; + // clk&rst + wire s_xtal_io; + wire s_xtal_io_buf; + wire s_xclk_i; + wire s_xclk_i_buf; + wire s_pll_clk; + wire s_pll_clk_buf; + wire s_clk; + wire s_clk_buf; // NOTE: UNUSED + wire s_rst_n_i; + wire s_rst_n; + // io + wire s_hk_sdi_i; + wire s_hk_sdo_o; + wire s_hk_csb_i; + wire s_hk_sck_i; + wire s_spi_mst_sdi_i; + wire s_spi_mst_csb_o; + wire s_spi_mst_sck_o; + wire s_spi_mst_sdo_o; + wire s_spi_mst_oenb_o; + wire s_flash_csb_o; + wire s_flash_clk_o; + wire s_flash_clk_oeb_o; + wire s_flash_csb_oeb_o; + wire s_flash_io0_oeb_o; + wire s_flash_io1_oeb_o; + wire s_flash_io2_oeb_o; + wire s_flash_io3_oeb_o; + wire s_flash_io0_do_o; + wire s_flash_io1_do_o; + wire s_flash_io2_do_o; + wire s_flash_io3_do_o; + wire s_flash_io0_di_i; + wire s_flash_io1_di_i; + wire s_flash_io2_di_i; + wire s_flash_io3_di_i; + wire s_uart_tx_o; + wire s_uart_rx_i; + wire s_i2c_scl_i; + wire s_i2c_scl_o; + wire s_i2c_scl_oeb_o; + wire s_i2c_sda_i; + wire s_i2c_sda_o; + wire s_i2c_sda_oeb_o; + wire [15:0] s_gpio_out_o; + wire [15:0] s_gpio_in_i; + wire [15:0] s_gpio_outenb_o; + wire [15:0] s_gpio_pullupb_o; + wire [15:0] s_gpio_pulldownb_o; + wire s_irq_pin_i; + // ram + wire [ 3:0] s_ram_wenb; + wire [13:0] s_ram_addr; + wire [31:0] s_ram_wdata; + wire [31:0] s_ram_rdata; + // housekeeping + wire s_hk_sdo_enb; + wire s_hk_xtal_ena; + wire s_hk_pll_vco_ena; + wire s_hk_pll_vco_in; + wire s_hk_pll_cp_ena; + wire s_hk_pll_bias_ena; + wire [ 3:0] s_hk_pll_trim; + wire s_hk_pll_bypass; + wire s_hk_irq; + wire s_hk_rst; + wire s_hk_trap; + wire s_hk_pt_rst; + wire s_hk_pt_csb; + wire s_hk_pt_sck; + wire s_hk_pt_sdi; + wire s_hk_pt_sdo; + wire [11:0] s_hk_mfgr_id; + wire [ 7:0] s_hk_prod_id; + wire [ 3:0] s_hk_mask_rev; // verilog_format: off - tc_io_tri_pad u_uart_tx_o_pad (.pad(uart_tx_o_pad), .c2p(s_uart_tx_o), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_uart_rx_i_pad (.pad(uart_rx_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_uart_rx_i)); - tc_io_tri_pad u_flash_csb_o_pad (.pad(flash_csb_o_pad), .c2p(s_flash_csb_o), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_flash_clk_o_pad (.pad(flash_clk_o_pad), .c2p(s_flash_clk_o), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_flash_io0_io_pad(.pad(flash_io0_io_pad), .c2p(s_flash_io0_do), .c2p_en(s_flash_io0_oe), .p2c(s_flash_io0_di)); - tc_io_tri_pad u_flash_io1_io_pad(.pad(flash_io1_io_pad), .c2p(s_flash_io1_do), .c2p_en(s_flash_io1_oe), .p2c(s_flash_io1_di)); - tc_io_tri_pad u_flash_io2_io_pad(.pad(flash_io2_io_pad), .c2p(s_flash_io2_do), .c2p_en(s_flash_io2_oe), .p2c(s_flash_io2_di)); - tc_io_tri_pad u_flash_io3_io_pad(.pad(flash_io3_io_pad), .c2p(s_flash_io3_do), .c2p_en(s_flash_io3_oe), .p2c(s_flash_io3_di)); - tc_io_tri_pad u_led1_o_pad (.pad(led1_o_pad), .c2p(s_leds[1]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led2_o_pad (.pad(led2_o_pad), .c2p(s_leds[2]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led3_o_pad (.pad(led3_o_pad), .c2p(s_leds[3]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led4_o_pad (.pad(led4_o_pad), .c2p(s_leds[4]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led5_o_pad (.pad(led5_o_pad), .c2p(s_leds[5]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led6_o_pad (.pad(led6_o_pad), .c2p(s_leds[6]), .c2p_en(1'b1), .p2c()); - tc_io_tri_pad u_led7_o_pad (.pad(led7_o_pad), .c2p(s_leds[7]), .c2p_en(1'b1), .p2c()); + ihp_io_xtl_pad u_xtal_pad (.xi_pad(xi_i_pad), .xo_pad(xo_o_pad), .en(s_hk_xtal_ena), .clk(s_xtal_io)); + ihp_io_tri_pad u_xclk_i_pad (.pad(xclk_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_xclk_i)); + ihp_io_tri_pad u_rst_n_i_pad (.pad(rst_n_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_rst_n_i)); + ihp_io_tri_pad u_hk_sdi_i_pad (.pad(hk_sdi_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_hk_sdi_i)); + ihp_io_tri_pad u_hk_sdo_o_pad (.pad(hk_sdo_o_pad), .c2p(s_hk_sdo_o), .c2p_en(~s_hk_sdo_enb), .p2c()); + ihp_io_tri_pad u_hk_csb_i_pad (.pad(hk_csb_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_hk_csb_i)); + ihp_io_tri_pad u_hk_sck_i_pad (.pad(hk_sck_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_hk_sck_i)); + ihp_io_tri_pad u_spi_mst_sdi_i_pad(.pad(spi_mst_sdi_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_spi_mst_sdi_i)); + ihp_io_tri_pad u_spi_mst_csb_o_pad(.pad(spi_mst_csb_o_pad), .c2p(s_spi_mst_csb_o), .c2p_en(1'b1), .p2c()); + ihp_io_tri_pad u_spi_mst_sck_o_pad(.pad(spi_mst_sck_o_pad), .c2p(s_spi_mst_sck_o), .c2p_en(1'b1), .p2c()); + ihp_io_tri_pad u_spi_mst_sdo_o_pad(.pad(spi_mst_sdo_o_pad), .c2p(s_spi_mst_sdo_o), .c2p_en(~s_spi_mst_oenb_o), .p2c()); + ihp_io_tri_pad u_flash_csb_o_pad (.pad(flash_csb_o_pad), .c2p(s_flash_csb_o), .c2p_en(~s_flash_csb_oeb_o), .p2c()); + ihp_io_tri_pad u_flash_clk_o_pad (.pad(flash_clk_o_pad), .c2p(s_flash_clk_o), .c2p_en(~s_flash_clk_oeb_o), .p2c()); + ihp_io_tri_pad u_flash_io0_io_pad (.pad(flash_io0_io_pad), .c2p(s_flash_io0_do_o), .c2p_en(~s_flash_io0_oeb_o), .p2c(s_flash_io0_di_i)); + ihp_io_tri_pad u_flash_io1_io_pad (.pad(flash_io1_io_pad), .c2p(s_flash_io1_do_o), .c2p_en(~s_flash_io1_oeb_o), .p2c(s_flash_io1_di_i)); + ihp_io_tri_pad u_flash_io2_io_pad (.pad(flash_io2_io_pad), .c2p(s_flash_io2_do_o), .c2p_en(~s_flash_io2_oeb_o), .p2c(s_flash_io2_di_i)); + ihp_io_tri_pad u_flash_io3_io_pad (.pad(flash_io3_io_pad), .c2p(s_flash_io3_do_o), .c2p_en(~s_flash_io3_oeb_o), .p2c(s_flash_io3_di_i)); + ihp_io_tri_pad u_uart_tx_o_pad (.pad(uart_tx_o_pad), .c2p(s_uart_tx_o), .c2p_en(1'b1), .p2c()); + ihp_io_tri_pad u_uart_rx_i_pad (.pad(uart_rx_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_uart_rx_i)); + ihp_io_tri_pad u_i2c_sda_io_pad (.pad(i2c_sda_io_pad), .c2p(s_i2c_sda_o), .c2p_en(~s_i2c_sda_oeb_o), .p2c(s_i2c_sda_i)); + ihp_io_tri_pad u_i2c_scl_io_pad (.pad(i2c_scl_io_pad), .c2p(s_i2c_scl_o), .c2p_en(~s_i2c_scl_oeb_o), .p2c(s_i2c_scl_i)); + ihp_io_tri_pad u_gpio_0_o_pad (.pad(gpio_0_o_pad), .c2p(s_gpio_out_o[0]), .c2p_en(~s_gpio_outenb_o[0]), .p2c(s_gpio_in_i[0])); + ihp_io_tri_pad u_gpio_1_o_pad (.pad(gpio_1_o_pad), .c2p(s_gpio_out_o[1]), .c2p_en(~s_gpio_outenb_o[1]), .p2c(s_gpio_in_i[1])); + ihp_io_tri_pad u_gpio_2_o_pad (.pad(gpio_2_o_pad), .c2p(s_gpio_out_o[2]), .c2p_en(~s_gpio_outenb_o[2]), .p2c(s_gpio_in_i[2])); + ihp_io_tri_pad u_gpio_3_o_pad (.pad(gpio_3_o_pad), .c2p(s_gpio_out_o[3]), .c2p_en(~s_gpio_outenb_o[3]), .p2c(s_gpio_in_i[3])); + ihp_io_tri_pad u_gpio_4_o_pad (.pad(gpio_4_o_pad), .c2p(s_gpio_out_o[4]), .c2p_en(~s_gpio_outenb_o[4]), .p2c(s_gpio_in_i[4])); + ihp_io_tri_pad u_gpio_5_o_pad (.pad(gpio_5_o_pad), .c2p(s_gpio_out_o[5]), .c2p_en(~s_gpio_outenb_o[5]), .p2c(s_gpio_in_i[5])); + ihp_io_tri_pad u_gpio_6_o_pad (.pad(gpio_6_o_pad), .c2p(s_gpio_out_o[6]), .c2p_en(~s_gpio_outenb_o[6]), .p2c(s_gpio_in_i[6])); + ihp_io_tri_pad u_gpio_7_o_pad (.pad(gpio_7_o_pad), .c2p(s_gpio_out_o[7]), .c2p_en(~s_gpio_outenb_o[7]), .p2c(s_gpio_in_i[7])); + ihp_io_tri_pad u_gpio_8_o_pad (.pad(gpio_8_o_pad), .c2p(s_gpio_out_o[8]), .c2p_en(~s_gpio_outenb_o[8]), .p2c(s_gpio_in_i[8])); + ihp_io_tri_pad u_gpio_9_o_pad (.pad(gpio_9_o_pad), .c2p(s_gpio_out_o[9]), .c2p_en(~s_gpio_outenb_o[9]), .p2c(s_gpio_in_i[9])); + ihp_io_tri_pad u_gpio_10_o_pad (.pad(gpio_10_o_pad), .c2p(s_gpio_out_o[10]), .c2p_en(~s_gpio_outenb_o[10]), .p2c(s_gpio_in_i[10])); + ihp_io_tri_pad u_gpio_11_o_pad (.pad(gpio_11_o_pad), .c2p(s_gpio_out_o[11]), .c2p_en(~s_gpio_outenb_o[11]), .p2c(s_gpio_in_i[11])); + ihp_io_tri_pad u_gpio_12_o_pad (.pad(gpio_12_o_pad), .c2p(s_gpio_out_o[12]), .c2p_en(~s_gpio_outenb_o[12]), .p2c(s_gpio_in_i[12])); + ihp_io_tri_pad u_gpio_13_o_pad (.pad(gpio_13_o_pad), .c2p(s_gpio_out_o[13]), .c2p_en(~s_gpio_outenb_o[13]), .p2c(s_gpio_in_i[13])); + ihp_io_tri_pad u_gpio_14_o_pad (.pad(gpio_14_o_pad), .c2p(s_gpio_out_o[14]), .c2p_en(~s_gpio_outenb_o[14]), .p2c(s_gpio_in_i[14])); + ihp_io_tri_pad u_gpio_15_o_pad (.pad(gpio_15_o_pad), .c2p(s_gpio_out_o[15]), .c2p_en(~s_gpio_outenb_o[15]), .p2c(s_gpio_in_i[15])); + ihp_io_tri_pad u_irq_pin_i_pad (.pad(irq_pin_i_pad), .c2p(), .c2p_en(1'b0), .p2c(s_irq_pin_i)); + // clk buf + ihp_clk_buffer u_xtal_buf (.clk_i(s_xtal_io), .clk_o(s_xtal_io_buf)); + ihp_clk_buffer u_xclk_buf (.clk_i(s_xclk_i), .clk_o(s_xclk_i_buf)); // verilog_format: on - assign s_leds = r_gpio; - always @(posedge clk_i) begin - if (!rst_n_i) begin - r_gpio <= 0; - end else begin - r_iomem_ready <= 0; - if (s_iomem_valid && !r_iomem_ready && s_iomem_addr[31:24] == 8'h03) begin - r_iomem_ready <= 1; - r_iomem_rdata <= r_gpio; - if (s_iomem_wstrb[0]) r_gpio[7:0] <= s_iomem_wdata[7:0]; - if (s_iomem_wstrb[1]) r_gpio[15:8] <= s_iomem_wdata[15:8]; - if (s_iomem_wstrb[2]) r_gpio[23:16] <= s_iomem_wdata[23:16]; - if (s_iomem_wstrb[3]) r_gpio[31:24] <= s_iomem_wdata[31:24]; - end - end - end - - retrosoc #( - .MEM_WORDS (MEM_WORDS), - .BARREL_SHIFTER (1), - .COMPRESSED_ISA (1), - .ENABLE_FAST_MUL(1), - .ENABLE_DIV (1) - ) u_retrosoc ( - .clk_i (clk_i), - .rst_n_i (rst_n_i), - .uart_tx_o (s_uart_tx_o), - .uart_rx_i (s_uart_rx_i), - .flash_csb_o (s_flash_csb_o), - .flash_clk_o (s_flash_clk_o), - .flash_io0_oe_o(s_flash_io0_oe), - .flash_io1_oe_o(s_flash_io1_oe), - .flash_io2_oe_o(s_flash_io2_oe), - .flash_io3_oe_o(s_flash_io3_oe), - .flash_io0_do_o(s_flash_io0_do), - .flash_io1_do_o(s_flash_io1_do), - .flash_io2_do_o(s_flash_io2_do), - .flash_io3_do_o(s_flash_io3_do), - .flash_io0_di_i(s_flash_io0_di), - .flash_io1_di_i(s_flash_io1_di), - .flash_io2_di_i(s_flash_io2_di), - .flash_io3_di_i(s_flash_io3_di), - .iomem_valid_o (s_iomem_valid), - .iomem_ready_i (r_iomem_ready), - .iomem_wstrb_o (s_iomem_wstrb), - .iomem_addr_o (s_iomem_addr), - .iomem_wdata_o (s_iomem_wdata), - .iomem_rdata_i (r_iomem_rdata) + // reset assignment. "s_rst_n_i" comes from button, while "s_hk_rst" + // comes from standalone SPI (and is normally zero unless activated from the SPI). + assign s_clk = s_hk_pll_bypass ? s_xclk_i_buf : s_pll_clk_buf; + assign s_rst_n = s_rst_n_i & ~s_hk_rst; + retrosoc u_retrosoc ( + .clk_i (s_clk), + .rst_n_i (s_rst_n), + .xtal_in_i (s_xtal_io_buf), + .clk_pll_i (s_pll_clk_buf), + .clk_ext_sel_i (s_hk_pll_bypass), + .hk_pt_i (s_hk_pt_rst), + .hk_pt_csb_i (s_hk_pt_csb), + .hk_pt_sck_i (s_hk_pt_sck), + .hk_pt_sdi_i (s_hk_pt_sdi), + .hk_pt_sdo_o (s_hk_pt_sdo), + .ram_wenb_o (s_ram_wenb), + .ram_addr_o (s_ram_addr), + .ram_wdata_o (s_ram_wdata), + .ram_rdata_o (s_ram_rdata), + .gpio_out_o (s_gpio_out_o), + .gpio_in_i (s_gpio_in_i), + .gpio_pullupb_o (s_gpio_pullupb_o), + .gpio_pulldownb_o (s_gpio_pulldownb_o), + .gpio_outenb_o (s_gpio_outenb_o), + .spi_slv_ro_config_i (8'd0), + .spi_slv_ro_xtal_ena_i (s_hk_xtal_ena), + .spi_slv_ro_reg_ena_i (1'b0), + .spi_slv_ro_pll_cp_ena_i (s_hk_pll_cp_ena), + .spi_slv_ro_pll_vco_ena_i (s_hk_pll_vco_ena), + .spi_slv_ro_pll_bias_ena_i(s_hk_pll_bias_ena), + .spi_slv_ro_pll_trim_i (s_hk_pll_trim), + .spi_slv_ro_mfgr_id_i (s_hk_mfgr_id), + .spi_slv_ro_prod_id_i (s_hk_prod_id), + .spi_slv_ro_mask_rev_i (s_hk_mask_rev), + .uart_tx_o (s_uart_tx_o), + .uart_rx_i (s_uart_rx_i), + .i2c_scl_i (s_i2c_scl_i), + .i2c_scl_o (s_i2c_scl_o), + .i2c_scl_oeb_o (s_i2c_scl_oeb_o), + .i2c_sda_i (s_i2c_sda_i), + .i2c_sda_o (s_i2c_sda_o), + .i2c_sda_oeb_o (s_i2c_sda_oeb_o), + .spi_mst_sdo_o (s_spi_mst_sdo_o), + .spi_mst_csb_o (s_spi_mst_csb_o), + .spi_mst_sck_o (s_spi_mst_sck_o), + .spi_mst_sdi_i (s_spi_mst_sdi_i), + .spi_mst_oenb_o (s_spi_mst_oenb_o), + .irq_pin_i (s_irq_pin_i), + .irq_spi_i (s_hk_irq), + .trap_o (s_hk_trap), + .flash_csb_o (s_flash_csb_o), + .flash_clk_o (s_flash_clk_o), + .flash_clk_oeb_o (s_flash_clk_oeb_o), + .flash_csb_oeb_o (s_flash_csb_oeb_o), + .flash_io0_oeb_o (s_flash_io0_oeb_o), + .flash_io1_oeb_o (s_flash_io1_oeb_o), + .flash_io2_oeb_o (s_flash_io2_oeb_o), + .flash_io3_oeb_o (s_flash_io3_oeb_o), + .flash_io0_do_o (s_flash_io0_do_o), + .flash_io1_do_o (s_flash_io1_do_o), + .flash_io2_do_o (s_flash_io2_do_o), + .flash_io3_do_o (s_flash_io3_do_o), + .flash_io0_di_i (s_flash_io0_di_i), + .flash_io1_di_i (s_flash_io1_di_i), + .flash_io2_di_i (s_flash_io2_di_i), + .flash_io3_di_i (s_flash_io3_di_i) ); + + /* it can control the xtal oscillator, PLL which CANNOT be changed from the CPU */ + /* without potentially killing it. */ + ravenna_spi u_ravenna_spi ( + .RST (~s_rst_n), + .SCK (s_hk_sck_i), + .SDI (s_hk_sdi_i), + .CSB (s_hk_csb_i), + .SDO (s_hk_sdo_o), + .sdo_enb (s_hk_sdo_enb), + .xtal_ena (s_hk_xtal_ena), + .reg_ena (), // regulator + .pll_vco_ena (s_hk_pll_vco_ena), + .pll_vco_in (s_hk_pll_vco_in), + .pll_cp_ena (s_hk_pll_cp_ena), + .pll_bias_ena (s_hk_pll_bias_ena), + .pll_trim (s_hk_pll_trim), + .pll_bypass (s_hk_pll_bypass), + .tm_nvcp (), + .irq (s_hk_irq), + .reset (s_hk_rst), + .trap (s_hk_trap), + .pass_thru_reset(s_hk_pt_rst), + .pass_thru_sck (s_hk_pt_sck), + .pass_thru_csb (s_hk_pt_csb), + .pass_thru_sdi (s_hk_pt_sdi), + .pass_thru_sdo (s_hk_pt_sdo), + .mask_rev_in (4'd0), + .mfgr_id (s_hk_mfgr_id), + .prod_id (s_hk_prod_id), + .mask_rev (s_hk_mask_rev) + ); + + spram_model u_spram_model ( + .clk (s_clk), + .wen (~s_ram_wenb), + .addr (s_ram_addr), + .wdata(s_ram_wdata), + .rdata(s_ram_rdata) + ); + + assign s_pll_clk = s_xclk_i_buf; + assign s_pll_clk_buf = s_pll_clk; + /* 8x clock multiplier PLL (NOTE: IP from A_CELLS_1V8) */ + // apllc03_1v8 pll ( + // .VSSD (VSS), + // .EN_VCO(spi_pll_vco_ena_lv), + // .EN_CP (spi_pll_cp_ena_lv), + // .B_VCO (bias5u), + // .B_CP (bias10u), + // .VSSA (VSS), + // .VDDD (VDD1V8), + // .VDDA (VDD1V8), + // .VCO_IN(pll_vco_in), + // .CLK (s_clk), // output (fast) clock + // .REF (xtal_out_lv), // input (slow) clock + // .B (spi_pll_trim_lv) // 4-bit trim + // ); endmodule diff --git a/rtl/retrosoc_tb.v b/rtl/retrosoc_tb.v index f0d062b6..686da67f 100644 --- a/rtl/retrosoc_tb.v +++ b/rtl/retrosoc_tb.v @@ -26,8 +26,6 @@ module retrosoc_tb; reg r_clk; reg [5:0] r_rst_cnt = 0; - wire [6:0] s_leds; - wire s_led1, s_led2, s_led3, s_led4, s_led5, s_led6, s_led7; wire s_uart_rx, s_uart_tx; wire s_flash_csb; wire s_flash_clk; @@ -44,29 +42,46 @@ module retrosoc_tb; r_rst_cnt <= r_rst_cnt + !s_rst_n; end - assign s_leds = {s_led7, s_led6, s_led5, s_led4, s_led3, s_led2, s_led1}; - always @(s_leds) begin - #1 $display("s_leds: %b", s_leds); - end - - retrosoc_asic u_retrosoc ( - .clk_i (r_clk), - .rst_n_i (s_rst_n), - .uart_tx_o_pad (s_uart_tx), - .uart_rx_i_pad (s_uart_rx), - .flash_csb_o_pad (s_flash_csb), - .flash_clk_o_pad (s_flash_clk), - .flash_io0_io_pad(s_flash_io0), - .flash_io1_io_pad(s_flash_io1), - .flash_io2_io_pad(s_flash_io2), - .flash_io3_io_pad(s_flash_io3), - .led1_o_pad (s_led1), - .led2_o_pad (s_led2), - .led3_o_pad (s_led3), - .led4_o_pad (s_led4), - .led5_o_pad (s_led5), - .led6_o_pad (s_led6), - .led7_o_pad (s_led7) + retrosoc_asic u_retrosoc_asic ( + .xi_i_pad (r_clk), + .xo_o_pad (), + .xclk_i_pad (r_clk), + .rst_n_i_pad (s_rst_n), + .hk_sdi_i_pad (1'b1), + .hk_sdo_o_pad (), + .hk_csb_i_pad (1'b1), + .hk_sck_i_pad (1'b0), + .spi_mst_sdi_i_pad(1'b0), + .spi_mst_csb_o_pad(), + .spi_mst_sck_o_pad(), + .spi_mst_sdo_o_pad(), + .flash_csb_o_pad (s_flash_csb), + .flash_clk_o_pad (s_flash_clk), + .flash_io0_io_pad (s_flash_io0), + .flash_io1_io_pad (s_flash_io1), + .flash_io2_io_pad (s_flash_io2), + .flash_io3_io_pad (s_flash_io3), + .uart_tx_o_pad (s_uart_tx), + .uart_rx_i_pad (s_uart_rx), + .i2c_sda_io_pad (), + .i2c_scl_io_pad (), + .gpio_0_o_pad (), + .gpio_1_o_pad (), + .gpio_2_o_pad (), + .gpio_3_o_pad (), + .gpio_4_o_pad (), + .gpio_5_o_pad (), + .gpio_6_o_pad (), + .gpio_7_o_pad (), + .gpio_8_o_pad (), + .gpio_9_o_pad (), + .gpio_10_o_pad (), + .gpio_11_o_pad (), + .gpio_12_o_pad (), + .gpio_13_o_pad (), + .gpio_14_o_pad (), + .gpio_15_o_pad (), + .irq_pin_i_pad (1'b0) ); spiflash u_spiflash ( @@ -110,17 +125,17 @@ module retrosoc_tb; initial begin if ($test$plusargs("behv_wave")) begin - $dumpfile("retrosoc_tb.vcd"); + $dumpfile("retrosoc_tb.fst"); $dumpvars(0, retrosoc_tb); end else if ($test$plusargs("syn_wave")) begin - $dumpfile("retrosoc_syn_tb.vcd"); + $dumpfile("retrosoc_syn_tb.fst"); $dumpvars(0, retrosoc_tb); end - repeat (100) begin + repeat (1500) begin repeat (5000) @(posedge r_clk); // $display("+5000 cycles"); end - // $finish; + $finish; end endmodule