initial commit
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v
deleted file mode 100644
index bbe24ce..0000000
--- a/verilog/rtl/caravel.v
+++ /dev/null
@@ -1,919 +0,0 @@
-/*------------------------------------------------------*/
-/* caravel, a standard container for user projects on */
-/* the Google/SkyWater/efabless shuttle runs for the */
-/* SkyWater sky130 130nm process. */
-/* */
-/* Copyright 2020 efabless, Inc. */
-/* Written by Tim Edwards, August 2020 */
-/* This file is open source hardware released under the */
-/* Apache 2.0 license. See file LICENSE. */
-/* */
-/*------------------------------------------------------*/
-
-`timescale 1 ns / 1 ps
-
-/* Always define USE_PG_PIN (used by SkyWater cells) */
-/* But do not define SC_USE_PG_PIN */
-`define USE_PG_PIN
-
-/* Must define functional for now because otherwise the timing delays */
-/* are assumed, but they have been stripped out because some are not */
-/* parsed by iverilog. */
-
-`define functional
-
-// Define GL to use the gate-level netlists
-//`define GL
-
-// PDK IP
-
-// I/O padframe cells
-
-// Local IP
-`include "striVe.v"
-
-//`define TOP_ROUTING
-
-`ifndef TOP_ROUTING
- `define ABUTMENT_PINS \
- .amuxbus_a(analog_a),\
- .amuxbus_b(analog_b),\
- .vssa(vss),\
- .vdda(vdd3v3),\
- .vswitch(vdd3v3),\
- .vddio_q(vddio_q),\
- .vcchib(vdd1v8),\
- .vddio(vdd3v3),\
- .vccd(vdd1v8),\
- .vssio(vss),\
- .vssd(vss),\
- .vssio_q(vssio_q),
-`else
- `define ABUTMENT_PINS
-`endif
-
-module caravel (vdd3v3, vdd1v8, vss, gpio, cclk, ser_rx, ser_tx, irq,
- RSTB, SDO, SDI, CSB, SCK,
- flash_csb, flash_clk, flash_io0, flash_io1, flash_io2, flash_io3);
- inout vdd3v3;
- inout vdd1v8;
- inout vss;
- inout [15:0] gpio;
- input cclk; // CMOS clock input
- input ser_rx;
- output ser_tx;
- input irq;
- input RSTB; // NOTE: Replaces analog_out pin from raven chip
- output SDO;
- input SDI;
- input CSB;
- input SCK;
- output flash_csb;
- output flash_clk;
- output flash_io0;
- output flash_io1;
- output flash_io2;
- output flash_io3;
-
- wire [15:0] gpio_out_core;
- wire [15:0] gpio_in_core;
- wire [15:0] gpio_mode0_core;
- wire [15:0] gpio_mode1_core;
- wire [15:0] gpio_outenb_core;
- wire [15:0] gpio_inenb_core;
-
- wire analog_a, analog_b; /* Placeholders for analog signals */
-
- wire porb_h;
- wire porb_l;
- wire por_h;
- wire por;
- wire SCK_core;
- wire SDI_core;
- wire CSB_core;
- wire SDO_core;
- wire SDO_enb;
- wire spi_ro_reg_ena_core;
- wire spi_ro_pll_dco_ena_core;
- wire [2:0] spi_ro_pll_sel_core;
- wire [4:0] spi_ro_pll_div_core;
- wire [25:0] spi_ro_pll_trim_core;
- wire irq_spi_core;
- wire ext_reset_core;
- wire trap_core;
- wire [11:0] spi_ro_mfgr_id_core;
- wire [7:0] spi_ro_prod_id_core;
- wire [3:0] spi_ro_mask_rev_core;
-
- // Instantiate power cells for VDD3V3 domain (8 total; 4 high clamps and
- // 4 low clamps)
- s8iom0_vdda_hvc_pad vdd3v3hclamp [1:0] (
- `ABUTMENT_PINS
- .drn_hvc(),
- .src_bdy_hvc()
- );
-
- s8iom0_vddio_hvc_pad vddiohclamp [1:0] (
- `ABUTMENT_PINS
- .drn_hvc(),
- .src_bdy_hvc()
- );
-
-
- s8iom0_vdda_lvc_pad vdd3v3lclamp [3:0] (
- `ABUTMENT_PINS
- .bdy2_b2b(),
- .drn_lvc1(),
- .drn_lvc2(),
- .src_bdy_lvc1(),
- .src_bdy_lvc2()
- );
-
- // Instantiate the core voltage supply (since it is not generated on-chip)
- // (1.8V) (4 total, 2 high and 2 low clamps)
-
- s8iom0_vccd_hvc_pad vdd1v8hclamp [1:0] (
- `ABUTMENT_PINS
- .drn_hvc(),
- .src_bdy_hvc()
- );
-
- s8iom0_vccd_lvc_pad vdd1v8lclamp [1:0] (
- `ABUTMENT_PINS
- .bdy2_b2b(),
- .drn_lvc1(),
- .drn_lvc2(),
- .src_bdy_lvc1(),
- .src_bdy_lvc2()
- );
-
- // Instantiate ground cells (7 total, 4 high clamps and 3 low clamps)
-
- s8iom0_vssa_hvc_pad vsshclamp [3:0] (
- `ABUTMENT_PINS
- .drn_hvc(),
- .src_bdy_hvc()
- );
-
- s8iom0_vssa_lvc_pad vssalclamp (
- `ABUTMENT_PINS
- .bdy2_b2b(),
- .drn_lvc1(),
- .drn_lvc2(),
- .src_bdy_lvc1(),
- .src_bdy_lvc2()
- );
-
- s8iom0_vssd_lvc_pad vssdlclamp (
- `ABUTMENT_PINS
- .bdy2_b2b(),
- .drn_lvc1(),
- .drn_lvc2(),
- .src_bdy_lvc1(),
- .src_bdy_lvc2()
- );
-
- s8iom0_vssio_lvc_pad vssiolclamp (
- `ABUTMENT_PINS
- .bdy2_b2b(),
- .drn_lvc1(),
- .drn_lvc2(),
- .src_bdy_lvc1(),
- .src_bdy_lvc2()
- );
-
-
-
- // Instantiate GPIO v2 cell. These are used for both digital and analog
- // functions, configured appropriately.
- //
- // GPIO pin description:
- //
- // general: signals with _h suffix are in the vddio (3.3V) domain. All
- // other signals are in 1.8V domains (vccd or vcchib)
-
- // out = Signal from core to pad (digital, 1.8V domain)
- // oe_n = Output buffer enable (sense inverted)
- // hld_h_n = Hold signals during deep sleep (sense inverted)
- // enable_h = Power-on-reset (inverted)
- // enable_inp_h = Defines state of input buffer output when disabled.
- // Connect via loopback to tie_hi_esd or tie_lo_esd.
- // enable_vdda_h = Power-on-reset (inverted) to analog section
- // enable_vswitch_h = set to 0 if not using vswitch
- // enable_vddio = set to 1 if vddio is up during deep sleep
- // inp_dis = Disable input buffer
- // ib_mode_sel = Input buffer mode select, 0 for 3.3V external signals, 1 for
- // 1.8V external signals
- // vtrip_se = Input buffer trip select, 0 for CMOS level, 1 for TTL level
- // slow = 0 for fast slew, 1 for slow slew
- // hld_ovr = override for pads that need to be enabled during deep sleep
- // analog_en = enable analog functions
- // analog_sel = select analog channel a or b
- // analog_pol = analog select polarity
- // dm = digital mode (3 bits) 000 = analog 001 = input only, 110 = output only
- // vddio = Main 3.3V supply
- // vddio_q = Quiet 3.3V supply
- // vdda = Analog 3.3V supply
- // vccd = Digital 1.8V supply
- // vswitch = High-voltage supply for analog switches
- // vcchib = Digital 1.8V supply live during deep sleep mode
- // vssa = Analog ground
- // vssd = Digital ground
- // vssio_q = Quiet main ground
- // vssio = Main ground
- // pad = Signal on pad
- // pad_a_noesd_h = Direct core connection to pad
- // pad_a_esd_0_h = Core connection to pad through 150 ohms (primary)
- // pad_a_esd_1_h = Core connection to pad through 150 ohms (secondary)
- // amuxbus_a = Analog bus A
- // amuxbus_b = Analog bus B
- // in = Signal from pad to core (digital, 1.8V domain)
- // in_h = Signal from pad to core (3.3V domain)
- // tie_hi_esd = 3.3V output for loopback to enable_inp_h
- // tie_lo_esd = ground output for loopback to enable_inp_h
-
- // 37 instances: 16 general purpose digital, 2 for the crystal oscillator,
- // 4 for the ADC, 1 for the analog out, 2 for the comparator inputs,
- // one for the IRQ input, one for the xclk input, 6 for the SPI flash
- // signals, and 4 for the housekeeping SPI signals.
-
- // NOTE: To pass a vector to array dm in an array of instances gpio_pad,
- // the array needs to be rearranged. Reconstruct the needed 48-bit vector
- // (3 bit signal * 16 instances).
- //
- // Also note: Preferable to use a generate block, but that is incompatible
- // with the current version of padframe_generator. . .
-
- wire [47:0] dm_all;
-
- assign dm_all = {gpio_mode1_core[15], gpio_mode1_core[15], gpio_mode0_core[15],
- gpio_mode1_core[14], gpio_mode1_core[14], gpio_mode0_core[14],
- gpio_mode1_core[13], gpio_mode1_core[13], gpio_mode0_core[13],
- gpio_mode1_core[12], gpio_mode1_core[12], gpio_mode0_core[12],
- gpio_mode1_core[11], gpio_mode1_core[11], gpio_mode0_core[11],
- gpio_mode1_core[10], gpio_mode1_core[10], gpio_mode0_core[10],
- gpio_mode1_core[9], gpio_mode1_core[9], gpio_mode0_core[9],
- gpio_mode1_core[8], gpio_mode1_core[8], gpio_mode0_core[8],
- gpio_mode1_core[7], gpio_mode1_core[7], gpio_mode0_core[7],
- gpio_mode1_core[6], gpio_mode1_core[6], gpio_mode0_core[6],
- gpio_mode1_core[5], gpio_mode1_core[5], gpio_mode0_core[5],
- gpio_mode1_core[4], gpio_mode1_core[4], gpio_mode0_core[4],
- gpio_mode1_core[3], gpio_mode1_core[3], gpio_mode0_core[3],
- gpio_mode1_core[2], gpio_mode1_core[2], gpio_mode0_core[2],
- gpio_mode1_core[1], gpio_mode1_core[1], gpio_mode0_core[1],
- gpio_mode1_core[0], gpio_mode1_core[0], gpio_mode0_core[0]};
-
- // GPIO pads (user space)
- s8iom0_gpiov2_pad gpio_pad [31:0] (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(gpio),
-`endif
- .out(gpio_out_core), // Signal from core to pad
- .oe_n(gpio_outenb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold signals during deep sleep (sense inverted)
- .enable_h(porb_h), // Post-reset enable
- .enable_inp_h(loopb0), // Input buffer state when disabled
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(gpio_inenb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm(dm_all), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(gpio_in_core), // Signal from pad to core
- .in_h(), // VDDA domain signal (unused)
- .tie_hi_esd(),
- .tie_lo_esd(loopb0)
- );
-
- s8iom0_gpiov2_pad cclk_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(cclk),
-`endif
- .out(), // Signal from core to pad
- .oe_n(vdd1v8), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb1), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(por), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(cclk_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb1)
- );
-
- // NOTE: The analog_out pad from the raven chip has been replaced by
- // the digital reset input RSTB on striVe due to the lack of an on-board
- // power-on-reset circuit. The XRES pad is used for providing a glitch-
- // free reset.
-
- s8iom0s8_top_xres4v2 RSTB_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(RSTB),
-`endif
- .tie_weak_hi_h(xresloop), // Loop-back connection to pad through pad_a_esd_h
- .tie_hi_esd(),
- .tie_lo_esd(),
- .pad_a_esd_h(xresloop),
- .xres_h_n(porb_h),
- .disable_pullup_h(vss), // 0 = enable pull-up on reset pad
- .enable_h(vdd), // Power-on-reset to the power-on-reset input??
- .en_vddio_sig_h(vss), // No idea.
- .inp_sel_h(vss), // 1 = use filt_in_h else filter the pad input
- .filt_in_h(vss), // Alternate input for glitch filter
- .pullup_h(vss), // Pullup connection for alternate filter input
- .enable_vddio(vdd1v8)
- );
-
- s8iom0_gpiov2_pad irq_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(irq),
-`endif
- .out(vss), // Signal from core to pad
- .oe_n(vdd1v8), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb10), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(por), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(irq_pin_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb10)
- );
-
- s8iom0_gpiov2_pad SDO_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(SDO),
-`endif
- .out(SDO_core), // Signal from core to pad
- .oe_n(SDO_enb), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb11), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(vdd1v8), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb11)
- );
-
- s8iom0_gpiov2_pad SDI_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(SDI),
-`endif
- .out(vss), // Signal from core to pad
- .oe_n(vdd1v8), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb12), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(por), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(SDI_core), // Signal from pad to core
- .in_h(SDI_core_h),
- .tie_hi_esd(),
- .tie_lo_esd()
- );
-
- s8iom0_gpiov2_pad CSB_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(CSB),
-`endif
- .out(vss), // Signal from core to pad
- .oe_n(vdd1v8), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb13), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(por), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(CSB_core), // Signal from pad to core
- .in_h(CSB_core_h),
- .tie_hi_esd(),
- .tie_lo_esd(loopb13)
- );
-
- s8iom0_gpiov2_pad SCK_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(SCK),
-`endif
- .out(vss), // Signal from core to pad
- .oe_n(vdd1v8), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb14), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(por), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(SCK_core), // Signal from pad to core
- .in_h(SCK_core_h), // Signal in vdda domain (3.3V)
- .tie_hi_esd(),
- .tie_lo_esd(loopb14)
- );
-
- s8iom0_gpiov2_pad flash_csb_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_csb),
-`endif
- .out(flash_csb_core), // Signal from core to pad
- .oe_n(flash_csb_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb16), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_csb_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd()
- );
-
- s8iom0_gpiov2_pad flash_clk_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_clk),
-`endif
- .out(flash_clk_core), // Signal from core to pad
- .oe_n(flash_clk_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb17), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_clk_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd()
- );
-
- s8iom0_gpiov2_pad flash_io0_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_io0),
-`endif
- .out(flash_io0_do_core), // Signal from core to pad
- .oe_n(flash_io0_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb18), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_io0_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(flash_io0_di_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb18)
- );
-
- s8iom0_gpiov2_pad flash_io1_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_io1),
-`endif
- .out(flash_io1_do_core), // Signal from core to pad
- .oe_n(flash_io1_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb19), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_io1_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(flash_io1_di_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb19)
- );
-
- s8iom0_gpiov2_pad flash_io2_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_io2),
-`endif
- .out(flash_io2_do_core), // Signal from core to pad
- .oe_n(flash_io2_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb20), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_io2_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({flash_io2_ieb_core, flash_io2_ieb_core, flash_io2_oeb_core}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(flash_io2_di_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb20)
- );
-
- s8iom0_gpiov2_pad flash_io3_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(flash_io3),
-`endif
- .out(flash_io3_do_core), // Signal from core to pad
- .oe_n(flash_io3_oeb_core), // Output enable (sense inverted)
- .hld_h_n(vdd), // Hold
- .enable_h(porb_h), // Enable
- .enable_inp_h(loopb21), // Enable input buffer
- .enable_vdda_h(porb_h), //
- .enable_vswitch_h(vss), //
- .enable_vddio(vdd1v8), //
- .inp_dis(flash_io3_ieb_core), // Disable input buffer
- .ib_mode_sel(vss), //
- .vtrip_sel(vss), //
- .slow(vss), //
- .hld_ovr(vss), //
- .analog_en(vss), //
- .analog_sel(vss), //
- .analog_pol(vss), //
- .dm({flash_io3_ieb_core, flash_io3_ieb_core, flash_io3_oeb_core}), // (3 bits) Mode control
- .pad_a_noesd_h(), // Direct pad connection
- .pad_a_esd_0_h(), // Pad connection through 150 ohms
- .pad_a_esd_1_h(), // Pad connection through 150 ohms
- .in(flash_io3_di_core), // Signal from pad to core
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd(loopb21)
- );
-
- // Instantiate GPIO overvoltage (I2C) compliant cell
- // (Use this for ser_rx and ser_tx; no reason other than testing
- // the use of the cell.) (Might be worth adding in the I2C IP from
- // ravenna just to test on a proper I2C channel.)
-
- s8iom0s8_top_gpio_ovtv2 ser_rx_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(ser_rx),
-`endif
- .out(vss),
- .oe_n(vdd1v8),
- .hld_h_n(vdd),
- .enable_h(porb_h),
- .enable_inp_h(loopb22),
- .enable_vdda_h(porb_h),
- .enable_vddio(vdd1v8),
- .enable_vswitch_h(vss),
- .inp_dis(por),
- .vtrip_sel(vss),
- .hys_trim(vdd1v8),
- .slow(vss),
- .slew_ctl({vss, vss}), // 2 bits
- .hld_ovr(vss),
- .analog_en(vss),
- .analog_sel(vss),
- .analog_pol(vss),
- .dm({vss, vss, vdd1v8}), // 3 bits
- .ib_mode_sel({vss, vss}), // 2 bits
- .vinref(vdd1v8),
- .pad_a_noesd_h(),
- .pad_a_esd_0_h(),
- .pad_a_esd_1_h(),
- .in(ser_rx_core),
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd()
- );
-
- s8iom0s8_top_gpio_ovtv2 ser_tx_pad (
- `ABUTMENT_PINS
-`ifndef TOP_ROUTING
- .pad(ser_tx),
-`endif
- .out(ser_tx_core),
- .oe_n(vss),
- .hld_h_n(vdd),
- .enable_h(porb_h),
- .enable_inp_h(loopb23),
- .enable_vdda_h(porb_h),
- .enable_vddio(vdd1v8),
- .enable_vswitch_h(vss),
- .inp_dis(vdd1v8),
- .vtrip_sel(vss),
- .hys_trim(vdd1v8),
- .slow(vss),
- .slew_ctl({vss, vss}), // 2 bits
- .hld_ovr(vss),
- .analog_en(vss),
- .analog_sel(vss),
- .analog_pol(vss),
- .dm({vdd1v8, vdd1v8, vss}), // 3 bits
- .ib_mode_sel({vss, vss}), // 2 bits
- .vinref(vdd1v8),
- .pad_a_noesd_h(),
- .pad_a_esd_0_h(),
- .pad_a_esd_1_h(),
- .in(),
- .in_h(),
- .tie_hi_esd(),
- .tie_lo_esd()
- );
-
- // Corner cells
- `ifndef TOP_ROUTING
- s8iom0_corner_pad corner [3:0] (
- .vssio(vss),
- .vddio(vdd),
- .vddio_q(vddio_q),
- .vssio_q(vssio_q),
- .amuxbus_a(analog_a),
- .amuxbus_b(analog_b),
- .vssd(vss),
- .vssa(vss),
- .vswitch(vdd),
- .vdda(vdd),
- .vccd(vdd1v8),
- .vcchib(vdd1v8)
- //`ABUTMENT_PINS
- );
-`endif
- // SoC core
-
- wire striVe_clk, striVe_rstn;
-
- striVe_clkrst clkrst(
-`ifdef LVS
- .vdd1v8(vdd1v8),
- .vss(vss),
-`endif
- .ext_clk_sel(ext_clk_sel_core),
- .ext_clk(ext_clk_core),
- .pll_clk(pll_clk_core),
- .reset(por),
- .ext_reset(ext_reset_core),
- .clk(striVe_clk),
- .resetn(striVe_rstn)
-);
-
- striVe_soc core (
-`ifdef LVS
- .vdd1v8(vdd1v8),
- .vss(vss),
-`endif
-
- .pll_clk(pll_clk_core),
- .clk(striVe_clk),
- .resetn(striVe_rstn),
- .gpio_out_pad(gpio_out_core),
- .gpio_in_pad(gpio_in_core),
- .gpio_mode0_pad(gpio_mode0_core),
- .gpio_mode1_pad(gpio_mode1_core),
- .gpio_outenb_pad(gpio_outenb_core),
- .gpio_inenb_pad(gpio_inenb_core),
- .spi_sck(SCK_core),
- .spi_ro_config(spi_ro_config_core),
- .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena_core),
- .spi_ro_pll_div(spi_ro_pll_div_core),
- .spi_ro_pll_sel(spi_ro_pll_sel_core),
- .spi_ro_pll_trim(spi_ro_pll_trim_core),
- .spi_ro_mfgr_id(spi_ro_mfgr_id_core),
- .spi_ro_prod_id(spi_ro_prod_id_core),
- .spi_ro_mask_rev(spi_ro_mask_rev_core),
- .ser_tx(ser_tx_core),
- .ser_rx(ser_rx_core),
- .irq_pin(irq_pin_core),
- .irq_spi(irq_spi_core),
- .trap(trap_core),
- .flash_csb(flash_csb_core),
- .flash_clk(flash_clk_core),
- .flash_csb_oeb(flash_csb_oeb_core),
- .flash_clk_oeb(flash_clk_oeb_core),
- .flash_io0_oeb(flash_io0_oeb_core),
- .flash_io1_oeb(flash_io1_oeb_core),
- .flash_io2_oeb(flash_io2_oeb_core),
- .flash_io3_oeb(flash_io3_oeb_core),
- .flash_csb_ieb(flash_csb_ieb_core),
- .flash_clk_ieb(flash_clk_ieb_core),
- .flash_io0_ieb(flash_io0_ieb_core),
- .flash_io1_ieb(flash_io1_ieb_core),
- .flash_io2_ieb(flash_io2_ieb_core),
- .flash_io3_ieb(flash_io3_ieb_core),
- .flash_io0_do(flash_io0_do_core),
- .flash_io1_do(flash_io1_do_core),
- .flash_io2_do(flash_io2_do_core),
- .flash_io3_do(flash_io3_do_core),
- .flash_io0_di(flash_io0_di_core),
- .flash_io1_di(flash_io1_di_core),
- .flash_io2_di(flash_io2_di_core),
- .flash_io3_di(flash_io3_di_core)
- );
-
- // For the mask revision input, use an array of digital constant logic cells
- wire [3:0] mask_rev_h;
- wire [3:0] no_connect;
-
- sky130_fd_sc_hvl__conb_1 mask_rev_value [3:0] (
-`ifdef LVS
- .vpwr(vdd3v3),
- .vpb(vdd3v3),
- .vnb(vss),
- .vgnd(vss),
-`endif
- .HI({no_connect[3:1], mask_rev[0]}),
- .LO({mask_rev[3:1], no_connect[0]})
- );
-
- // Housekeeping SPI at 3.3V.
-
- striVe_spi housekeeping (
-`ifdef LVS
- .vdd(vdd3v3),
- .vss(vss),
-`endif
- .RSTB(porb_h),
- .SCK(SCK_core_h),
- .SDI(SDI_core_h),
- .CSB(CSB_core_h),
- .SDO(SDO_core_h),
- .sdo_enb(SDO_enb_h),
- .reg_ena(spi_ro_reg_ena_core_h),
- .pll_dco_ena(spi_ro_pll_dco_ena_core_h),
- .pll_sel(spi_ro_pll_sel_core_h),
- .pll_div(spi_ro_pll_div_core_h),
- .pll_trim(spi_ro_pll_trim_core_h),
- .irq(irq_spi_core_h),
- .RST(por_h),
- .reset(ext_reset_core_h),
- .trap(trap_core_h),
- .mfgr_id(spi_ro_mfgr_id_core_h),
- .prod_id(spi_ro_prod_id_core_h),
- .mask_rev_in(mask_rev_h),
- .mask_rev(spi_ro_mask_rev_core_h)
- );
-
- // Level shifters from the HVL library
-
- // On-board digital PLL
-
- digital_pll pll (
-`ifdef LVS
- .vdd(vdd1v8),
- .vss(vss),
-`endif
- .reset(por),
- .osc(cclk_core),
- .clockc(pll_clk_core),
- .clockp({pll_clk_core0, pll_clk_core90}),
- .clockd({pll_clk2, pll_clk4, pll_clk8, pll_clk16}),
- .div(spi_ro_pll_div_core),
- .sel(spi_ro_pll_sel_core),
- .dco(spi_ro_pll_dco_ena_core),
- .ext_trim(spi_ro_pll_trim_core)
- );
-
-endmodule
diff --git a/verilog/rtl/digital_pll.v b/verilog/rtl/digital_pll.v
index fe564cb..d7dc839 100644
--- a/verilog/rtl/digital_pll.v
+++ b/verilog/rtl/digital_pll.v
@@ -4,7 +4,17 @@
`include "digital_pll_controller.v"
`include "ring_osc2x13.v"
-module digital_pll(reset, extclk_sel, osc, clockc, clockp, clockd, div, sel, dco, ext_trim);
+module digital_pll(
+`ifdef LVS
+ vdd,
+ vss,
+`endif
+ reset, extclk_sel, osc, clockc, clockp, clockd, div, sel, dco, ext_trim);
+
+`ifdef LVS
+ input vdd;
+ input vss;
+`endif
input reset; // Sense positive reset
input extclk_sel; // External clock select (acts as 2nd reset)
@@ -32,66 +42,66 @@
assign creset = (dco == 1'b0) ? ireset : 1'b1;
ring_osc2x13 ringosc (
- .reset(ireset),
- .trim(itrim),
- .clockp(clockp)
+ .reset(ireset),
+ .trim(itrim),
+ .clockp(clockp)
);
digital_pll_controller pll_control (
- .reset(creset),
- .clock(clockp[0]),
- .osc(osc),
- .div(div),
- .trim(otrim)
+ .reset(creset),
+ .clock(clockp[0]),
+ .osc(osc),
+ .div(div),
+ .trim(otrim)
);
// Select core clock output
assign clockc = (sel == 3'b000) ? clockp[0] :
- (sel == 3'b001) ? clockd[0] :
- (sel == 3'b010) ? clockd[1] :
- (sel == 3'b011) ? clockd[2] :
- clockd[3];
+ (sel == 3'b001) ? clockd[0] :
+ (sel == 3'b010) ? clockd[1] :
+ (sel == 3'b011) ? clockd[2] :
+ clockd[3];
// Derive negative-sense reset from the input positive-sense reset
- sky130_fd_sc_hd__inv_4 irb (
- .A(reset),
- .Y(resetb)
+ scs8hd_inv_4 irb (
+ .A(reset),
+ .Y(resetb)
);
// Create divided down clocks. The inverted output only comes
// with digital standard cells with inverted resets, so the
// reset has to be inverted as well.
- sky130_fd_sc_hd__dfrbp_1 idiv2 (
- .CLK(clockp[1]),
- .D(clockd[0]),
- .Q(nint[0]),
- .QN(clockd[0]),
- .RESETB(resetb)
+ scs8hd_dfrbp_1 idiv2 (
+ .CLK(clockp[1]),
+ .D(clockd[0]),
+ .Q(nint[0]),
+ .QN(clockd[0]),
+ .RESETB(resetb)
);
- sky130_fd_sc_hd__dfrbp_1 idiv4 (
- .CLK(clockd[0]),
- .D(clockd[1]),
- .Q(nint[1]),
- .QN(clockd[1]),
- .RESETB(resetb)
+ scs8hd_dfrbp_1 idiv4 (
+ .CLK(clockd[0]),
+ .D(clockd[1]),
+ .Q(nint[1]),
+ .QN(clockd[1]),
+ .RESETB(resetb)
);
- sky130_fd_sc_hd__dfrbp_1 idiv8 (
- .CLK(clockd[1]),
- .D(clockd[2]),
- .Q(nint[2]),
- .QN(clockd[2]),
- .RESETB(resetb)
+ scs8hd_dfrbp_1 idiv8 (
+ .CLK(clockd[1]),
+ .D(clockd[2]),
+ .Q(nint[2]),
+ .QN(clockd[2]),
+ .RESETB(resetb)
);
- sky130_fd_sc_hd__dfrbp_1 idiv16 (
- .CLK(clockd[2]),
- .D(clockd[3]),
- .Q(nint[3]),
- .QN(clockd[3]),
- .RESETB(resetb)
+ scs8hd_dfrbp_1 idiv16 (
+ .CLK(clockd[2]),
+ .D(clockd[3]),
+ .Q(nint[3]),
+ .QN(clockd[3]),
+ .RESETB(resetb)
);
endmodule
diff --git a/verilog/rtl/digital_pll_controller.v b/verilog/rtl/digital_pll_controller.v
index b88cc33..ddc553d 100644
--- a/verilog/rtl/digital_pll_controller.v
+++ b/verilog/rtl/digital_pll_controller.v
@@ -54,62 +54,62 @@
assign tint = tval[6:2];
// |<--second-->|<-- first-->|
assign trim = (tint == 5'd0) ? 26'b0000000000000_0000000000000 :
- (tint == 5'd1) ? 26'b0000000000000_0000000000001 :
- (tint == 5'd2) ? 26'b0000000000000_0000001000001 :
- (tint == 5'd3) ? 26'b0000000000000_0010001000001 :
- (tint == 5'd4) ? 26'b0000000000000_0010001001001 :
- (tint == 5'd5) ? 26'b0000000000000_0010101001001 :
- (tint == 5'd6) ? 26'b0000000000000_1010101001001 :
- (tint == 5'd7) ? 26'b0000000000000_1010101101001 :
- (tint == 5'd8) ? 26'b0000000000000_1010101101101 :
- (tint == 5'd9) ? 26'b0000000000000_1011101101101 :
- (tint == 5'd10) ? 26'b0000000000000_1011101111101 :
- (tint == 5'd11) ? 26'b0000000000000_1111101111101 :
- (tint == 5'd12) ? 26'b0000000000000_1111101111111 :
- (tint == 5'd13) ? 26'b0000000000000_1111111111111 :
- (tint == 5'd14) ? 26'b0000000000001_1111111111111 :
- (tint == 5'd15) ? 26'b0000001000001_1111111111111 :
- (tint == 5'd16) ? 26'b0010001000001_1111111111111 :
- (tint == 5'd17) ? 26'b0010001001001_1111111111111 :
- (tint == 5'd18) ? 26'b0010101001001_1111111111111 :
- (tint == 5'd19) ? 26'b1010101001001_1111111111111 :
- (tint == 5'd20) ? 26'b1010101101001_1111111111111 :
- (tint == 5'd21) ? 26'b1010101101101_1111111111111 :
- (tint == 5'd22) ? 26'b1011101101101_1111111111111 :
- (tint == 5'd23) ? 26'b1011101111101_1111111111111 :
- (tint == 5'd24) ? 26'b1111101111101_1111111111111 :
- (tint == 5'd25) ? 26'b1111101111111_1111111111111 :
- 26'b1111111111111_1111111111111;
+ (tint == 5'd1) ? 26'b0000000000000_0000000000001 :
+ (tint == 5'd2) ? 26'b0000000000000_0000001000001 :
+ (tint == 5'd3) ? 26'b0000000000000_0010001000001 :
+ (tint == 5'd4) ? 26'b0000000000000_0010001001001 :
+ (tint == 5'd5) ? 26'b0000000000000_0010101001001 :
+ (tint == 5'd6) ? 26'b0000000000000_1010101001001 :
+ (tint == 5'd7) ? 26'b0000000000000_1010101101001 :
+ (tint == 5'd8) ? 26'b0000000000000_1010101101101 :
+ (tint == 5'd9) ? 26'b0000000000000_1011101101101 :
+ (tint == 5'd10) ? 26'b0000000000000_1011101111101 :
+ (tint == 5'd11) ? 26'b0000000000000_1111101111101 :
+ (tint == 5'd12) ? 26'b0000000000000_1111101111111 :
+ (tint == 5'd13) ? 26'b0000000000000_1111111111111 :
+ (tint == 5'd14) ? 26'b0000000000001_1111111111111 :
+ (tint == 5'd15) ? 26'b0000001000001_1111111111111 :
+ (tint == 5'd16) ? 26'b0010001000001_1111111111111 :
+ (tint == 5'd17) ? 26'b0010001001001_1111111111111 :
+ (tint == 5'd18) ? 26'b0010101001001_1111111111111 :
+ (tint == 5'd19) ? 26'b1010101001001_1111111111111 :
+ (tint == 5'd20) ? 26'b1010101101001_1111111111111 :
+ (tint == 5'd21) ? 26'b1010101101101_1111111111111 :
+ (tint == 5'd22) ? 26'b1011101101101_1111111111111 :
+ (tint == 5'd23) ? 26'b1011101111101_1111111111111 :
+ (tint == 5'd24) ? 26'b1111101111101_1111111111111 :
+ (tint == 5'd25) ? 26'b1111101111111_1111111111111 :
+ 26'b1111111111111_1111111111111;
always @(posedge clock or posedge reset) begin
- if (reset == 1'b1) begin
- tval <= 7'd0; // Note: trim[0] must be zero for startup to work.
- oscbuf <= 3'd0;
- prep <= 3'd0;
- count0 <= 5'd0;
- count1 <= 5'd0;
+ if (reset == 1'b1) begin
+ tval <= 7'd0; // Note: trim[0] must be zero for startup to work.
+ oscbuf <= 3'd0;
+ prep <= 3'd0;
+ count0 <= 5'd0;
+ count1 <= 5'd0;
- end else begin
- oscbuf <= {oscbuf[1:0], osc};
+ end else begin
+ oscbuf <= {oscbuf[1:0], osc};
- if (oscbuf[2] != oscbuf[1]) begin
- count1 <= count0;
- count0 <= 5'b00001;
- prep <= {prep[1:0], 1'b1};
+ if (oscbuf[2] != oscbuf[1]) begin
+ count1 <= count0;
+ count0 <= 5'b00001;
+ prep <= {prep[1:0], 1'b1};
- if (prep == 3'b111) begin
- if (sum > div) begin
- tval <= tval + 1;
- end else if (sum < div) begin
- tval <= tval - 1;
- end
- end
- end else begin
- if (count0 != 5'b11111) begin
- count0 <= count0 + 1;
- end
- end
- end
+ if (prep == 3'b111) begin
+ if (sum > div) begin
+ tval <= tval + 1;
+ end else if (sum < div) begin
+ tval <= tval - 1;
+ end
+ end
+ end else begin
+ if (count0 != 5'b11111) begin
+ count0 <= count0 + 1;
+ end
+ end
+ end
end
endmodule // digital_pll_controller
diff --git a/verilog/rtl/gpio_wb.v b/verilog/rtl/gpio_wb.v
new file mode 100644
index 0000000..5f014ce
--- /dev/null
+++ b/verilog/rtl/gpio_wb.v
@@ -0,0 +1,147 @@
+module gpio_wb # (
+ parameter BASE_ADR = 32'h 2100_0000,
+ parameter GPIO_DATA = 8'h 00,
+ parameter GPIO_ENA = 8'h 04,
+ parameter GPIO_PU = 8'h 08,
+ parameter GPIO_PD = 8'h 0c
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_dat_i,
+ input [31:0] wb_adr_i,
+ input [3:0] wb_sel_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+ input wb_we_i,
+
+ output [31:0] wb_dat_o,
+ output wb_ack_o,
+
+ input [15:0] gpio_in_pad,
+ output [15:0] gpio,
+ output [15:0] gpio_oeb,
+ output [15:0] gpio_pu,
+ output [15:0] gpio_pd
+);
+
+ wire resetn;
+ wire valid;
+ wire ready;
+ wire [3:0] iomem_we;
+
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_stb_i && wb_cyc_i;
+
+ assign iomem_we = wb_sel_i & {4{wb_we_i}};
+ assign wb_ack_o = ready;
+
+ gpio #(
+ .BASE_ADR(BASE_ADR),
+ .GPIO_DATA(GPIO_DATA),
+ .GPIO_ENA(GPIO_ENA),
+ .GPIO_PD(GPIO_PD),
+ .GPIO_PU(GPIO_PU)
+ ) gpio_ctrl (
+ .clk(wb_clk_i),
+ .resetn(resetn),
+
+ .gpio_in_pad(gpio_in_pad),
+
+ .iomem_addr(wb_adr_i),
+ .iomem_valid(valid),
+ .iomem_wstrb(iomem_we),
+ .iomem_wdata(wb_dat_i),
+ .iomem_rdata(wb_dat_o),
+ .iomem_ready(ready),
+
+ .gpio(gpio),
+ .gpio_oeb(gpio_oeb),
+ .gpio_pu(gpio_pu),
+ .gpio_pd(gpio_pd)
+ );
+
+endmodule
+
+module gpio #(
+ parameter BASE_ADR = 32'h 2100_0000,
+ parameter GPIO_DATA = 8'h 00,
+ parameter GPIO_ENA = 8'h 04,
+ parameter GPIO_PU = 8'h 08,
+ parameter GPIO_PD = 8'h 0c
+) (
+ input clk,
+ input resetn,
+
+ input [15:0] gpio_in_pad,
+
+ input [31:0] iomem_addr,
+ input iomem_valid,
+ input [3:0] iomem_wstrb,
+ input [31:0] iomem_wdata,
+ output reg [31:0] iomem_rdata,
+ output reg iomem_ready,
+
+ output [15:0] gpio,
+ output [15:0] gpio_oeb,
+ output [15:0] gpio_pu,
+ output [15:0] gpio_pd
+);
+
+ reg [15:0] gpio; // GPIO output data
+ reg [15:0] gpio_pu; // GPIO pull-up enable
+ reg [15:0] gpio_pd; // GPIO pull-down enable
+ reg [15:0] gpio_oeb; // GPIO output enable (sense negative)
+
+ wire gpio_sel;
+ wire gpio_oeb_sel;
+ wire gpio_pu_sel;
+ wire gpio_pd_sel;
+
+ assign gpio_sel = (iomem_addr[7:0] == GPIO_DATA);
+ assign gpio_oeb_sel = (iomem_addr[7:0] == GPIO_ENA);
+ assign gpio_pu_sel = (iomem_addr[7:0] == GPIO_PU);
+ assign gpio_pd_sel = (iomem_addr[7:0] == GPIO_PD);
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ gpio <= 0;
+ gpio_oeb <= 16'hffff;
+ gpio_pu <= 0;
+ gpio_pd <= 0;
+ end else begin
+ iomem_ready <= 0;
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ iomem_ready <= 1'b 1;
+
+ if (gpio_sel) begin
+ iomem_rdata <= {gpio, gpio_in_pad};
+
+ if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8];
+
+ end else if (gpio_oeb_sel) begin
+ iomem_rdata <= {16'd0, gpio_oeb};
+
+ if (iomem_wstrb[0]) gpio_oeb[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) gpio_oeb[15: 8] <= iomem_wdata[15: 8];
+
+ end else if (gpio_pu_sel) begin
+ iomem_rdata <= {16'd0, gpio_pu};
+
+ if (iomem_wstrb[0]) gpio_pu[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) gpio_pu[15: 8] <= iomem_wdata[15: 8];
+
+ end else if (gpio_pd_sel) begin
+ iomem_rdata <= {16'd0, gpio_pd};
+
+ if (iomem_wstrb[0]) gpio_pd[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) gpio_pd[15: 8] <= iomem_wdata[15: 8];
+
+ end
+
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/harness.v b/verilog/rtl/harness.v
new file mode 100644
index 0000000..b8403e1
--- /dev/null
+++ b/verilog/rtl/harness.v
@@ -0,0 +1,1303 @@
+/*----------------------------------------------------------*/
+/* striVe, a raven/ravenna-like architecture in SkyWater s8 */
+/* */
+/* 1st edition, test of SkyWater s8 process */
+/* This version is missing all analog functionality, */
+/* including crystal oscillator, voltage regulator, and PLL */
+/* For simplicity, the pad arrangement of Raven has been */
+/* retained, even though many pads have no internal */
+/* connection. */
+/* */
+/* Copyright 2020 efabless, Inc. */
+/* Written by Tim Edwards, December 2019 */
+/* This file is open source hardware released under the */
+/* Apache 2.0 license. See file LICENSE. */
+/* */
+/*----------------------------------------------------------*/
+
+`timescale 1 ns / 1 ps
+
+`define USE_OPENRAM
+`define USE_PG_PIN
+`define functional
+
+`ifdef SYNTH_OPENLANE
+ `include "../stubs/scs8hd_conb_1.v"
+ `include "../stubs/s8iom0s8.v"
+ `include "../stubs/power_pads_lib.v"
+`else
+
+ `ifndef LVS
+ `include "/ef/tech/SW/EFS8A/libs.ref/verilog/s8iom0s8/s8iom0s8.v"
+ `include "/ef/tech/SW/EFS8A/libs.ref/verilog/s8iom0s8/power_pads_lib.v"
+ `include "/ef/tech/SW/EFS8A/libs.ref/verilog/scs8hd/scs8hd.v"
+
+ `include "lvlshiftdown.v"
+ `include "mgmt_soc.v"
+ `include "striVe_spi.v"
+ `include "digital_pll.v"
+ `include "striVe_clkrst.v"
+ `include "../ip/crossbar.v"
+ `include "../dv/dummy_slave.v"
+
+ `endif
+`endif
+
+`ifdef USE_OPENRAM
+ `include "sram_1rw1r_32_256_8_sky130.v"
+`endif
+
+//`define TOP_ROUTING
+`ifndef TOP_ROUTING
+ `define ABUTMENT_PINS \
+ .amuxbus_a(analog_a),\
+ .amuxbus_b(analog_b),\
+ .vssa(vss),\
+ .vdda(vdd),\
+ .vswitch(vdd),\
+ .vddio_q(vddio_q),\
+ .vcchib(vdd1v8),\
+ .vddio(vdd),\
+ .vccd(vdd1v8),\
+ .vssio(vss),\
+ .vssd(vss),\
+ .vssio_q(vssio_q),
+`else
+ `define ABUTMENT_PINS
+`endif
+
+// Crossbar Slaves
+`ifndef SLAVE_ADR
+ `define SLAVE_ADR { \
+ {8'hB0, {24{1'b0}}},\
+ {8'hA0, {24{1'b0}}},\
+ {8'h90, {24{1'b0}}},\
+ {8'h80, {24{1'b0}}}\
+ }\
+`endif
+
+`ifndef ADR_MASK
+ `define ADR_MASK { \
+ {8'hFF, {24{1'b0}}}, \
+ {8'hFF, {24{1'b0}}}, \
+ {8'hFF, {24{1'b0}}}, \
+ {8'hFF, {24{1'b0}}} \
+ }\
+`endif
+
+`define NM 2 // Crossbar switch number of masters
+`define NS 4 // Crossbar switch number of slaves
+`define DW 32
+`define AW 32
+
+module harness (vdd, vdd1v8, vss, gpio, xi, xo, adc0_in, adc1_in, adc_high, adc_low,
+ comp_inn, comp_inp, RSTB, ser_rx, ser_tx, irq, SDO, SDI, CSB, SCK,
+ xclk, flash_csb, flash_clk, flash_io0, flash_io1, flash_io2, flash_io3);
+
+ inout vdd;
+ inout vdd1v8;
+ inout vss;
+ inout [15:0] gpio;
+ input xi; // CMOS clock input, not a crystal
+ output xo; // divide-by-16 clock output
+ input adc0_in;
+ input adc1_in;
+ input adc_high;
+ input adc_low;
+ input comp_inn;
+ input comp_inp;
+ input RSTB; // NOTE: Replaces analog_out pin from raven chip
+ input ser_rx;
+ output ser_tx;
+ input irq;
+ output SDO;
+ input SDI;
+ input CSB;
+ input SCK;
+ input xclk;
+ output flash_csb;
+ output flash_clk;
+ output flash_io0;
+ output flash_io1;
+ output flash_io2;
+ output flash_io3;
+
+ wire [15:0] gpio_out_core;
+ wire [15:0] gpio_in_core;
+ wire [15:0] gpio_mode0_core;
+ wire [15:0] gpio_mode1_core;
+ wire [15:0] gpio_outenb_core;
+ wire [15:0] gpio_inenb_core;
+
+ wire analog_a, analog_b; /* Placeholders for analog signals */
+
+ wire porb_h;
+ wire porb_l;
+ wire por_h;
+ wire por;
+ wire SCK_core;
+ wire SDI_core;
+ wire CSB_core;
+ wire SDO_core;
+ wire SDO_enb;
+ wire spi_ro_xtal_ena_core;
+ wire spi_ro_reg_ena_core;
+ wire spi_ro_pll_dco_ena_core;
+ wire [2:0] spi_ro_pll_sel_core;
+ wire [4:0] spi_ro_pll_div_core;
+ wire [25:0] spi_ro_pll_trim_core;
+ wire ext_clk_sel_core;
+ wire irq_spi_core;
+ wire ext_reset_core;
+ wire trap_core;
+ wire [11:0] spi_ro_mfgr_id_core;
+ wire [7:0] spi_ro_prod_id_core;
+ wire [3:0] spi_ro_mask_rev_core;
+
+ // Instantiate power cells for VDD3V3 domain (8 total; 4 high clamps and
+ // 4 low clamps)
+ s8iom0_vdda_hvc_pad vdd3v3hclamp [1:0] (
+ `ABUTMENT_PINS
+ .drn_hvc(),
+ .src_bdy_hvc()
+ );
+
+ s8iom0_vddio_hvc_pad vddiohclamp [1:0] (
+ `ABUTMENT_PINS
+ .drn_hvc(),
+ .src_bdy_hvc()
+ );
+
+
+ s8iom0_vdda_lvc_pad vdd3v3lclamp [3:0] (
+ `ABUTMENT_PINS
+ .bdy2_b2b(),
+ .drn_lvc1(),
+ .drn_lvc2(),
+ .src_bdy_lvc1(),
+ .src_bdy_lvc2()
+ );
+
+ // Instantiate the core voltage supply (since it is not generated on-chip)
+ // (1.8V) (4 total, 2 high and 2 low clamps)
+
+ s8iom0_vccd_hvc_pad vdd1v8hclamp [1:0] (
+ `ABUTMENT_PINS
+ .drn_hvc(),
+ .src_bdy_hvc()
+ );
+
+ s8iom0_vccd_lvc_pad vdd1v8lclamp [1:0] (
+ `ABUTMENT_PINS
+ .bdy2_b2b(),
+ .drn_lvc1(),
+ .drn_lvc2(),
+ .src_bdy_lvc1(),
+ .src_bdy_lvc2()
+ );
+
+ // Instantiate ground cells (7 total, 4 high clamps and 3 low clamps)
+
+ s8iom0_vssa_hvc_pad vsshclamp [3:0] (
+ `ABUTMENT_PINS
+ .drn_hvc(),
+ .src_bdy_hvc()
+ );
+
+ s8iom0_vssa_lvc_pad vssalclamp (
+ `ABUTMENT_PINS
+ .bdy2_b2b(),
+ .drn_lvc1(),
+ .drn_lvc2(),
+ .src_bdy_lvc1(),
+ .src_bdy_lvc2()
+ );
+
+ s8iom0_vssd_lvc_pad vssdlclamp (
+ `ABUTMENT_PINS
+ .bdy2_b2b(),
+ .drn_lvc1(),
+ .drn_lvc2(),
+ .src_bdy_lvc1(),
+ .src_bdy_lvc2()
+ );
+
+ s8iom0_vssio_lvc_pad vssiolclamp (
+ `ABUTMENT_PINS
+ .bdy2_b2b(),
+ .drn_lvc1(),
+ .drn_lvc2(),
+ .src_bdy_lvc1(),
+ .src_bdy_lvc2()
+ );
+
+ wire [47:0] dm_all;
+
+ assign dm_all = {gpio_mode1_core[15], gpio_mode1_core[15], gpio_mode0_core[15],
+ gpio_mode1_core[14], gpio_mode1_core[14], gpio_mode0_core[14],
+ gpio_mode1_core[13], gpio_mode1_core[13], gpio_mode0_core[13],
+ gpio_mode1_core[12], gpio_mode1_core[12], gpio_mode0_core[12],
+ gpio_mode1_core[11], gpio_mode1_core[11], gpio_mode0_core[11],
+ gpio_mode1_core[10], gpio_mode1_core[10], gpio_mode0_core[10],
+ gpio_mode1_core[9], gpio_mode1_core[9], gpio_mode0_core[9],
+ gpio_mode1_core[8], gpio_mode1_core[8], gpio_mode0_core[8],
+ gpio_mode1_core[7], gpio_mode1_core[7], gpio_mode0_core[7],
+ gpio_mode1_core[6], gpio_mode1_core[6], gpio_mode0_core[6],
+ gpio_mode1_core[5], gpio_mode1_core[5], gpio_mode0_core[5],
+ gpio_mode1_core[4], gpio_mode1_core[4], gpio_mode0_core[4],
+ gpio_mode1_core[3], gpio_mode1_core[3], gpio_mode0_core[3],
+ gpio_mode1_core[2], gpio_mode1_core[2], gpio_mode0_core[2],
+ gpio_mode1_core[1], gpio_mode1_core[1], gpio_mode0_core[1],
+ gpio_mode1_core[0], gpio_mode1_core[0], gpio_mode0_core[0]};
+
+ // GPIO pads
+ s8iom0_gpiov2_pad gpio_pad [15:0] (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(gpio),
+`endif
+ .out(gpio_out_core), // Signal from core to pad
+ .oe_n(gpio_outenb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold signals during deep sleep (sense inverted)
+ .enable_h(porb_h), // Post-reset enable
+ .enable_inp_h(loopb0), // Input buffer state when disabled
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(gpio_inenb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm(dm_all), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(gpio_in_core), // Signal from pad to core
+ .in_h(), // VDDA domain signal (unused)
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb0)
+ );
+
+ s8iom0_gpiov2_pad xi_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(xi),
+`endif
+ .out(), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb1), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(xi_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb1)
+ );
+
+ s8iom0_gpiov2_pad xo_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(xo),
+`endif
+ .out(pll_clk16), // Signal from core to pad
+ .oe_n(vss), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb2), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb2)
+ );
+
+ s8iom0_gpiov2_pad adc0_in_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(adc0_in),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb3), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad adc1_in_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(adc1_in),
+`endif
+ .pad_a_noesd_h(), // Direct pad connection
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb4), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad adc_high_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(adc_high),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb5), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vdd1v8), //
+ .analog_pol(vdd1v8), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad adc_low_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(adc_low),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb6), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad comp_inn_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(comp_inn),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb7), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad comp_inp_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(comp_inp),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb8), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vdd1v8), //
+ .analog_sel(vdd1v8), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ // NOTE: The analog_out pad from the raven chip has been replaced by
+ // the digital reset input RSTB on striVe due to the lack of an on-board
+ // power-on-reset circuit. The XRES pad is used for providing a glitch-
+ // free reset.
+
+ s8iom0s8_top_xres4v2 RSTB_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(RSTB),
+`endif
+ .tie_weak_hi_h(xresloop), // Loop-back connection to pad through pad_a_esd_h
+ .tie_hi_esd(),
+ .tie_lo_esd(),
+ .pad_a_esd_h(xresloop),
+ .xres_h_n(porb_h),
+ .disable_pullup_h(vss), // 0 = enable pull-up on reset pad
+ .enable_h(vdd), // Power-on-reset to the power-on-reset input??
+ .en_vddio_sig_h(vss), // No idea.
+ .inp_sel_h(vss), // 1 = use filt_in_h else filter the pad input
+ .filt_in_h(vss), // Alternate input for glitch filter
+ .pullup_h(vss), // Pullup connection for alternate filter input
+ .enable_vddio(vdd1v8)
+ );
+
+ s8iom0_gpiov2_pad irq_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(irq),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb10), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(irq_pin_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb10)
+ );
+
+ s8iom0_gpiov2_pad SDO_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(SDO),
+`endif
+ .out(SDO_core), // Signal from core to pad
+ .oe_n(SDO_enb), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb11), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(vdd1v8), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb11)
+ );
+
+ s8iom0_gpiov2_pad SDI_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(SDI),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb12), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(SDI_core), // Signal from pad to core
+ .in_h(SDI_core_h),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad CSB_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(CSB),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb13), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(CSB_core), // Signal from pad to core
+ .in_h(CSB_core_h),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb13)
+ );
+
+ s8iom0_gpiov2_pad SCK_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(SCK),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb14), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(SCK_core), // Signal from pad to core
+ .in_h(SCK_core_h), // Signal in vdda domain (3.3V)
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb14)
+ );
+
+ s8iom0_gpiov2_pad xclk_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(xclk),
+`endif
+ .out(vss), // Signal from core to pad
+ .oe_n(vdd1v8), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb15), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(por), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vss, vss, vdd1v8}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(ext_clk_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb15)
+ );
+
+ // assign flash_csb = (input) ?
+ s8iom0_gpiov2_pad flash_csb_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_csb),
+`endif
+ .out(flash_csb_core), // Signal from core to pad
+ .oe_n(flash_csb_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb16), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_csb_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad flash_clk_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_clk),
+`endif
+ .out(flash_clk_core), // Signal from core to pad
+ .oe_n(flash_clk_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb17), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_clk_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0_gpiov2_pad flash_io0_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_io0),
+`endif
+ .out(flash_io0_do_core), // Signal from core to pad
+ .oe_n(flash_io0_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb18), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_io0_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(flash_io0_di_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb18)
+ );
+
+ s8iom0_gpiov2_pad flash_io1_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_io1),
+`endif
+ .out(flash_io1_do_core), // Signal from core to pad
+ .oe_n(flash_io1_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb19), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_io1_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(flash_io1_di_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb19)
+ );
+
+ s8iom0_gpiov2_pad flash_io2_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_io2),
+`endif
+ .out(flash_io2_do_core), // Signal from core to pad
+ .oe_n(flash_io2_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb20), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_io2_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({flash_io2_ieb_core, flash_io2_ieb_core, flash_io2_oeb_core}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(flash_io2_di_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb20)
+ );
+
+ s8iom0_gpiov2_pad flash_io3_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(flash_io3),
+`endif
+ .out(flash_io3_do_core), // Signal from core to pad
+ .oe_n(flash_io3_oeb_core), // Output enable (sense inverted)
+ .hld_h_n(vdd), // Hold
+ .enable_h(porb_h), // Enable
+ .enable_inp_h(loopb21), // Enable input buffer
+ .enable_vdda_h(porb_h), //
+ .enable_vswitch_h(vss), //
+ .enable_vddio(vdd1v8), //
+ .inp_dis(flash_io3_ieb_core), // Disable input buffer
+ .ib_mode_sel(vss), //
+ .vtrip_sel(vss), //
+ .slow(vss), //
+ .hld_ovr(vss), //
+ .analog_en(vss), //
+ .analog_sel(vss), //
+ .analog_pol(vss), //
+ .dm({flash_io3_ieb_core, flash_io3_ieb_core, flash_io3_oeb_core}), // (3 bits) Mode control
+ .pad_a_noesd_h(), // Direct pad connection
+ .pad_a_esd_0_h(), // Pad connection through 150 ohms
+ .pad_a_esd_1_h(), // Pad connection through 150 ohms
+ .in(flash_io3_di_core), // Signal from pad to core
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd(loopb21)
+ );
+
+ // Instantiate GPIO overvoltage (I2C) compliant cell
+ // (Use this for ser_rx and ser_tx; no reason other than testing
+ // the use of the cell.) (Might be worth adding in the I2C IP from
+ // ravenna just to test on a proper I2C channel.)
+
+ s8iom0s8_top_gpio_ovtv2 ser_rx_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(ser_rx),
+`endif
+ .out(vss),
+ .oe_n(vdd1v8),
+ .hld_h_n(vdd),
+ .enable_h(porb_h),
+ .enable_inp_h(loopb22),
+ .enable_vdda_h(porb_h),
+ .enable_vddio(vdd1v8),
+ .enable_vswitch_h(vss),
+ .inp_dis(por),
+ .vtrip_sel(vss),
+ .hys_trim(vdd1v8),
+ .slow(vss),
+ .slew_ctl({vss, vss}), // 2 bits
+ .hld_ovr(vss),
+ .analog_en(vss),
+ .analog_sel(vss),
+ .analog_pol(vss),
+ .dm({vss, vss, vdd1v8}), // 3 bits
+ .ib_mode_sel({vss, vss}), // 2 bits
+ .vinref(vdd1v8),
+ .pad_a_noesd_h(),
+ .pad_a_esd_0_h(),
+ .pad_a_esd_1_h(),
+ .in(ser_rx_core),
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ s8iom0s8_top_gpio_ovtv2 ser_tx_pad (
+ `ABUTMENT_PINS
+`ifndef TOP_ROUTING
+ .pad(ser_tx),
+`endif
+ .out(ser_tx_core),
+ .oe_n(vss),
+ .hld_h_n(vdd),
+ .enable_h(porb_h),
+ .enable_inp_h(loopb23),
+ .enable_vdda_h(porb_h),
+ .enable_vddio(vdd1v8),
+ .enable_vswitch_h(vss),
+ .inp_dis(vdd1v8),
+ .vtrip_sel(vss),
+ .hys_trim(vdd1v8),
+ .slow(vss),
+ .slew_ctl({vss, vss}), // 2 bits
+ .hld_ovr(vss),
+ .analog_en(vss),
+ .analog_sel(vss),
+ .analog_pol(vss),
+ .dm({vdd1v8, vdd1v8, vss}), // 3 bits
+ .ib_mode_sel({vss, vss}), // 2 bits
+ .vinref(vdd1v8),
+ .pad_a_noesd_h(),
+ .pad_a_esd_0_h(),
+ .pad_a_esd_1_h(),
+ .in(),
+ .in_h(),
+ .tie_hi_esd(),
+ .tie_lo_esd()
+ );
+
+ // Corner cells (These are overlay cells; it is not clear what is normally
+ // supposed to go under them.)
+ `ifndef TOP_ROUTING
+ s8iom0_corner_pad corner [3:0] (
+ .vssio(vss),
+ .vddio(vdd),
+ .vddio_q(vddio_q),
+ .vssio_q(vssio_q),
+ .amuxbus_a(analog_a),
+ .amuxbus_b(analog_b),
+ .vssd(vss),
+ .vssa(vss),
+ .vswitch(vdd),
+ .vdda(vdd),
+ .vccd(vdd1v8),
+ .vcchib(vdd1v8)
+ //`ABUTMENT_PINS
+ );
+`endif
+
+ // SoC core
+ wire [9:0] adc0_data_core;
+ wire [1:0] adc0_inputsrc_core;
+ wire [9:0] adc1_data_core;
+ wire [1:0] adc1_inputsrc_core;
+ wire [9:0] dac_value_core;
+ wire [1:0] comp_ninputsrc_core;
+ wire [1:0] comp_pinputsrc_core;
+ wire [7:0] spi_ro_config_core;
+
+ wire xbar_cyc_o_core;
+ wire xbar_stb_o_core;
+ wire xbar_we_o_core;
+ wire [3:0] xbar_sel_o_core;
+ wire [31:0] xbar_adr_o_core;
+ wire [31:0] xbar_dat_o_core;
+ wire xbar_ack_i_core;
+ wire [31:0] xbar_dat_i_core;
+
+ wire striVe_clk, striVe_rstn;
+
+ striVe_clkrst clkrst(
+ `ifdef LVS
+ .vdd1v8(vdd1v8),
+ .vss(vss),
+ `endif
+ .ext_clk_sel(ext_clk_sel_core),
+ .ext_clk(ext_clk_core),
+ .pll_clk(pll_clk_core),
+ .reset(por),
+ .ext_reset(ext_reset_core),
+ .clk(striVe_clk),
+ .resetn(striVe_rstn)
+ );
+
+ mgmt_soc core (
+ `ifdef LVS
+ .vdd1v8(vdd1v8),
+ .vss(vss),
+ `endif
+ .pll_clk(pll_clk_core),
+ .ext_clk(ext_clk_core),
+ .ext_clk_sel(ext_clk_sel_core),
+ .clk(striVe_clk),
+ .resetn(striVe_rstn),
+ .gpio_out_pad(gpio_out_core),
+ .gpio_in_pad(gpio_in_core),
+ .gpio_mode0_pad(gpio_mode0_core),
+ .gpio_mode1_pad(gpio_mode1_core),
+ .gpio_outenb_pad(gpio_outenb_core),
+ .gpio_inenb_pad(gpio_inenb_core),
+ .adc0_ena(adc0_ena_core),
+ .adc0_convert(adc0_convert_core),
+ .adc0_data(adc0_data_core),
+ .adc0_done(adc0_done_core),
+ .adc0_clk(adc0_clk_core),
+ .adc0_inputsrc(adc0_inputsrc_core),
+ .adc1_ena(adc1_ena_core),
+ .adc1_convert(adc1_convert_core),
+ .adc1_clk(adc1_clk_core),
+ .adc1_inputsrc(adc1_inputsrc_core),
+ .adc1_data(adc1_data_core),
+ .adc1_done(adc1_done_core),
+ .xtal_in(xtal_in_core),
+ .comp_in(comp_in_core),
+ .spi_sck(SCK_core),
+ .spi_ro_config(spi_ro_config_core),
+ .spi_ro_xtal_ena(spi_ro_xtal_ena_core),
+ .spi_ro_reg_ena(spi_ro_reg_ena_core),
+ .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena_core),
+ .spi_ro_pll_div(spi_ro_pll_div_core),
+ .spi_ro_pll_sel(spi_ro_pll_sel_core),
+ .spi_ro_pll_trim(spi_ro_pll_trim_core),
+ .spi_ro_mfgr_id(spi_ro_mfgr_id_core),
+ .spi_ro_prod_id(spi_ro_prod_id_core),
+ .spi_ro_mask_rev(spi_ro_mask_rev_core),
+ .ser_tx(ser_tx_core),
+ .ser_rx(ser_rx_core),
+ .irq_pin(irq_pin_core),
+ .irq_spi(irq_spi_core),
+ .trap(trap_core),
+ .flash_csb(flash_csb_core),
+ .flash_clk(flash_clk_core),
+ .flash_csb_oeb(flash_csb_oeb_core),
+ .flash_clk_oeb(flash_clk_oeb_core),
+ .flash_io0_oeb(flash_io0_oeb_core),
+ .flash_io1_oeb(flash_io1_oeb_core),
+ .flash_io2_oeb(flash_io2_oeb_core),
+ .flash_io3_oeb(flash_io3_oeb_core),
+ .flash_csb_ieb(flash_csb_ieb_core),
+ .flash_clk_ieb(flash_clk_ieb_core),
+ .flash_io0_ieb(flash_io0_ieb_core),
+ .flash_io1_ieb(flash_io1_ieb_core),
+ .flash_io2_ieb(flash_io2_ieb_core),
+ .flash_io3_ieb(flash_io3_ieb_core),
+ .flash_io0_do(flash_io0_do_core),
+ .flash_io1_do(flash_io1_do_core),
+ .flash_io2_do(flash_io2_do_core),
+ .flash_io3_do(flash_io3_do_core),
+ .flash_io0_di(flash_io0_di_core),
+ .flash_io1_di(flash_io1_di_core),
+ .flash_io2_di(flash_io2_di_core),
+ .flash_io3_di(flash_io3_di_core),
+ .xbar_cyc_o(xbar_cyc_o_core),
+ .xbar_stb_o(xbar_stb_o_core),
+ .xbar_we_o (xbar_we_o_core),
+ .xbar_sel_o(xbar_sel_o_core),
+ .xbar_adr_o(xbar_adr_o_core),
+ .xbar_dat_o(xbar_dat_o_core),
+ .xbar_ack_i(xbar_ack_i_core),
+ .xbar_dat_i(xbar_dat_i_core)
+ );
+
+ // Mega-Project
+ wire mega_cyc_o;
+ wire mega_stb_o;
+ wire mega_we_o;
+ wire [3:0] mega_sel_o;
+ wire [31:0] mega_adr_o;
+ wire [31:0] mega_dat_o;
+ wire mega_ack_i;
+ wire [31:0] mega_dat_i;
+
+ // Masters interface
+ wire [`NM-1:0] wbm_cyc_i;
+ wire [`NM-1:0] wbm_stb_i;
+ wire [`NM-1:0] wbm_we_i;
+ wire [(`NM*(`DW/8))-1:0] wbm_sel_i;
+ wire [(`NM*`AW)-1:0] wbm_adr_i;
+ wire [(`NM*`DW)-1:0] wbm_dat_i;
+
+ wire [`NM-1:0] wbm_ack_o;
+ wire [(`NM*`DW)-1:0] wbm_dat_o;
+
+ // Slaves interfaces
+ wire [`NS-1:0] wbs_ack_o;
+ wire [(`NS*`DW)-1:0] wbs_dat_i;
+ wire [`NS-1:0] wbs_cyc_o;
+ wire [`NS-1:0] wbs_stb_o;
+ wire [`NS-1:0] wbs_we_o;
+ wire [(`NS*(`DW/8))-1:0] wbs_sel_o;
+ wire [(`NS*`AW)-1:0] wbs_adr_o;
+ wire [(`NS*`DW)-1:0] wbs_dat_o;
+
+ assign wbm_cyc_i = {mega_cyc_o, xbar_cyc_o_core};
+ assign wbm_stb_i = {mega_stb_o, xbar_stb_o_core};
+ assign wbm_we_i = {mega_we_o , xbar_we_o_core};
+ assign wbm_sel_i = {mega_sel_o, xbar_sel_o_core};
+ assign wbm_adr_i = {mega_adr_o, xbar_adr_o_core};
+ assign wbm_dat_i = {mega_dat_o, xbar_dat_o_core};
+
+ assign xbar_ack_i_core = wbm_ack_o[0];
+ assign mega_ack_i = wbm_ack_o[1];
+ assign xbar_dat_i_core = wbm_dat_o[`DW-1:0];
+ assign mega_dat_i = wbm_dat_o[`DW*2-1:`DW];
+
+ // Instantiate four dummy slaves for testing (TO-BE-REMOVED)
+ dummy_slave dummy_slaves [`NS-1:0](
+ .wb_clk_i({`NS{striVe_clk}}),
+ .wb_rst_i({`NS{~striVe_rstn}}),
+ .wb_stb_i(wbs_stb_o),
+ .wb_cyc_i(wbs_cyc_o),
+ .wb_we_i(wbs_we_o),
+ .wb_sel_i(wbs_sel_o),
+ .wb_adr_i(wbs_adr_o),
+ .wb_dat_i(wbs_dat_i),
+ .wb_dat_o(wbs_dat_o),
+ .wb_ack_o(wbs_ack_o)
+ );
+ // Crossbar Switch
+ wb_xbar #(
+ .NM(`NM),
+ .NS(`NS),
+ .AW(`AW),
+ .DW(`DW),
+ .SLAVE_ADR(`SLAVE_ADR),
+ .ADR_MASK(`ADR_MASK)
+ )
+ wb_xbar(
+ .wb_clk_i(striVe_clk),
+ .wb_rst_i(~striVe_rstn),
+
+ // Masters interface
+ .wbm_cyc_i(wbm_cyc_i),
+ .wbm_stb_i(wbm_stb_i),
+ .wbm_we_i (wbm_we_i),
+ .wbm_sel_i(wbm_sel_i),
+ .wbm_adr_i(wbm_adr_i),
+ .wbm_dat_i(wbm_dat_i),
+ .wbm_ack_o(wbm_ack_o),
+ .wbm_dat_o(wbm_dat_o),
+
+ // Slaves interfaces
+ .wbs_ack_i(wbs_ack_o),
+ .wbs_dat_i(wbs_dat_o),
+ .wbs_cyc_o(wbs_cyc_o),
+ .wbs_stb_o(wbs_stb_o),
+ .wbs_we_o (wbs_we_o),
+ .wbs_sel_o(wbs_sel_o),
+ .wbs_adr_o(wbs_adr_o),
+ .wbs_dat_o(wbs_dat_i)
+ );
+
+ // For the mask revision input, use an array of digital constant logic cells
+ wire [3:0] mask_rev;
+ wire [3:0] no_connect;
+ scs8hd_conb_1 mask_rev_value [3:0] (
+ `ifdef LVS
+ .vpwr(vdd1v8),
+ .vpb(vdd1v8),
+ .vnb(vss),
+ .vgnd(vss),
+ `endif
+ .HI({no_connect[3:1], mask_rev[0]}),
+ .LO({mask_rev[3:1], no_connect[0]})
+ );
+
+ // Housekeeping SPI at 1.8V.
+
+ striVe_spi housekeeping (
+ `ifdef LVS
+ .vdd(vdd1v8),
+ .vss(vss),
+ `endif
+ .RSTB(porb_l),
+ .SCK(SCK_core),
+ .SDI(SDI_core),
+ .CSB(CSB_core),
+ .SDO(SDO_core),
+ .sdo_enb(SDO_enb),
+
+ .xtal_ena(spi_ro_xtal_ena_core),
+ .reg_ena(spi_ro_reg_ena_core),
+ .pll_dco_ena(spi_ro_pll_dco_ena_core),
+ .pll_sel(spi_ro_pll_sel_core),
+ .pll_div(spi_ro_pll_div_core),
+ .pll_trim(spi_ro_pll_trim_core),
+ .pll_bypass(ext_clk_sel_core),
+ .irq(irq_spi_core),
+ .RST(por),
+ .reset(ext_reset_core),
+ .trap(trap_core),
+ .mfgr_id(spi_ro_mfgr_id_core),
+ .prod_id(spi_ro_prod_id_core),
+ .mask_rev_in(mask_rev),
+ .mask_rev(spi_ro_mask_rev_core)
+ );
+
+ lvlshiftdown porb_level_shift (
+ `ifdef LVS
+ .vpwr(vdd1v8),
+ .vpb(vdd1v8),
+ .vnb(vss),
+ .vgnd(vss),
+ `endif
+ .A(porb_h),
+ .X(porb_l)
+ );
+
+ // On-board experimental digital PLL
+ // Use xi_core, assumed to be a CMOS digital clock signal. xo_core
+ // is used as an output and set from pll_clk16.
+
+ digital_pll pll (
+ `ifdef LVS
+ .vdd(vdd1v8),
+ .vss(vss),
+ `endif
+ .reset(por),
+ .extclk_sel(ext_clk_sel_core),
+ .osc(xi_core),
+ .clockc(pll_clk_core),
+ .clockp({pll_clk_core0, pll_clk_core90}),
+ .clockd({pll_clk2, pll_clk4, pll_clk8, pll_clk16}),
+ .div(spi_ro_pll_div_core),
+ .sel(spi_ro_pll_sel_core),
+ .dco(spi_ro_pll_dco_ena_core),
+ .ext_trim(spi_ro_pll_trim_core)
+ );
+
+endmodule
diff --git a/verilog/rtl/la_wb.v b/verilog/rtl/la_wb.v
new file mode 100644
index 0000000..fd713a4
--- /dev/null
+++ b/verilog/rtl/la_wb.v
@@ -0,0 +1,201 @@
+module la_wb # (
+ parameter BASE_ADR = 32'h 2200_0000,
+ parameter LA_DATA_0 = 8'h00,
+ parameter LA_DATA_1 = 8'h04,
+ parameter LA_DATA_2 = 8'h08,
+ parameter LA_DATA_3 = 8'h0c,
+ parameter LA_ENA_0 = 8'h10,
+ parameter LA_ENA_1 = 8'h14,
+ parameter LA_ENA_2 = 8'h18,
+ parameter LA_ENA_3 = 8'h1c
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_dat_i,
+ input [31:0] wb_adr_i,
+ input [3:0] wb_sel_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+ input wb_we_i,
+
+ output [31:0] wb_dat_o,
+ output wb_ack_o,
+
+ output [127:0] la_data,
+ output [127:0] la_ena
+);
+
+ wire resetn;
+ wire valid;
+ wire ready;
+ wire [3:0] iomem_we;
+
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_stb_i && wb_cyc_i;
+
+ assign iomem_we = wb_sel_i & {4{wb_we_i}};
+ assign wb_ack_o = ready;
+
+ la #(
+ .BASE_ADR(BASE_ADR),
+ .LA_DATA_0(LA_DATA_0),
+ .LA_DATA_1(LA_DATA_1),
+ .LA_DATA_2(LA_DATA_2),
+ .LA_DATA_3(LA_DATA_3),
+ .LA_ENA_0(LA_ENA_0),
+ .LA_ENA_1(LA_ENA_1),
+ .LA_ENA_2(LA_ENA_2),
+ .LA_ENA_3(LA_ENA_3)
+ ) la_ctrl (
+ .clk(wb_clk_i),
+ .resetn(resetn),
+ .iomem_addr(wb_adr_i),
+ .iomem_valid(valid),
+ .iomem_wstrb(iomem_we),
+ .iomem_wdata(wb_dat_i),
+ .iomem_rdata(wb_dat_o),
+ .iomem_ready(ready),
+ .la_data(la_data),
+ .la_ena(la_ena)
+ );
+
+endmodule
+
+module la #(
+ parameter BASE_ADR = 32'h 2200_0000,
+ parameter LA_DATA_0 = 8'h00,
+ parameter LA_DATA_1 = 8'h04,
+ parameter LA_DATA_2 = 8'h08,
+ parameter LA_DATA_3 = 8'h0c,
+ parameter LA_ENA_0 = 8'h10,
+ parameter LA_ENA_1 = 8'h14,
+ parameter LA_ENA_2 = 8'h18,
+ parameter LA_ENA_3 = 8'h1c
+) (
+ input clk,
+ input resetn,
+
+ input [31:0] iomem_addr,
+ input iomem_valid,
+ input [3:0] iomem_wstrb,
+ input [31:0] iomem_wdata,
+
+ output reg [31:0] iomem_rdata,
+ output reg iomem_ready,
+
+ output [127:0] la_data,
+ output [127:0] la_ena
+);
+
+ reg [31:0] la_data_0;
+ reg [31:0] la_data_1;
+ reg [31:0] la_data_2;
+ reg [31:0] la_data_3;
+
+ reg [31:0] la_ena_0;
+ reg [31:0] la_ena_1;
+ reg [31:0] la_ena_2;
+ reg [31:0] la_ena_3;
+
+ wire [3:0] la_data_sel;
+ wire [3:0] la_ena_sel;
+
+ assign la_data = {la_data_3, la_data_2, la_data_1, la_data_0};
+ assign la_ena = {la_ena_3, la_ena_2, la_ena_1, la_ena_0};
+
+ assign la_data_sel = {
+ (iomem_addr[7:0] == LA_DATA_3),
+ (iomem_addr[7:0] == LA_DATA_2),
+ (iomem_addr[7:0] == LA_DATA_1),
+ (iomem_addr[7:0] == LA_DATA_0)
+ };
+
+ assign la_ena_sel = {
+ (iomem_addr[7:0] == LA_ENA_3),
+ (iomem_addr[7:0] == LA_ENA_2),
+ (iomem_addr[7:0] == LA_ENA_1),
+ (iomem_addr[7:0] == LA_ENA_0)
+ };
+
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ la_data_0 <= 0;
+ la_data_1 <= 0;
+ la_data_2 <= 0;
+ la_data_3 <= 0;
+ la_ena_0 <= 0;
+ la_ena_1 <= 0;
+ la_ena_2 <= 0;
+ la_ena_3 <= 0;
+ end else begin
+ iomem_ready <= 0;
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ iomem_ready <= 1'b 1;
+
+ if (la_data_sel[0]) begin
+ iomem_rdata <= la_data_0;
+
+ if (iomem_wstrb[0]) la_data_0[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_data_0[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_data_0[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_data_0[31:24] <= iomem_wdata[31:24];
+
+ end else if (la_data_sel[1]) begin
+ iomem_rdata <= la_data_1;
+
+ if (iomem_wstrb[0]) la_data_1[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_data_1[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_data_1[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_data_1[31:24] <= iomem_wdata[31:24];
+
+ end else if (la_data_sel[2]) begin
+ iomem_rdata <= la_data_2;
+
+ if (iomem_wstrb[0]) la_data_2[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_data_2[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_data_2[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_data_2[31:24] <= iomem_wdata[31:24];
+
+ end else if (la_data_sel[3]) begin
+ iomem_rdata <= la_data_3;
+
+ if (iomem_wstrb[0]) la_data_3[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_data_3[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_data_3[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_data_3[31:24] <= iomem_wdata[31:24];
+ end else if (la_ena_sel[0]) begin
+ iomem_rdata <= la_ena_0;
+
+ if (iomem_wstrb[0]) la_ena_0[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_ena_0[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_ena_0[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_ena_0[31:24] <= iomem_wdata[31:24];
+ end else if (la_ena_sel[1]) begin
+ iomem_rdata <= la_ena_1;
+
+ if (iomem_wstrb[0]) la_ena_1[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_ena_1[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_ena_1[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_ena_1[31:24] <= iomem_wdata[31:24];
+ end else if (la_ena_sel[2]) begin
+ iomem_rdata <= la_ena_2;
+
+ if (iomem_wstrb[0]) la_ena_2[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_ena_2[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_ena_2[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_ena_2[31:24] <= iomem_wdata[31:24];
+ end else if (la_ena_sel[3]) begin
+ iomem_rdata <= la_ena_3;
+
+ if (iomem_wstrb[0]) la_ena_3[ 7: 0] <= iomem_wdata[ 7: 0];
+ if (iomem_wstrb[1]) la_ena_3[15: 8] <= iomem_wdata[15: 8];
+ if (iomem_wstrb[2]) la_ena_3[23:16] <= iomem_wdata[23:16];
+ if (iomem_wstrb[3]) la_ena_3[31:24] <= iomem_wdata[31:24];
+ end
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/lvlshiftdown.v b/verilog/rtl/lvlshiftdown.v
new file mode 100644
index 0000000..a647cf6
--- /dev/null
+++ b/verilog/rtl/lvlshiftdown.v
@@ -0,0 +1,30 @@
+/* Level shifter (simplified model, as buffer only) */
+
+module lvlshiftdown (
+`ifdef LVS
+ vpwr, vpb, vnb, vgnd,
+`endif
+ A,
+ X
+ );
+
+
+`ifdef LVS
+ input vpwr;
+ input vpb;
+ input vnb;
+ input vgnd;
+`endif
+
+input A;
+output X;
+
+`ifdef LVS
+ wire vpwr, vpb, vnb, vgnd;
+`endif
+
+wire A, X;
+
+assign X = A;
+
+endmodule // lvlshiftdown
diff --git a/verilog/rtl/mem_wb.v b/verilog/rtl/mem_wb.v
new file mode 100644
index 0000000..e0b6599
--- /dev/null
+++ b/verilog/rtl/mem_wb.v
@@ -0,0 +1,106 @@
+module mem_wb # (
+ parameter integer MEM_WORDS = 256
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_adr_i,
+ input [31:0] wb_dat_i,
+ input [3:0] wb_sel_i,
+ input wb_we_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+
+ output wb_ack_o,
+ output [31:0] wb_dat_o
+
+);
+ wire valid;
+ wire ram_wen;
+ wire [3:0] wen; // write enable
+
+ assign valid = wb_cyc_i & wb_stb_i;
+ assign ram_wen = wb_we_i && valid;
+
+ assign wen = wb_sel_i & {4{ram_wen}} ;
+
+`ifndef USE_OPENRAM
+ assign wb_ack_o = valid;
+`else
+
+ /*
+ Ack Generation
+ - write transaction: asserted upon receiving adr_i & dat_i
+ - read transaction : asserted one clock cycle after receiving the adr_i & dat_i
+ */
+
+ reg [2:0] wb_ack_read;
+
+ assign wb_ack_o = wb_we_i ? valid : &wb_ack_read;
+
+ always @(posedge wb_clk_i) begin
+ if (wb_rst_i == 1'b 1) begin
+ wb_ack_read <= 3'b 00;
+ end else begin
+ wb_ack_read <= {3{valid}} & {1'b1, wb_ack_read[2:1]};
+ end
+ end
+
+`endif
+
+ soc_mem mem(
+ .clk(wb_clk_i),
+ .ena(valid),
+ .wen(wen),
+ .addr(wb_adr_i[23:2]),
+ .wdata(wb_dat_i),
+ .rdata(wb_dat_o)
+ );
+
+endmodule
+
+module soc_mem
+`ifndef USE_OPENRAM
+#(
+ parameter integer WORDS = 256
+)
+`endif
+ (
+ input clk,
+ input ena,
+ input [3:0] wen,
+ input [21:0] addr,
+ input [31:0] wdata,
+ output[31:0] rdata
+);
+
+`ifndef USE_OPENRAM
+ reg [31:0] rdata;
+ reg [31:0] mem [0:WORDS-1];
+
+ always @(posedge clk) begin
+ if (ena == 1'b1) 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
+ end
+`else
+
+ /* Using Port 0 Only - Size: 1KB, 256x32 bits */
+ //sram_1rw1r_32_256_8_scn4m_subm
+ sram_1rw1r_32_256_8_sky130 SRAM(
+ .clk0(clk),
+ .csb0(~ena),
+ .web0(~|wen),
+ .wmask0(wen),
+ .addr0(addr[7:0]),
+ .din0(wdata),
+ .dout0(rdata)
+ );
+
+`endif
+
+endmodule
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v
new file mode 100644
index 0000000..007ca0f
--- /dev/null
+++ b/verilog/rtl/mgmt_soc.v
@@ -0,0 +1,876 @@
+/*
+ * PicoSoC - A simple example SoC using PicoRV32
+ *
+ * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Revision 1, July 2019: Added signals to drive flash_clk and flash_csb
+ * output enable (inverted), tied to reset so that the flash is completely
+ * isolated from the processor when the processor is in reset.
+ *
+ * Also: Made ram_wenb a 4-bit bus so that the memory access can be made
+ * byte-wide for byte-wide instructions.
+ */
+
+`ifdef PICORV32_V
+`error "openstriVe_soc.v must be read before picorv32.v!"
+`endif
+
+`define PICORV32_REGS openstriVe_soc_regs
+
+`include "picorv32.v"
+`include "spimemio.v"
+`include "simpleuart.v"
+`include "wb_intercon.v"
+`include "mem_wb.v"
+`include "gpio_wb.v"
+`include "spi_sysctrl.v"
+`include "sysctrl.v"
+`include "la_wb.v"
+
+module mgmt_soc (
+`ifdef LVS
+ inout vdd1v8, /* 1.8V domain */
+ inout vss,
+`endif
+ input pll_clk,
+ input ext_clk,
+ input ext_clk_sel,
+
+ input clk,
+ input resetn,
+
+ // Memory mapped I/O signals
+ output [15:0] gpio_out_pad, // Connect to out on gpio pad
+ input [15:0] gpio_in_pad, // Connect to in on gpio pad
+ output [15:0] gpio_mode0_pad, // Connect to dm[0] on gpio pad
+ output [15:0] gpio_mode1_pad, // Connect to dm[2] on gpio pad
+ output [15:0] gpio_outenb_pad, // Connect to oe_n on gpio pad
+ output [15:0] gpio_inenb_pad, // Connect to inp_dis on gpio pad
+
+ // LA signals
+ input [127:0] la_input, // From Mega-Project to cpu
+ output [127:0] la_output, // From CPU to Mega-Project
+ output [127:0] la_oe, // LA output enable (sensitiviy according to tri-state ?)
+
+ output adc0_ena,
+ output adc0_convert,
+ input [9:0] adc0_data,
+ input adc0_done,
+ output adc0_clk,
+ output [1:0] adc0_inputsrc,
+ output adc1_ena,
+ output adc1_convert,
+ output adc1_clk,
+ output [1:0] adc1_inputsrc,
+ input [9:0] adc1_data,
+ input adc1_done,
+
+ output dac_ena,
+ output [9:0] dac_value,
+
+ output analog_out_sel, // Analog output select (DAC or bandgap)
+ output opamp_ena, // Op-amp enable for analog output
+ output opamp_bias_ena, // Op-amp bias enable for analog output
+ output bg_ena, // Bandgap enable
+
+ output comp_ena,
+ output [1:0] comp_ninputsrc,
+ output [1:0] comp_pinputsrc,
+ output rcosc_ena,
+
+ output overtemp_ena,
+ input overtemp,
+ input rcosc_in, // RC oscillator output
+ input xtal_in, // crystal oscillator output
+ input comp_in, // comparator output
+ input spi_sck,
+
+ input [7:0] spi_ro_config,
+ input spi_ro_xtal_ena,
+ input spi_ro_reg_ena,
+ input spi_ro_pll_dco_ena,
+ input [4:0] spi_ro_pll_div,
+ input [2:0] spi_ro_pll_sel,
+ input [25:0] spi_ro_pll_trim,
+
+ input [11:0] spi_ro_mfgr_id,
+ input [7:0] spi_ro_prod_id,
+ input [3:0] spi_ro_mask_rev,
+
+ output ser_tx,
+ input ser_rx,
+
+ // IRQ
+ input irq_pin, // dedicated IRQ pin
+ input irq_spi, // IRQ from standalone SPI
+
+ // trap
+ output trap,
+
+ // Flash memory control (SPI master)
+ output flash_csb,
+ output flash_clk,
+
+ output flash_csb_oeb,
+ output flash_clk_oeb,
+
+ output flash_io0_oeb,
+ output flash_io1_oeb,
+ output flash_io2_oeb,
+ output flash_io3_oeb,
+
+ output flash_csb_ieb,
+ output flash_clk_ieb,
+
+ output flash_io0_ieb,
+ output flash_io1_ieb,
+ output flash_io2_ieb,
+ output flash_io3_ieb,
+
+ output flash_io0_do,
+ output flash_io1_do,
+ output flash_io2_do,
+ output flash_io3_do,
+
+ input flash_io0_di,
+ input flash_io1_di,
+ input flash_io2_di,
+ input flash_io3_di,
+
+ // Crossbar Switch Slaves
+ input [31:0] xbar_dat_i,
+ input xbar_ack_i,
+ output xbar_cyc_o,
+ output xbar_stb_o,
+ output xbar_we_o,
+ output [3:0] xbar_sel_o,
+ output [31:0] xbar_adr_o,
+ output [31:0] xbar_dat_o
+);
+ /* Memory reverted back to 256 words while memory has to be synthesized */
+ parameter integer MEM_WORDS = 256;
+ parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
+ parameter [31:0] PROGADDR_RESET = 32'h 1000_0000;
+ parameter [31:0] PROGADDR_IRQ = 32'h 0000_0000;
+
+ // Slaves Base Addresses
+ parameter RAM_BASE_ADR = 32'h 0000_0000;
+ parameter FLASH_BASE_ADR = 32'h 1000_0000;
+ parameter UART_BASE_ADR = 32'h 2000_0000;
+ parameter GPIO_BASE_ADR = 32'h 2100_0000;
+ parameter LA_BASE_ADR = 32'h 2200_0000;
+ parameter SYS_BASE_ADR = 32'h 2F00_0000;
+ parameter SPI_BASE_ADR = 32'h 2E00_0000;
+ parameter FLASH_CTRL_CFG = 32'h 2D00_0000;
+ parameter XBAR_BASE_ADR = 32'h 8000_0000;
+
+ // UART
+ parameter UART_CLK_DIV = 8'h00;
+ parameter UART_DATA = 8'h04;
+
+ // SOC GPIO
+ parameter GPIO_DATA = 8'h00;
+ parameter GPIO_ENA = 8'h04;
+ parameter GPIO_PU = 8'h08;
+ parameter GPIO_PD = 8'h0c;
+
+ // LDO
+ parameter LA_DATA_0 = 8'h00;
+ parameter LA_DATA_1 = 8'h04;
+ parameter LA_DATA_2 = 8'h08;
+ parameter LA_DATA_3 = 8'h0c;
+ parameter LA_ENA_0 = 8'h10;
+ parameter LA_ENA_1 = 8'h14;
+ parameter LA_ENA_2 = 8'h18;
+ parameter LA_ENA_3 = 8'h1c;
+
+ // SPI-Controlled Registers
+ parameter SPI_CFG = 8'h00;
+ parameter SPI_ENA = 8'h04;
+ parameter SPI_PLL_CFG = 8'h08;
+ parameter SPI_MFGR_ID = 8'h0c;
+ parameter SPI_PROD_ID = 8'h10;
+ parameter SPI_MASK_REV = 8'h14;
+ parameter SPI_PLL_BYPASS = 8'h18;
+
+ // System Control Registers
+ parameter OSC_ENA = 8'h00;
+ parameter OSC_OUT = 8'h04;
+ parameter XTAL_OUT = 8'h08;
+ parameter PLL_OUT = 8'h0c;
+ parameter TRAP_OUT = 8'h10;
+ parameter IRQ7_SRC = 8'h14;
+ parameter IRQ8_SRC = 8'h18;
+ parameter OVERTEMP_ENA = 8'h1c;
+ parameter OVERTEMP_DATA = 8'h20;
+ parameter OVERTEMP_OUT = 8'h24;
+
+ // Wishbone Interconnect
+ localparam ADR_WIDTH = 32;
+ localparam DAT_WIDTH = 32;
+ localparam NUM_SLAVES = 9;
+
+ parameter [NUM_SLAVES*ADR_WIDTH-1: 0] ADR_MASK = {
+ {8'h80, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}},
+ {8'hFF, {ADR_WIDTH-8{1'b0}}}
+ };
+ parameter [NUM_SLAVES*ADR_WIDTH-1: 0] SLAVE_ADR = {
+ {XBAR_BASE_ADR},
+ {SYS_BASE_ADR},
+ {SPI_BASE_ADR},
+ {FLASH_CTRL_CFG},
+ {LA_BASE_ADR},
+ {GPIO_BASE_ADR},
+ {UART_BASE_ADR},
+ {FLASH_BASE_ADR},
+ {RAM_BASE_ADR}
+ };
+
+ // memory-mapped I/O control registers
+ wire [15:0] gpio_pullup; // Intermediate GPIO pullup
+ wire [15:0] gpio_pulldown; // Intermediate GPIO pulldown
+ wire [15:0] gpio_outenb; // Intermediate GPIO out enable (bar)
+ wire [15:0] gpio_out; // Intermediate GPIO output
+
+ wire [15:0] gpio; // GPIO output data
+ wire [15:0] gpio_pu; // GPIO pull-up enable
+ wire [15:0] gpio_pd; // GPIO pull-down enable
+ wire [15:0] gpio_oeb; // GPIO output enable (sense negative)
+
+ wire [1:0] rcosc_output_dest; // RC oscillator output destination
+ wire [1:0] overtemp_dest; // Over-temperature alarm destination
+ wire [1:0] pll_output_dest; // PLL clock output destination
+ wire [1:0] xtal_output_dest; // Crystal oscillator output destination
+ wire [1:0] trap_output_dest; // Trap signal output destination
+ wire [1:0] irq_7_inputsrc; // IRQ 5 source
+ wire [1:0] irq_8_inputsrc; // IRQ 6 source
+
+ // Analgo registers (not-used)
+ reg adc0_ena; // ADC0 enable
+ reg adc0_convert; // ADC0 convert
+ reg [1:0] adc0_clksrc; // ADC0 clock source
+ reg [1:0] adc0_inputsrc; // ADC0 input source
+ reg adc1_ena; // ADC1 enable
+ reg adc1_convert; // ADC1 convert
+ reg [1:0] adc1_clksrc; // ADC1 clock source
+ reg [1:0] adc1_inputsrc; // ADC1 input source
+ reg dac_ena; // DAC enable
+ reg [9:0] dac_value; // DAC output value
+ reg comp_ena; // Comparator enable
+ reg [1:0] comp_ninputsrc; // Comparator negative input source
+ reg [1:0] comp_pinputsrc; // Comparator positive input source
+ reg [1:0] comp_output_dest; // Comparator output destination
+
+ reg analog_out_sel; // Analog output select
+ reg opamp_ena; // Analog output op-amp enable
+ reg opamp_bias_ena; // Analog output op-amp bias enable
+ reg bg_ena; // Bandgap enable
+ wire adc0_clk; // ADC0 clock (multiplexed)
+ wire adc1_clk; // ADC1 clock (multiplexed)
+
+ // ADC clock assignments
+ assign adc0_clk = (adc0_clksrc == 2'b00) ? rcosc_in :
+ (adc0_clksrc == 2'b01) ? spi_sck :
+ (adc0_clksrc == 2'b10) ? xtal_in :
+ ext_clk;
+
+ assign adc1_clk = (adc1_clksrc == 2'b00) ? rcosc_in :
+ (adc1_clksrc == 2'b01) ? spi_sck :
+ (adc1_clksrc == 2'b10) ? xtal_in :
+ ext_clk;
+
+ // GPIO assignments
+ assign gpio_out[0] = (comp_output_dest == 2'b01) ? comp_in : gpio[0];
+ assign gpio_out[1] = (comp_output_dest == 2'b10) ? comp_in : gpio[1];
+ assign gpio_out[2] = (rcosc_output_dest == 2'b01) ? rcosc_in : gpio[2];
+ assign gpio_out[3] = (rcosc_output_dest == 2'b10) ? rcosc_in : gpio[3];
+ assign gpio_out[4] = (rcosc_output_dest == 2'b11) ? rcosc_in : gpio[4];
+ assign gpio_out[5] = (xtal_output_dest == 2'b01) ? xtal_in : gpio[5];
+ assign gpio_out[6] = (xtal_output_dest == 2'b10) ? xtal_in : gpio[6];
+ assign gpio_out[7] = (xtal_output_dest == 2'b11) ? xtal_in : gpio[7];
+ assign gpio_out[8] = (pll_output_dest == 2'b01) ? pll_clk : gpio[8];
+ assign gpio_out[9] = (pll_output_dest == 2'b10) ? pll_clk : gpio[9];
+ assign gpio_out[10] = (pll_output_dest == 2'b11) ? clk : gpio[10];
+ assign gpio_out[11] = (trap_output_dest == 2'b01) ? trap : gpio[11];
+ assign gpio_out[12] = (trap_output_dest == 2'b10) ? trap : gpio[12];
+ assign gpio_out[13] = (trap_output_dest == 2'b11) ? trap : gpio[13];
+ assign gpio_out[14] = (overtemp_dest == 2'b01) ? overtemp : gpio[14];
+ assign gpio_out[15] = (overtemp_dest == 2'b10) ? overtemp : gpio[15];
+
+ assign gpio_outenb[0] = (comp_output_dest == 2'b00) ? gpio_oeb[0] : 1'b0;
+ assign gpio_outenb[1] = (comp_output_dest == 2'b00) ? gpio_oeb[1] : 1'b0;
+ assign gpio_outenb[2] = (rcosc_output_dest == 2'b00) ? gpio_oeb[2] : 1'b0;
+ assign gpio_outenb[3] = (rcosc_output_dest == 2'b00) ? gpio_oeb[3] : 1'b0;
+ assign gpio_outenb[4] = (rcosc_output_dest == 2'b00) ? gpio_oeb[4] : 1'b0;
+ assign gpio_outenb[5] = (xtal_output_dest == 2'b00) ? gpio_oeb[5] : 1'b0;
+ assign gpio_outenb[6] = (xtal_output_dest == 2'b00) ? gpio_oeb[6] : 1'b0;
+ assign gpio_outenb[7] = (xtal_output_dest == 2'b00) ? gpio_oeb[7] : 1'b0;
+ assign gpio_outenb[8] = (pll_output_dest == 2'b00) ? gpio_oeb[8] : 1'b0;
+ assign gpio_outenb[9] = (pll_output_dest == 2'b00) ? gpio_oeb[9] : 1'b0;
+ assign gpio_outenb[10] = (pll_output_dest == 2'b00) ? gpio_oeb[10] : 1'b0;
+ assign gpio_outenb[11] = (trap_output_dest == 2'b00) ? gpio_oeb[11] : 1'b0;
+ assign gpio_outenb[12] = (trap_output_dest == 2'b00) ? gpio_oeb[12] : 1'b0;
+ assign gpio_outenb[13] = (trap_output_dest == 2'b00) ? gpio_oeb[13] : 1'b0;
+ assign gpio_outenb[14] = (overtemp_dest == 2'b00) ? gpio_oeb[14] : 1'b0;
+ assign gpio_outenb[15] = (overtemp_dest == 2'b00) ? gpio_oeb[15] : 1'b0;
+
+ assign gpio_pullup[0] = (comp_output_dest == 2'b00) ? gpio_pu[0] : 1'b0;
+ assign gpio_pullup[1] = (comp_output_dest == 2'b00) ? gpio_pu[1] : 1'b0;
+ assign gpio_pullup[2] = (rcosc_output_dest == 2'b00) ? gpio_pu[2] : 1'b0;
+ assign gpio_pullup[3] = (rcosc_output_dest == 2'b00) ? gpio_pu[3] : 1'b0;
+ assign gpio_pullup[4] = (rcosc_output_dest == 2'b00) ? gpio_pu[4] : 1'b0;
+ assign gpio_pullup[5] = (xtal_output_dest == 2'b00) ? gpio_pu[5] : 1'b0;
+ assign gpio_pullup[6] = (xtal_output_dest == 2'b00) ? gpio_pu[6] : 1'b0;
+ assign gpio_pullup[7] = (xtal_output_dest == 2'b00) ? gpio_pu[7] : 1'b0;
+ assign gpio_pullup[8] = (pll_output_dest == 2'b00) ? gpio_pu[8] : 1'b0;
+ assign gpio_pullup[9] = (pll_output_dest == 2'b00) ? gpio_pu[9] : 1'b0;
+ assign gpio_pullup[10] = (pll_output_dest == 2'b00) ? gpio_pu[10] : 1'b0;
+ assign gpio_pullup[11] = (trap_output_dest == 2'b00) ? gpio_pu[11] : 1'b0;
+ assign gpio_pullup[12] = (trap_output_dest == 2'b00) ? gpio_pu[12] : 1'b0;
+ assign gpio_pullup[13] = (trap_output_dest == 2'b00) ? gpio_pu[13] : 1'b0;
+ assign gpio_pullup[14] = (overtemp_dest == 2'b00) ? gpio_pu[14] : 1'b0;
+ assign gpio_pullup[15] = (overtemp_dest == 2'b00) ? gpio_pu[15] : 1'b0;
+
+ assign gpio_pulldown[0] = (comp_output_dest == 2'b00) ? gpio_pd[0] : 1'b0;
+ assign gpio_pulldown[1] = (comp_output_dest == 2'b00) ? gpio_pd[1] : 1'b0;
+ assign gpio_pulldown[2] = (rcosc_output_dest == 2'b00) ? gpio_pd[2] : 1'b0;
+ assign gpio_pulldown[3] = (rcosc_output_dest == 2'b00) ? gpio_pd[3] : 1'b0;
+ assign gpio_pulldown[4] = (rcosc_output_dest == 2'b00) ? gpio_pd[4] : 1'b0;
+ assign gpio_pulldown[5] = (xtal_output_dest == 2'b00) ? gpio_pd[5] : 1'b0;
+ assign gpio_pulldown[6] = (xtal_output_dest == 2'b00) ? gpio_pd[6] : 1'b0;
+ assign gpio_pulldown[7] = (xtal_output_dest == 2'b00) ? gpio_pd[7] : 1'b0;
+ assign gpio_pulldown[8] = (pll_output_dest == 2'b00) ? gpio_pd[8] : 1'b0;
+ assign gpio_pulldown[9] = (pll_output_dest == 2'b00) ? gpio_pd[9] : 1'b0;
+ assign gpio_pulldown[10] = (pll_output_dest == 2'b00) ? gpio_pd[10] : 1'b0;
+ assign gpio_pulldown[11] = (trap_output_dest == 2'b00) ? gpio_pd[11] : 1'b0;
+ assign gpio_pulldown[12] = (trap_output_dest == 2'b00) ? gpio_pd[12] : 1'b0;
+ assign gpio_pulldown[13] = (trap_output_dest == 2'b00) ? gpio_pd[13] : 1'b0;
+ assign gpio_pulldown[14] = (overtemp_dest == 2'b00) ? gpio_pd[14] : 1'b0;
+ assign gpio_pulldown[15] = (overtemp_dest == 2'b00) ? gpio_pd[15] : 1'b0;
+
+ // Convert GPIO signals to s8 pad signals
+ convert_gpio_sigs convert_gpio_bit [15:0] (
+ .gpio_out(gpio_out),
+ .gpio_outenb(gpio_outenb),
+ .gpio_pu(gpio_pullup),
+ .gpio_pd(gpio_pulldown),
+ .gpio_out_pad(gpio_out_pad),
+ .gpio_outenb_pad(gpio_outenb_pad),
+ .gpio_inenb_pad(gpio_inenb_pad),
+ .gpio_mode1_pad(gpio_mode1_pad),
+ .gpio_mode0_pad(gpio_mode0_pad)
+ );
+
+ reg [31:0] irq;
+ wire irq_7;
+ wire irq_8;
+ wire irq_stall;
+ wire irq_uart;
+
+ assign irq_7 = (irq_7_inputsrc == 2'b01) ? gpio_in_pad[0] :
+ (irq_7_inputsrc == 2'b10) ? gpio_in_pad[1] :
+ (irq_7_inputsrc == 2'b11) ? gpio_in_pad[2] : 1'b0;
+ assign irq_8 = (irq_8_inputsrc == 2'b01) ? gpio_in_pad[3] :
+ (irq_8_inputsrc == 2'b10) ? gpio_in_pad[4] :
+ (irq_8_inputsrc == 2'b11) ? gpio_in_pad[5] : 1'b0;
+
+ assign irq_uart = 0;
+ assign irq_stall = 0;
+
+ always @* begin
+ irq = 0;
+ irq[3] = irq_stall;
+ irq[4] = irq_uart;
+ irq[5] = irq_pin;
+ irq[6] = irq_spi;
+ irq[7] = irq_7;
+ irq[8] = irq_8;
+ irq[9] = comp_output_dest[0] & comp_output_dest[1] & comp_in;
+ irq[10] = overtemp_dest[0] & overtemp_dest[1] & overtemp;
+ end
+
+ // wire mem_valid;
+ // wire mem_instr;
+ // wire mem_ready;
+ // wire [31:0] mem_addr;
+ // wire [31:0] mem_wdata;
+ // wire [3:0] mem_wstrb;
+ // wire [31:0] mem_rdata;
+
+ // wire spimem_ready;
+ // wire [31:0] spimem_rdata;
+
+ // reg ram_ready;
+ // wire [31:0] ram_rdata;
+
+ // assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
+ // assign iomem_wstrb = mem_wstrb;
+ // assign iomem_addr = mem_addr;
+ // assign iomem_wdata = mem_wdata;
+
+ // wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000);
+ // wire [31:0] spimemio_cfgreg_do;
+
+ // wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004);
+ // wire [31:0] simpleuart_reg_div_do;
+
+ // wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008);
+ // wire [31:0] simpleuart_reg_dat_do;
+ // wire simpleuart_reg_dat_wait;
+
+ // Akin to the slave ack ?
+ // assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel ||
+ // simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait);
+
+ // Akin to wb_intercon -- mem_rdata like cpu_dat_i
+ // assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata :
+ // spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do :
+ // simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
+
+ wire wb_clk_i;
+ wire wb_rst_i;
+
+ // Assumption : no syscon module and wb_clk is the clock coming from the chip pin ?
+ assign wb_clk_i = clk;
+ assign wb_rst_i = ~resetn; // Redundant
+
+ // Wishbone Master
+ wire [31:0] cpu_adr_o;
+ wire [31:0] cpu_dat_i;
+ wire [3:0] cpu_sel_o;
+ wire cpu_we_o;
+ wire cpu_cyc_o;
+ wire cpu_stb_o;
+ wire [31:0] cpu_dat_o;
+ wire cpu_ack_i;
+
+ assign xbar_cyc_o = cpu_cyc_o;
+ assign xbar_we_o = cpu_we_o;
+ assign xbar_sel_o = cpu_sel_o;
+ assign xbar_adr_o = cpu_adr_o;
+ assign xbar_dat_o = cpu_dat_o;
+
+ picorv32_wb #(
+ .STACKADDR(STACKADDR),
+ .PROGADDR_RESET(PROGADDR_RESET),
+ .PROGADDR_IRQ(PROGADDR_IRQ),
+ .BARREL_SHIFTER(1),
+ .COMPRESSED_ISA(1),
+ .ENABLE_MUL(1),
+ .ENABLE_DIV(1),
+ .ENABLE_IRQ(1),
+ .ENABLE_IRQ_QREGS(0)
+ ) cpu (
+ .wb_clk_i (wb_clk_i),
+ .wb_rst_i (wb_rst_i),
+ .trap (trap),
+ .irq (irq),
+ .mem_instr(mem_instr),
+ .wbm_adr_o(cpu_adr_o),
+ .wbm_dat_i(cpu_dat_i),
+ .wbm_stb_o(cpu_stb_o),
+ .wbm_ack_i(cpu_ack_i),
+ .wbm_cyc_o(cpu_cyc_o),
+ .wbm_dat_o(cpu_dat_o),
+ .wbm_we_o(cpu_we_o),
+ .wbm_sel_o(cpu_sel_o)
+ );
+
+ // Wishbone Slave SPIMEMIO
+ wire spimemio_flash_stb_i;
+ wire spimemio_flash_ack_o;
+ wire [31:0] spimemio_flash_dat_o;
+
+ wire spimemio_cfg_stb_i;
+ wire spimemio_cfg_ack_o;
+ wire [31:0] spimemio_cfg_dat_o;
+
+ spimemio_wb spimemio (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ // FLash Slave
+ .wb_flash_stb_i(spimemio_flash_stb_i),
+ .wb_flash_ack_o(spimemio_flash_ack_o),
+ .wb_flash_dat_o(spimemio_flash_dat_o),
+
+ // Config Register Slave
+ .wb_cfg_stb_i(spimemio_cfg_stb_i),
+ .wb_cfg_ack_o(spimemio_cfg_ack_o),
+ .wb_cfg_dat_o(spimemio_cfg_dat_o),
+
+ .flash_csb (flash_csb),
+ .flash_clk (flash_clk),
+
+ .flash_csb_oeb (flash_csb_oeb),
+ .flash_clk_oeb (flash_clk_oeb),
+
+ .flash_io0_oeb (flash_io0_oeb),
+ .flash_io1_oeb (flash_io1_oeb),
+ .flash_io2_oeb (flash_io2_oeb),
+ .flash_io3_oeb (flash_io3_oeb),
+
+ .flash_csb_ieb (flash_csb_ieb),
+ .flash_clk_ieb (flash_clk_ieb),
+
+ .flash_io0_ieb (flash_io0_ieb),
+ .flash_io1_ieb (flash_io1_ieb),
+ .flash_io2_ieb (flash_io2_ieb),
+ .flash_io3_ieb (flash_io3_ieb),
+
+ .flash_io0_do (flash_io0_do),
+ .flash_io1_do (flash_io1_do),
+ .flash_io2_do (flash_io2_do),
+ .flash_io3_do (flash_io3_do),
+
+ .flash_io0_di (flash_io0_di),
+ .flash_io1_di (flash_io1_di),
+ .flash_io2_di (flash_io2_di),
+ .flash_io3_di (flash_io3_di)
+ );
+
+ // Wishbone Slave uart
+ wire uart_stb_i;
+ wire uart_ack_o;
+ wire [31:0] uart_dat_o;
+
+ simpleuart_wb #(
+ .BASE_ADR(UART_BASE_ADR),
+ .CLK_DIV(UART_CLK_DIV),
+ .DATA(UART_DATA)
+ ) simpleuart (
+ // Wishbone Interface
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(uart_stb_i),
+ .wb_ack_o(uart_ack_o),
+ .wb_dat_o(uart_dat_o),
+
+ .ser_tx(ser_tx),
+ .ser_rx(ser_rx)
+ );
+
+ // Wishbone Slave GPIO Registers
+ wire gpio_stb_i;
+ wire gpio_ack_o;
+ wire [31:0] gpio_dat_o;
+
+ gpio_wb #(
+ .BASE_ADR(GPIO_BASE_ADR),
+ .GPIO_DATA(GPIO_DATA),
+ .GPIO_ENA(GPIO_ENA),
+ .GPIO_PD(GPIO_PD),
+ .GPIO_PU(GPIO_PU)
+ ) gpio_wb (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(gpio_stb_i),
+ .wb_ack_o(gpio_ack_o),
+ .wb_dat_o(gpio_dat_o),
+ .gpio_in_pad(gpio_in_pad),
+
+ .gpio(gpio),
+ .gpio_oeb(gpio_oeb),
+ .gpio_pu(gpio_pu),
+ .gpio_pd(gpio_pd)
+ );
+
+ // Wishbone SPI System Control Registers (RO)
+ wire spi_sys_stb_i;
+ wire spi_sys_ack_o;
+ wire [31:0] spi_sys_dat_o;
+
+ spi_sysctrl_wb #(
+ .BASE_ADR(SPI_BASE_ADR),
+ .SPI_CFG(SPI_CFG),
+ .SPI_ENA(SPI_ENA),
+ .SPI_PLL_CFG(SPI_PLL_CFG),
+ .SPI_MFGR_ID(SPI_MFGR_ID),
+ .SPI_PROD_ID(SPI_PROD_ID),
+ .SPI_MASK_REV(SPI_MASK_REV),
+ .SPI_PLL_BYPASS(SPI_PLL_BYPASS)
+ ) spi_sysctrl (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(spi_sys_stb_i),
+ .wb_ack_o(spi_sys_ack_o),
+ .wb_dat_o(spi_sys_dat_o),
+
+ .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ?
+ .spi_ro_pll_div(spi_ro_pll_div),
+ .spi_ro_pll_sel(spi_ro_pll_sel),
+ .spi_ro_xtal_ena(spi_ro_xtal_ena),
+ .spi_ro_reg_ena(spi_ro_reg_ena),
+
+ .spi_ro_pll_trim(spi_ro_pll_trim),
+ .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena),
+
+ .spi_ro_mfgr_id(spi_ro_mfgr_id),
+ .spi_ro_prod_id(spi_ro_prod_id),
+ .spi_ro_mask_rev(spi_ro_mask_rev),
+ .pll_bypass(ext_clk_sel)
+ );
+
+ // Wishbone Slave System Control Register
+ wire sys_stb_i;
+ wire sys_ack_o;
+ wire [31:0] sys_dat_o;
+
+ sysctrl_wb #(
+ .BASE_ADR(SYS_BASE_ADR),
+ .OSC_ENA(OSC_ENA),
+ .OSC_OUT(OSC_OUT),
+ .XTAL_OUT(XTAL_OUT),
+ .PLL_OUT(PLL_OUT),
+ .TRAP_OUT(TRAP_OUT),
+ .IRQ7_SRC(IRQ7_SRC),
+ .IRQ8_SRC(IRQ8_SRC),
+ .OVERTEMP_ENA(OVERTEMP_ENA),
+ .OVERTEMP_DATA(OVERTEMP_DATA),
+ .OVERTEMP_OUT(OVERTEMP_OUT)
+ ) sysctrl (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(sys_stb_i),
+ .wb_ack_o(sys_ack_o),
+ .wb_dat_o(sys_dat_o),
+
+ .overtemp(overtemp),
+ .rcosc_ena(rcosc_ena),
+ .rcosc_output_dest(rcosc_output_dest),
+ .xtal_output_dest(xtal_output_dest),
+ .pll_output_dest(pll_output_dest),
+ .trap_output_dest(trap_output_dest),
+ .irq_7_inputsrc(irq_7_inputsrc),
+ .irq_8_inputsrc(irq_8_inputsrc),
+ .overtemp_ena(overtemp_ena),
+ .overtemp_dest(overtemp_dest)
+ );
+
+ // Logic Analyzer
+ wire la_stb_i;
+ wire la_ack_o;
+ wire [31:0] la_dat_o;
+
+ la_wb #(
+ .BASE_ADR(LA_BASE_ADR),
+ .LA_DATA_0(LA_DATA_0),
+ .LA_DATA_1(LA_DATA_1),
+ .LA_DATA_3(LA_DATA_3),
+ .LA_ENA_0(LA_ENA_0),
+ .LA_ENA_1(LA_ENA_1),
+ .LA_ENA_2(LA_ENA_2),
+ .LA_ENA_3(LA_ENA_3)
+ ) la (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(la_stb_i),
+ .wb_ack_o(la_ack_o),
+ .wb_dat_o(la_dat_o),
+
+ .la_data(la_output),
+ .la_ena(la_oe)
+ );
+
+ // Wishbone Slave RAM
+ wire mem_stb_i;
+ wire mem_ack_o;
+ wire [31:0] mem_dat_o;
+
+ mem_wb #(
+ .MEM_WORDS(MEM_WORDS)
+ ) soc_mem (
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+
+ .wb_adr_i(cpu_adr_o),
+ .wb_dat_i(cpu_dat_o),
+ .wb_sel_i(cpu_sel_o),
+ .wb_we_i(cpu_we_o),
+ .wb_cyc_i(cpu_cyc_o),
+
+ .wb_stb_i(mem_stb_i),
+ .wb_ack_o(mem_ack_o),
+ .wb_dat_o(mem_dat_o)
+ );
+
+ // Wishbone intercon logic
+ wb_intercon #(
+ .AW(ADR_WIDTH),
+ .DW(DAT_WIDTH),
+ .NS(NUM_SLAVES),
+ .ADR_MASK(ADR_MASK),
+ .SLAVE_ADR(SLAVE_ADR)
+ ) intercon (
+ // Master Interface
+ .wbm_adr_i(cpu_adr_o),
+ .wbm_stb_i(cpu_stb_o),
+ .wbm_dat_o(cpu_dat_i),
+ .wbm_ack_o(cpu_ack_i),
+
+ // Slaves Interface
+ .wbs_stb_o({ xbar_stb_o, sys_stb_i, spi_sys_stb_i, spimemio_cfg_stb_i, la_stb_i, gpio_stb_i, uart_stb_i, spimemio_flash_stb_i, mem_stb_i }),
+ .wbs_dat_i({ xbar_dat_i, sys_dat_o, spi_sys_dat_o, spimemio_cfg_dat_o, la_dat_o, gpio_dat_o, uart_dat_o, spimemio_flash_dat_o, mem_dat_o }),
+ .wbs_ack_i({ xbar_ack_i, sys_ack_o, spi_sys_ack_o, spimemio_cfg_ack_o, la_ack_o, gpio_ack_o, uart_ack_o, spimemio_flash_ack_o, mem_ack_o })
+ );
+
+ // Akin to ram ack
+ // always @(posedge clk)
+ // ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ adc0_ena <= 0;
+ adc0_convert <= 0;
+ adc0_clksrc <= 0;
+ adc0_inputsrc <= 0;
+ adc1_ena <= 0;
+ adc1_convert <= 0;
+ adc1_clksrc <= 0;
+ adc1_inputsrc <= 0;
+ dac_ena <= 0;
+ dac_value <= 0;
+ comp_ena <= 0;
+ comp_ninputsrc <= 0;
+ comp_pinputsrc <= 0;
+ comp_output_dest <= 0;
+ analog_out_sel <= 0;
+ opamp_ena <= 0;
+ opamp_bias_ena <= 0;
+ bg_ena <= 0;
+ end else begin
+ // iomem_ready <= 0;
+ // if (iomem_valid && !iomem_ready && iomem_addr[31:8] == 24'h030000) begin
+ // iomem_ready <= 1;
+ // end else if (iomem_addr[7:0] == 8'hc0) begin
+ // iomem_rdata <= {31'd0, analog_out_sel};
+ // if (iomem_wstrb[0]) analog_out_sel <= iomem_wdata[0];
+ // end else if (iomem_addr[7:0] == 8'hc4) begin
+ // iomem_rdata <= {31'd0, opamp_bias_ena};
+ // if (iomem_wstrb[0]) opamp_bias_ena <= iomem_wdata[0];
+ // end else if (iomem_addr[7:0] == 8'hc8) begin
+ // iomem_rdata <= {31'd0, opamp_ena};
+ // if (iomem_wstrb[0]) opamp_ena <= iomem_wdata[0];
+ // end else if (iomem_addr[7:0] == 8'hd0) begin
+ // iomem_rdata <= {31'd0, bg_ena};
+ // if (iomem_wstrb[0]) bg_ena <= iomem_wdata[0];
+ // end
+ end
+ end
+
+endmodule
+
+
+/* Convert the standard set of GPIO signals: input, output, output_enb,
+ * pullup, and pulldown into the set needed by the s8 GPIO pads:
+ * input, output, output_enb, input_enb, mode. Note that dm[2] on
+ * thepads is always equal to dm[1] in this setup, so mode is shown as
+ * only a 2-bit signal.
+ *
+ * This module is bit-sliced. Instantiate once for each GPIO pad.
+ */
+
+module convert_gpio_sigs (
+ input gpio_out,
+ input gpio_outenb,
+ input gpio_pu,
+ input gpio_pd,
+ output gpio_out_pad,
+ output gpio_outenb_pad,
+ output gpio_inenb_pad,
+ output gpio_mode1_pad,
+ output gpio_mode0_pad
+);
+
+ assign gpio_out_pad = (gpio_pu == 1'b0 && gpio_pd == 1'b0) ? gpio_out :
+ (gpio_pu == 1'b1) ? 1 : 0;
+
+ assign gpio_outenb_pad = (gpio_outenb == 1'b0) ? 0 :
+ (gpio_pu == 1'b1 || gpio_pd == 1'b1) ? 0 : 1;
+
+ assign gpio_inenb_pad = ~gpio_outenb;
+
+ assign gpio_mode1_pad = ~gpio_outenb_pad;
+ assign gpio_mode0_pad = gpio_outenb;
+
+endmodule
+
+// Implementation note:
+// Replace the following two modules with wrappers for your SRAM cells.
+module openstriVe_soc_regs (
+ input clk, 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
diff --git a/verilog/rtl/picorv32.v b/verilog/rtl/picorv32.v
index af634b4..cbbbb60 100644
--- a/verilog/rtl/picorv32.v
+++ b/verilog/rtl/picorv32.v
@@ -17,6 +17,11 @@
*
*/
+/* verilator lint_off WIDTH */
+/* verilator lint_off PINMISSING */
+/* verilator lint_off CASEOVERLAP */
+/* verilator lint_off CASEINCOMPLETE */
+
`timescale 1 ns / 1 ps
// `default_nettype none
// `define DEBUGNETS
@@ -122,6 +127,8 @@
output reg rvfi_trap,
output reg rvfi_halt,
output reg rvfi_intr,
+ output reg [ 1:0] rvfi_mode,
+ output reg [ 1:0] rvfi_ixl,
output reg [ 4:0] rvfi_rs1_addr,
output reg [ 4:0] rvfi_rs2_addr,
output reg [31:0] rvfi_rs1_rdata,
@@ -135,6 +142,16 @@
output reg [ 3:0] rvfi_mem_wmask,
output reg [31:0] rvfi_mem_rdata,
output reg [31:0] rvfi_mem_wdata,
+
+ output reg [63:0] rvfi_csr_mcycle_rmask,
+ output reg [63:0] rvfi_csr_mcycle_wmask,
+ output reg [63:0] rvfi_csr_mcycle_rdata,
+ output reg [63:0] rvfi_csr_mcycle_wdata,
+
+ output reg [63:0] rvfi_csr_minstret_rmask,
+ output reg [63:0] rvfi_csr_minstret_wmask,
+ output reg [63:0] rvfi_csr_minstret_rdata,
+ output reg [63:0] rvfi_csr_minstret_wdata,
`endif
// Trace Interface
@@ -636,7 +653,7 @@
wire instr_trap;
reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
- reg [31:0] decoded_imm, decoded_imm_uj;
+ reg [31:0] decoded_imm, decoded_imm_j;
reg decoder_trigger;
reg decoder_trigger_q;
reg decoder_pseudo_trigger;
@@ -858,7 +875,7 @@
is_alu_reg_imm <= mem_rdata_latched[6:0] == 7'b0010011;
is_alu_reg_reg <= mem_rdata_latched[6:0] == 7'b0110011;
- { 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});
+ { decoded_imm_j[31:20], decoded_imm_j[10:1], decoded_imm_j[11], decoded_imm_j[19:12], decoded_imm_j[0] } <= $signed({mem_rdata_latched[31:12], 1'b0});
decoded_rd <= mem_rdata_latched[11:7];
decoded_rs1 <= mem_rdata_latched[19:15];
@@ -877,8 +894,8 @@
decoded_rs1 <= 0;
decoded_rs2 <= 0;
- { decoded_imm_uj[31:11], decoded_imm_uj[4], decoded_imm_uj[9:8], decoded_imm_uj[10], decoded_imm_uj[6],
- 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});
+ { decoded_imm_j[31:11], decoded_imm_j[4], decoded_imm_j[9:8], decoded_imm_j[10], decoded_imm_j[6],
+ decoded_imm_j[7], decoded_imm_j[3:1], decoded_imm_j[5], decoded_imm_j[0] } <= $signed({mem_rdata_latched[12:2], 1'b0});
case (mem_rdata_latched[1:0])
2'b00: begin // Quadrant 0
@@ -1099,7 +1116,7 @@
(* parallel_case *)
case (1'b1)
instr_jal:
- decoded_imm <= decoded_imm_uj;
+ decoded_imm <= decoded_imm_j;
|{instr_lui, instr_auipc}:
decoded_imm <= mem_rdata_q[31:12] << 12;
|{instr_jalr, is_lb_lh_lw_lbu_lhu, is_alu_reg_imm}:
@@ -1314,7 +1331,13 @@
`ifndef PICORV32_REGS
always @(posedge clk) begin
if (resetn && cpuregs_write && latched_rd)
+`ifdef PICORV32_TESTBUG_001
+ cpuregs[latched_rd ^ 1] <= cpuregs_wrdata;
+`elsif PICORV32_TESTBUG_002
+ cpuregs[latched_rd] <= cpuregs_wrdata ^ 1;
+`else
cpuregs[latched_rd] <= cpuregs_wrdata;
+`endif
end
always @* begin
@@ -1412,15 +1435,9 @@
next_irq_pending = ENABLE_IRQ ? irq_pending & LATCHED_IRQ : 'bx;
if (ENABLE_IRQ && ENABLE_IRQ_TIMER && timer) begin
- if (timer - 1 == 0)
- next_irq_pending[irq_timer] = 1;
timer <= timer - 1;
end
- if (ENABLE_IRQ) begin
- next_irq_pending = next_irq_pending | irq;
- end
-
decoder_trigger <= mem_do_rinst && mem_done;
decoder_trigger_q <= decoder_trigger;
decoder_pseudo_trigger <= 0;
@@ -1544,7 +1561,7 @@
end
if (instr_jal) begin
mem_do_rinst <= 1;
- reg_next_pc <= current_pc + decoded_imm_uj;
+ reg_next_pc <= current_pc + decoded_imm_j;
latched_branch <= 1;
end else begin
mem_do_rinst <= 0;
@@ -1890,6 +1907,13 @@
end
endcase
+ if (ENABLE_IRQ) begin
+ next_irq_pending = next_irq_pending | irq;
+ if(ENABLE_IRQ_TIMER && timer)
+ if (timer - 1 == 0)
+ next_irq_pending[irq_timer] = 1;
+ end
+
if (CATCH_MISALIGN && resetn && (mem_do_rdata || mem_do_wdata)) begin
if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin
`debug($display("MISALIGNED WORD: 0x%08x", reg_op1);)
@@ -1962,6 +1986,8 @@
rvfi_trap <= trap;
rvfi_halt <= trap;
rvfi_intr <= dbg_irq_enter;
+ rvfi_mode <= 3;
+ rvfi_ixl <= 1;
if (!resetn) begin
dbg_irq_call <= 0;
@@ -1981,8 +2007,16 @@
rvfi_rd_wdata <= 0;
end else
if (cpuregs_write && !irq_state) begin
+`ifdef PICORV32_TESTBUG_003
+ rvfi_rd_addr <= latched_rd ^ 1;
+`else
rvfi_rd_addr <= latched_rd;
+`endif
+`ifdef PICORV32_TESTBUG_004
+ rvfi_rd_wdata <= latched_rd ? cpuregs_wrdata ^ 1 : 0;
+`else
rvfi_rd_wdata <= latched_rd ? cpuregs_wrdata : 0;
+`endif
end else
if (rvfi_valid) begin
rvfi_rd_addr <= 0;
@@ -2023,7 +2057,40 @@
end
always @* begin
+`ifdef PICORV32_TESTBUG_005
+ rvfi_pc_wdata = (dbg_irq_call ? dbg_irq_ret : dbg_insn_addr) ^ 4;
+`else
rvfi_pc_wdata = dbg_irq_call ? dbg_irq_ret : dbg_insn_addr;
+`endif
+
+ rvfi_csr_mcycle_rmask = 0;
+ rvfi_csr_mcycle_wmask = 0;
+ rvfi_csr_mcycle_rdata = 0;
+ rvfi_csr_mcycle_wdata = 0;
+
+ rvfi_csr_minstret_rmask = 0;
+ rvfi_csr_minstret_wmask = 0;
+ rvfi_csr_minstret_rdata = 0;
+ rvfi_csr_minstret_wdata = 0;
+
+ if (rvfi_valid && rvfi_insn[6:0] == 7'b 1110011 && rvfi_insn[13:12] == 3'b010) begin
+ if (rvfi_insn[31:20] == 12'h C00) begin
+ rvfi_csr_mcycle_rmask = 64'h 0000_0000_FFFF_FFFF;
+ rvfi_csr_mcycle_rdata = {32'h 0000_0000, rvfi_rd_wdata};
+ end
+ if (rvfi_insn[31:20] == 12'h C80) begin
+ rvfi_csr_mcycle_rmask = 64'h FFFF_FFFF_0000_0000;
+ rvfi_csr_mcycle_rdata = {rvfi_rd_wdata, 32'h 0000_0000};
+ end
+ if (rvfi_insn[31:20] == 12'h C02) begin
+ rvfi_csr_minstret_rmask = 64'h 0000_0000_FFFF_FFFF;
+ rvfi_csr_minstret_rdata = {32'h 0000_0000, rvfi_rd_wdata};
+ end
+ if (rvfi_insn[31:20] == 12'h C82) begin
+ rvfi_csr_minstret_rmask = 64'h FFFF_FFFF_0000_0000;
+ rvfi_csr_minstret_rdata = {rvfi_rd_wdata, 32'h 0000_0000};
+ end
+ end
end
`endif
@@ -2913,7 +2980,7 @@
.trace_valid(trace_valid),
.trace_data (trace_data)
);
-
+ // Wishbone Controller
localparam IDLE = 2'b00;
localparam WBSTART = 2'b01;
localparam WBEND = 2'b10;
diff --git a/verilog/rtl/ring_osc2x13.v b/verilog/rtl/ring_osc2x13.v
index 4363c00..58a01af 100644
--- a/verilog/rtl/ring_osc2x13.v
+++ b/verilog/rtl/ring_osc2x13.v
@@ -10,40 +10,40 @@
wire d0, d1, d2;
- sky130_fd_sc_hd__clkbuf_2 delaybuf0 (
+ scs8hd_clkbuf_2 delaybuf0 (
.A(in),
.X(ts)
);
- sky130_fd_sc_hd__clkbuf_1 delaybuf1 (
+ scs8hd_clkbuf_1 delaybuf1 (
.A(ts),
.X(d0)
);
- sky130_fd_sc_hd__einvp_2 delayen1 (
+ scs8hd_einvp_2 delayen1 (
.A(d0),
.TE(trim[1]),
.Z(d1)
);
- sky130_fd_sc_hd__einvn_4 delayenb1 (
+ scs8hd_einvn_4 delayenb1 (
.A(ts),
.TEB(trim[1]),
.Z(d1)
);
- sky130_fd_sc_hd__clkinv_1 delayint0 (
+ scs8hd_clkinv_1 delayint0 (
.A(d1),
.Y(d2)
);
- sky130_fd_sc_hd__einvp_2 delayen0 (
+ scs8hd_einvp_2 delayen0 (
.A(d2),
.TE(trim[0]),
.Z(out)
);
- sky130_fd_sc_hd__einvn_8 delayenb0 (
+ scs8hd_einvn_8 delayenb0 (
.A(ts),
.TEB(trim[0]),
.Z(out)
@@ -59,53 +59,53 @@
wire d0, d1, d2, ctrl0, one;
- sky130_fd_sc_hd__clkbuf_1 delaybuf0 (
+ scs8hd_clkbuf_1 delaybuf0 (
.A(in),
.X(d0)
);
- sky130_fd_sc_hd__einvp_2 delayen1 (
+ scs8hd_einvp_2 delayen1 (
.A(d0),
.TE(trim[1]),
.Z(d1)
);
- sky130_fd_sc_hd__einvn_4 delayenb1 (
+ scs8hd_einvn_4 delayenb1 (
.A(in),
.TEB(trim[1]),
.Z(d1)
);
- sky130_fd_sc_hd__clkinv_1 delayint0 (
+ scs8hd_clkinv_1 delayint0 (
.A(d1),
.Y(d2)
);
- sky130_fd_sc_hd__einvp_2 delayen0 (
+ scs8hd_einvp_2 delayen0 (
.A(d2),
.TE(trim[0]),
.Z(out)
);
- sky130_fd_sc_hd__einvn_8 delayenb0 (
+ scs8hd_einvn_8 delayenb0 (
.A(in),
.TEB(ctrl0),
.Z(out)
);
- sky130_fd_sc_hd__einvp_1 reseten0 (
+ scs8hd_einvp_1 reseten0 (
.A(one),
.TE(reset),
.Z(out)
);
- sky130_fd_sc_hd__or2_2 ctrlen0 (
+ scs8hd_or2_2 ctrlen0 (
.A(reset),
.B(trim[0]),
.X(ctrl0)
);
- sky130_fd_sc_hd__conb_1 const1 (
+ scs8hd_conb_1 const1 (
.HI(one),
.LO()
);
@@ -159,19 +159,19 @@
// Buffered outputs a 0 and 90 degrees phase (approximately)
- sky130_fd_sc_hd__clkinv_2 ibufp00 (
+ scs8hd_clkinv_2 ibufp00 (
.A(d[0]),
.Y(c[0])
);
- sky130_fd_sc_hd__clkinv_8 ibufp01 (
+ scs8hd_clkinv_8 ibufp01 (
.A(c[0]),
.Y(clockp[0])
);
- sky130_fd_sc_hd__clkinv_2 ibufp10 (
+ scs8hd_clkinv_2 ibufp10 (
.A(d[6]),
.Y(c[1])
);
- sky130_fd_sc_hd__clkinv_8 ibufp11 (
+ scs8hd_clkinv_8 ibufp11 (
.A(c[1]),
.Y(clockp[1])
);
diff --git a/verilog/rtl/simpleuart.v b/verilog/rtl/simpleuart.v
index 50808cb..51e95c7 100644
--- a/verilog/rtl/simpleuart.v
+++ b/verilog/rtl/simpleuart.v
@@ -17,121 +17,180 @@
*
*/
-module simpleuart (
- input clk,
- input resetn,
+module simpleuart_wb # (
+ parameter BASE_ADR = 32'h 2000_0000,
+ parameter CLK_DIV = 8'h00,
+ parameter DATA = 8'h04
+) (
+ input wb_clk_i,
+ input wb_rst_i,
- output ser_tx,
- input ser_rx,
+ input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?)
+ input [31:0] wb_dat_i,
+ input [3:0] wb_sel_i,
+ input wb_we_i,
+ input wb_cyc_i,
+ input wb_stb_i,
- input [3:0] reg_div_we,
- input [31:0] reg_div_di,
- output [31:0] reg_div_do,
+ output wb_ack_o,
+ output [31:0] wb_dat_o,
- input reg_dat_we,
- input reg_dat_re,
- input [31:0] reg_dat_di,
- output [31:0] reg_dat_do,
- output reg_dat_wait
+ output ser_tx,
+ input ser_rx
+
);
- reg [31:0] cfg_divider;
+ wire [31:0] simpleuart_reg_div_do;
+ wire [31:0] simpleuart_reg_dat_do;
- reg [3:0] recv_state;
- reg [31:0] recv_divcnt;
- reg [7:0] recv_pattern;
- reg [7:0] recv_buf_data;
- reg recv_buf_valid;
+ wire resetn = ~wb_rst_i;
+ wire valid = wb_stb_i && wb_cyc_i;
+ wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
+ wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
- reg [9:0] send_pattern;
- reg [3:0] send_bitcnt;
- reg [31:0] send_divcnt;
- reg send_dummy;
+ wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; // simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000), // sel: depends on address buss
+ wire reg_dat_we = simpleuart_reg_dat_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; // simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0
- assign reg_div_do = cfg_divider;
+ wire [31:0] mem_wdata = wb_dat_i;
+ wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
- assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
- assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
+ assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do: simpleuart_reg_dat_do;
+ assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel) && (!reg_dat_wait);
+
+ simpleuart simpleuart (
+ .clk (wb_clk_i),
+ .resetn (resetn),
- always @(posedge clk) begin
- if (!resetn) begin
- cfg_divider <= 1;
- end else begin
- if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
- if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
- if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
- if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
- end
- end
+ .ser_tx (ser_tx),
+ .ser_rx (ser_rx),
- always @(posedge clk) begin
- if (!resetn) begin
- recv_state <= 0;
- recv_divcnt <= 0;
- recv_pattern <= 0;
- recv_buf_data <= 0;
- recv_buf_valid <= 0;
- end else begin
- recv_divcnt <= recv_divcnt + 1;
- if (reg_dat_re)
- recv_buf_valid <= 0;
- case (recv_state)
- 0: begin
- if (!ser_rx)
- recv_state <= 1;
- recv_divcnt <= 0;
- end
- 1: begin
- if (2*recv_divcnt > cfg_divider) begin
- recv_state <= 2;
- recv_divcnt <= 0;
- end
- end
- 10: begin
- if (recv_divcnt > cfg_divider) begin
- recv_buf_data <= recv_pattern;
- recv_buf_valid <= 1;
- recv_state <= 0;
- end
- end
- default: begin
- if (recv_divcnt > cfg_divider) begin
- recv_pattern <= {ser_rx, recv_pattern[7:1]};
- recv_state <= recv_state + 1;
- recv_divcnt <= 0;
- end
- end
- endcase
- end
- end
+ .reg_div_we (reg_div_we),
+ .reg_div_di (mem_wdata),
+ .reg_div_do (simpleuart_reg_div_do),
- assign ser_tx = send_pattern[0];
+ .reg_dat_we (reg_dat_we),
+ .reg_dat_re (reg_dat_re),
+ .reg_dat_di (mem_wdata),
+ .reg_dat_do (simpleuart_reg_dat_do),
+ .reg_dat_wait(reg_dat_wait)
+ );
- always @(posedge clk) begin
- if (reg_div_we)
- send_dummy <= 1;
- send_divcnt <= send_divcnt + 1;
- if (!resetn) begin
- send_pattern <= ~0;
- send_bitcnt <= 0;
- send_divcnt <= 0;
- send_dummy <= 1;
- end else begin
- if (send_dummy && !send_bitcnt) begin
- send_pattern <= ~0;
- send_bitcnt <= 15;
- send_divcnt <= 0;
- send_dummy <= 0;
- end else
- if (reg_dat_we && !send_bitcnt) begin
- send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
- send_bitcnt <= 10;
- send_divcnt <= 0;
- end else
- if (send_divcnt > cfg_divider && send_bitcnt) begin
- send_pattern <= {1'b1, send_pattern[9:1]};
- send_bitcnt <= send_bitcnt - 1;
- send_divcnt <= 0;
- end
- end
- end
+endmodule
+
+module simpleuart (
+ input clk,
+ input resetn,
+
+ output ser_tx,
+ input ser_rx,
+
+ input [3:0] reg_div_we,
+ input [31:0] reg_div_di,
+ output [31:0] reg_div_do,
+
+ input reg_dat_we,
+ input reg_dat_re,
+ input [31:0] reg_dat_di,
+ output [31:0] reg_dat_do,
+ output reg_dat_wait
+);
+ reg [31:0] cfg_divider;
+
+ reg [3:0] recv_state;
+ reg [31:0] recv_divcnt;
+ reg [7:0] recv_pattern;
+ reg [7:0] recv_buf_data;
+ reg recv_buf_valid;
+
+ reg [9:0] send_pattern;
+ reg [3:0] send_bitcnt;
+ reg [31:0] send_divcnt;
+ reg send_dummy;
+
+ assign reg_div_do = cfg_divider;
+
+ assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
+ assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ cfg_divider <= 1;
+ end else begin
+ if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
+ if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
+ if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
+ if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
+ end
+ end
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ recv_state <= 0;
+ recv_divcnt <= 0;
+ recv_pattern <= 0;
+ recv_buf_data <= 0;
+ recv_buf_valid <= 0;
+ end else begin
+ recv_divcnt <= recv_divcnt + 1;
+ if (reg_dat_re)
+ recv_buf_valid <= 0;
+ case (recv_state)
+ 0: begin
+ if (!ser_rx)
+ recv_state <= 1;
+ recv_divcnt <= 0;
+ end
+ 1: begin
+ if (2*recv_divcnt > cfg_divider) begin
+ recv_state <= 2;
+ recv_divcnt <= 0;
+ end
+ end
+ 10: begin
+ if (recv_divcnt > cfg_divider) begin
+ recv_buf_data <= recv_pattern;
+ recv_buf_valid <= 1;
+ recv_state <= 0;
+ end
+ end
+ default: begin
+ if (recv_divcnt > cfg_divider) begin
+ recv_pattern <= {ser_rx, recv_pattern[7:1]};
+ recv_state <= recv_state + 1;
+ recv_divcnt <= 0;
+ end
+ end
+ endcase
+ end
+ end
+
+ assign ser_tx = send_pattern[0];
+
+ always @(posedge clk) begin
+ if (reg_div_we)
+ send_dummy <= 1;
+ send_divcnt <= send_divcnt + 1;
+ if (!resetn) begin
+ send_pattern <= ~0;
+ send_bitcnt <= 0;
+ send_divcnt <= 0;
+ send_dummy <= 1;
+ end else begin
+ if (send_dummy && !send_bitcnt) begin
+ send_pattern <= ~0;
+ send_bitcnt <= 15;
+ send_divcnt <= 0;
+ send_dummy <= 0;
+ end else
+ if (reg_dat_we && !send_bitcnt) begin
+ send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
+ send_bitcnt <= 10;
+ send_divcnt <= 0;
+ end else
+ if (send_divcnt > cfg_divider && send_bitcnt) begin
+ send_pattern <= {1'b1, send_pattern[9:1]};
+ send_bitcnt <= send_bitcnt - 1;
+ send_divcnt <= 0;
+ end
+ end
+ end
endmodule
diff --git a/verilog/rtl/spi_slave.v b/verilog/rtl/spi_slave.v
index 50a6520..16a1923 100644
--- a/verilog/rtl/spi_slave.v
+++ b/verilog/rtl/spi_slave.v
@@ -83,97 +83,97 @@
// Readback data is captured on the falling edge of SCK so that
// it is guaranteed valid at the next rising edge.
always @(negedge SCK or posedge CSB) begin
- if (CSB == 1'b1) begin
- wrstb <= 1'b0;
- ldata <= 8'b00000000;
- sdoenb <= 1'b1;
+ if (CSB == 1'b1) begin
+ wrstb <= 1'b0;
+ ldata <= 8'b00000000;
+ sdoenb <= 1'b1;
end else begin
- // After CSB low, 1st SCK starts command
+ // After CSB low, 1st SCK starts command
- if (state == `DATA) begin
- if (readmode == 1'b1) begin
- sdoenb <= 1'b0;
- if (count == 3'b000) begin
- ldata <= idata;
- end else begin
- ldata <= {ldata[6:0], 1'b0}; // Shift out
- end
- end else begin
- sdoenb <= 1'b1;
- end
+ if (state == `DATA) begin
+ if (readmode == 1'b1) begin
+ sdoenb <= 1'b0;
+ if (count == 3'b000) begin
+ ldata <= idata;
+ end else begin
+ ldata <= {ldata[6:0], 1'b0}; // Shift out
+ end
+ end else begin
+ sdoenb <= 1'b1;
+ end
- // Apply write strobe on SCK negative edge on the next-to-last
- // data bit so that it updates data on the rising edge of SCK
- // on the last data bit.
+ // Apply write strobe on SCK negative edge on the next-to-last
+ // data bit so that it updates data on the rising edge of SCK
+ // on the last data bit.
- if (count == 3'b111) begin
- if (writemode == 1'b1) begin
- wrstb <= 1'b1;
- end
- end else begin
- wrstb <= 1'b0;
- end
- end else begin
- wrstb <= 1'b0;
- sdoenb <= 1'b1;
- end // ! state `DATA
- end // ! CSB
+ if (count == 3'b111) begin
+ if (writemode == 1'b1) begin
+ wrstb <= 1'b1;
+ end
+ end else begin
+ wrstb <= 1'b0;
+ end
+ end else begin
+ wrstb <= 1'b0;
+ sdoenb <= 1'b1;
+ end // ! state `DATA
+ end // ! CSB
end // always @ ~SCK
always @(posedge SCK or posedge CSB) begin
- if (CSB == 1'b1) begin
- // Default state on reset
- addr <= 8'h00;
- rdstb <= 1'b0;
- predata <= 7'b0000000;
- state <= `COMMAND;
- count <= 3'b000;
- readmode <= 1'b0;
- writemode <= 1'b0;
- fixed <= 3'b000;
+ if (CSB == 1'b1) begin
+ // Default state on reset
+ addr <= 8'h00;
+ rdstb <= 1'b0;
+ predata <= 7'b0000000;
+ state <= `COMMAND;
+ count <= 3'b000;
+ readmode <= 1'b0;
+ writemode <= 1'b0;
+ fixed <= 3'b000;
end else begin
- // After CSB low, 1st SCK starts command
- if (state == `COMMAND) begin
- rdstb <= 1'b0;
- count <= count + 1;
- if (count == 3'b000) begin
- writemode <= SDI;
- end else if (count == 3'b001) begin
- readmode <= SDI;
- end else if (count < 3'b101) begin
- fixed <= {fixed[1:0], SDI};
- end else if (count == 3'b111) begin
- state <= `ADDRESS;
- end
- end else if (state == `ADDRESS) begin
- count <= count + 1;
- addr <= {addr[6:0], SDI};
- if (count == 3'b111) begin
- if (readmode == 1'b1) begin
- rdstb <= 1'b1;
- end
- state <= `DATA;
- end else begin
- rdstb <= 1'b0;
- end
- end else if (state == `DATA) begin
- predata <= {predata[6:0], SDI};
- count <= count + 1;
- if (count == 3'b111) begin
- if (fixed == 3'b001) begin
- state <= `COMMAND;
- end else if (fixed != 3'b000) begin
- fixed <= fixed - 1;
- addr <= addr + 1; // Auto increment address (fixed)
- end else begin
- addr <= addr + 1; // Auto increment address (streaming)
- end
- end else begin
- rdstb <= 1'b0;
- end
- end // ! state `DATA
- end // ! CSB
+ // After CSB low, 1st SCK starts command
+ if (state == `COMMAND) begin
+ rdstb <= 1'b0;
+ count <= count + 1;
+ if (count == 3'b000) begin
+ writemode <= SDI;
+ end else if (count == 3'b001) begin
+ readmode <= SDI;
+ end else if (count < 3'b101) begin
+ fixed <= {fixed[1:0], SDI};
+ end else if (count == 3'b111) begin
+ state <= `ADDRESS;
+ end
+ end else if (state == `ADDRESS) begin
+ count <= count + 1;
+ addr <= {addr[6:0], SDI};
+ if (count == 3'b111) begin
+ if (readmode == 1'b1) begin
+ rdstb <= 1'b1;
+ end
+ state <= `DATA;
+ end else begin
+ rdstb <= 1'b0;
+ end
+ end else if (state == `DATA) begin
+ predata <= {predata[6:0], SDI};
+ count <= count + 1;
+ if (count == 3'b111) begin
+ if (fixed == 3'b001) begin
+ state <= `COMMAND;
+ end else if (fixed != 3'b000) begin
+ fixed <= fixed - 1;
+ addr <= addr + 1; // Auto increment address (fixed)
+ end else begin
+ addr <= addr + 1; // Auto increment address (streaming)
+ end
+ end else begin
+ rdstb <= 1'b0;
+ end
+ end // ! state `DATA
+ end // ! CSB
end // always @ SCK
endmodule // spi_slave
diff --git a/verilog/rtl/spi_sysctrl.v b/verilog/rtl/spi_sysctrl.v
new file mode 100644
index 0000000..7a34a7f
--- /dev/null
+++ b/verilog/rtl/spi_sysctrl.v
@@ -0,0 +1,182 @@
+module spi_sysctrl_wb #(
+ parameter BASE_ADR = 32'h2E00_0000,
+ parameter SPI_CFG = 8'h00,
+ parameter SPI_ENA = 8'h04,
+ parameter SPI_PLL_CFG = 8'h08,
+ parameter SPI_MFGR_ID = 8'h0c,
+ parameter SPI_PROD_ID = 8'h10,
+ parameter SPI_MASK_REV = 8'h14,
+ parameter SPI_PLL_BYPASS = 8'h18
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_dat_i,
+ input [31:0] wb_adr_i,
+ input [3:0] wb_sel_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+ input wb_we_i,
+
+ output [31:0] wb_dat_o,
+ output wb_ack_o,
+
+ // Read-Only HKSPI Registers
+ input [7:0] spi_ro_config, // (verify) wire input to the core not connected to HKSPI, what should it be connected to ?
+
+ input [4:0] spi_ro_pll_div,
+ input [2:0] spi_ro_pll_sel,
+ input spi_ro_xtal_ena,
+ input spi_ro_reg_ena,
+
+ input [25:0] spi_ro_pll_trim,
+ input spi_ro_pll_dco_ena,
+
+ input [11:0] spi_ro_mfgr_id,
+ input [7:0] spi_ro_prod_id,
+ input [3:0] spi_ro_mask_rev,
+ input pll_bypass
+);
+
+ wire resetn;
+ wire valid;
+ wire ready;
+ wire [3:0] iomem_we;
+
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_stb_i && wb_cyc_i;
+
+ assign iomem_we = wb_sel_i & {4{wb_we_i}};
+ assign wb_ack_o = ready;
+
+ spi_sysctrl #(
+ .BASE_ADR(BASE_ADR),
+ .SPI_CFG(SPI_CFG),
+ .SPI_ENA(SPI_ENA),
+ .SPI_PLL_CFG(SPI_PLL_CFG),
+ .SPI_MFGR_ID(SPI_MFGR_ID),
+ .SPI_PROD_ID(SPI_PROD_ID),
+ .SPI_MASK_REV(SPI_MASK_REV),
+ .SPI_PLL_BYPASS(SPI_PLL_BYPASS)
+ ) spi_sysctrl (
+ .clk(wb_clk_i),
+ .resetn(resetn),
+
+ .iomem_addr(wb_adr_i),
+ .iomem_valid(valid),
+ .iomem_wstrb(iomem_we),
+ .iomem_wdata(wb_dat_i),
+ .iomem_rdata(wb_dat_o),
+ .iomem_ready(ready),
+
+ .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ?
+ .spi_ro_pll_div(spi_ro_pll_div),
+ .spi_ro_pll_sel(spi_ro_pll_sel),
+ .spi_ro_xtal_ena(spi_ro_xtal_ena),
+ .spi_ro_reg_ena(spi_ro_reg_ena),
+
+ .spi_ro_pll_trim(spi_ro_pll_trim),
+ .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena),
+
+ .spi_ro_mfgr_id(spi_ro_mfgr_id),
+ .spi_ro_prod_id(spi_ro_prod_id),
+ .spi_ro_mask_rev(spi_ro_mask_rev),
+ .pll_bypass(pll_bypass)
+ );
+
+endmodule
+
+module spi_sysctrl #(
+ parameter BASE_ADR = 32'h2300_0000,
+ parameter SPI_CFG = 8'h00,
+ parameter SPI_ENA = 8'h04,
+ parameter SPI_PLL_CFG = 8'h08,
+ parameter SPI_MFGR_ID = 8'h0c,
+ parameter SPI_PROD_ID = 8'h10,
+ parameter SPI_MASK_REV = 8'h14,
+ parameter SPI_PLL_BYPASS = 8'h18
+) (
+ input clk,
+ input resetn,
+
+ input [31:0] iomem_addr,
+ input iomem_valid,
+ input [3:0] iomem_wstrb,
+ input [31:0] iomem_wdata,
+ output reg [31:0] iomem_rdata,
+ output reg iomem_ready,
+
+ input [7:0] spi_ro_config, // (verify) wire input to the core not connected to HKSPI, what should it be connected to ?
+
+ input [4:0] spi_ro_pll_div,
+ input [2:0] spi_ro_pll_sel,
+ input spi_ro_xtal_ena,
+ input spi_ro_reg_ena,
+
+ input [25:0] spi_ro_pll_trim,
+ input spi_ro_pll_dco_ena,
+
+ input [11:0] spi_ro_mfgr_id,
+ input [7:0] spi_ro_prod_id,
+ input [3:0] spi_ro_mask_rev,
+ input pll_bypass
+);
+ // Read-only Registers
+
+ wire spi_cfg_sel;
+ wire spi_ena_sel;
+ wire pll_cfg_sel;
+ wire spi_mfgr_sel;
+ wire spi_prod_sel;
+ wire spi_maskrev_sel;
+ wire pll_bypass_sel;
+
+
+ assign spi_cfg_sel = (iomem_addr[7:0] == SPI_CFG);
+ assign spi_ena_sel = (iomem_addr[7:0] == SPI_ENA);
+ assign pll_cfg_sel = (iomem_addr[7:0] == SPI_PLL_CFG);
+ assign spi_mfgr_sel = (iomem_addr[7:0] == SPI_MFGR_ID);
+ assign spi_prod_sel = (iomem_addr[7:0] == SPI_PROD_ID);
+
+ assign spi_maskrev_sel = (iomem_addr[7:0] == SPI_MASK_REV);
+ assign pll_bypass_sel = (iomem_addr[7:0] == SPI_PLL_BYPASS);
+
+ always @(posedge clk) begin
+ iomem_ready <= 0;
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ iomem_ready <= 1;
+ if (spi_cfg_sel) begin
+ iomem_rdata <= {24'd0, spi_ro_config};
+
+ end else if (spi_ena_sel) begin
+ iomem_rdata <= {
+ 22'd0,
+ spi_ro_pll_div,
+ spi_ro_pll_sel,
+ spi_ro_xtal_ena,
+ spi_ro_reg_ena
+ };
+
+ end else if (pll_cfg_sel) begin
+ iomem_rdata <= {
+ 5'd0,
+ spi_ro_pll_trim,
+ spi_ro_pll_dco_ena
+ };
+
+ end else if (spi_mfgr_sel) begin
+ iomem_rdata <= {20'd0, spi_ro_mfgr_id};
+
+ end else if (spi_prod_sel) begin
+ iomem_rdata <= {24'd0, spi_ro_prod_id};
+
+ end else if (spi_maskrev_sel) begin
+ iomem_rdata <= {28'd0, spi_ro_mask_rev};
+
+ end else if (pll_bypass_sel) begin
+ iomem_rdata <= {31'd0, pll_bypass};
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/spiflash.v b/verilog/rtl/spiflash.v
deleted file mode 100755
index 0b236e0..0000000
--- a/verilog/rtl/spiflash.v
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * PicoSoC - A simple example SoC using PicoRV32
- *
- * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
- *
- * 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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-`timescale 1 ns / 1 ps
-
-//
-// Simple SPI flash simulation model
-//
-// This model samples io input signals 1ns before the SPI clock edge and
-// updates output signals 1ns after the SPI clock edge.
-//
-// Supported commands:
-// AB, B9, FF, 03, BB, EB, ED
-//
-// Well written SPI flash data sheets:
-// Cypress S25FL064L http://www.cypress.com/file/316661/download
-// Cypress S25FL128L http://www.cypress.com/file/316171/download
-//
-
-module spiflash #(
- parameter FILENAME = "firmware.hex"
-)(
- input csb,
- input clk,
- inout io0, // MOSI
- inout io1, // MISO
- inout io2,
- inout io3
-);
- localparam verbose = 0;
- localparam integer latency = 8;
-
- reg [7:0] buffer;
- integer bitcount = 0;
- integer bytecount = 0;
- integer dummycount = 0;
-
- reg [7:0] spi_cmd;
- reg [7:0] xip_cmd = 0;
- reg [23:0] spi_addr;
-
- reg [7:0] spi_in;
- reg [7:0] spi_out;
- reg spi_io_vld;
-
- reg powered_up = 0;
-
- localparam [3:0] mode_spi = 1;
- localparam [3:0] mode_dspi_rd = 2;
- localparam [3:0] mode_dspi_wr = 3;
- localparam [3:0] mode_qspi_rd = 4;
- localparam [3:0] mode_qspi_wr = 5;
- localparam [3:0] mode_qspi_ddr_rd = 6;
- localparam [3:0] mode_qspi_ddr_wr = 7;
-
- reg [3:0] mode = 0;
- reg [3:0] next_mode = 0;
-
- reg io0_oe = 0;
- reg io1_oe = 0;
- reg io2_oe = 0;
- reg io3_oe = 0;
-
- reg io0_dout = 0;
- reg io1_dout = 0;
- reg io2_dout = 0;
- reg io3_dout = 0;
-
- assign #1 io0 = io0_oe ? io0_dout : 1'bz;
- assign #1 io1 = io1_oe ? io1_dout : 1'bz;
- assign #1 io2 = io2_oe ? io2_dout : 1'bz;
- assign #1 io3 = io3_oe ? io3_dout : 1'bz;
-
- wire io0_delayed;
- wire io1_delayed;
- wire io2_delayed;
- wire io3_delayed;
-
- assign #1 io0_delayed = io0;
- assign #1 io1_delayed = io1;
- assign #1 io2_delayed = io2;
- assign #1 io3_delayed = io3;
-
- // 16 MB (128Mb) Flash
- reg [7:0] memory [0:16*1024*1024-1];
-
- initial begin
- $display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
- memory[1048576], memory[1048577], memory[1048578],
- memory[1048579], memory[1048580]);
- $display("Reading %s", FILENAME);
- $readmemh(FILENAME, memory);
- $display("%s loaded into memory", FILENAME);
- $display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
- memory[1048576], memory[1048577], memory[1048578],
- memory[1048579], memory[1048580]);
- end
-
- task spi_action;
- begin
- spi_in = buffer;
-
- if (bytecount == 1) begin
- spi_cmd = buffer;
-
- if (spi_cmd == 8'h ab)
- powered_up = 1;
-
- if (spi_cmd == 8'h b9)
- powered_up = 0;
-
- if (spi_cmd == 8'h ff)
- xip_cmd = 0;
- end
-
- if (powered_up && spi_cmd == 'h 03) begin
- if (bytecount == 2)
- spi_addr[23:16] = buffer;
-
- if (bytecount == 3)
- spi_addr[15:8] = buffer;
-
- if (bytecount == 4)
- spi_addr[7:0] = buffer;
-
- if (bytecount >= 4) begin
- buffer = memory[spi_addr];
- spi_addr = spi_addr + 1;
- end
- end
-
- if (powered_up && spi_cmd == 'h bb) begin
- if (bytecount == 1)
- mode = mode_dspi_rd;
-
- if (bytecount == 2)
- spi_addr[23:16] = buffer;
-
- if (bytecount == 3)
- spi_addr[15:8] = buffer;
-
- if (bytecount == 4)
- spi_addr[7:0] = buffer;
-
- if (bytecount == 5) begin
- xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
- mode = mode_dspi_wr;
- dummycount = latency;
- end
-
- if (bytecount >= 5) begin
- buffer = memory[spi_addr];
- spi_addr = spi_addr + 1;
- end
- end
-
- if (powered_up && spi_cmd == 'h eb) begin
- if (bytecount == 1)
- mode = mode_qspi_rd;
-
- if (bytecount == 2)
- spi_addr[23:16] = buffer;
-
- if (bytecount == 3)
- spi_addr[15:8] = buffer;
-
- if (bytecount == 4)
- spi_addr[7:0] = buffer;
-
- if (bytecount == 5) begin
- xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
- mode = mode_qspi_wr;
- dummycount = latency;
- end
-
- if (bytecount >= 5) begin
- buffer = memory[spi_addr];
- spi_addr = spi_addr + 1;
- end
- end
-
- if (powered_up && spi_cmd == 'h ed) begin
- if (bytecount == 1)
- next_mode = mode_qspi_ddr_rd;
-
- if (bytecount == 2)
- spi_addr[23:16] = buffer;
-
- if (bytecount == 3)
- spi_addr[15:8] = buffer;
-
- if (bytecount == 4)
- spi_addr[7:0] = buffer;
-
- if (bytecount == 5) begin
- xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
- mode = mode_qspi_ddr_wr;
- dummycount = latency;
- end
-
- if (bytecount >= 5) begin
- buffer = memory[spi_addr];
- spi_addr = spi_addr + 1;
- end
- end
-
- spi_out = buffer;
- spi_io_vld = 1;
-
- if (verbose) begin
- if (bytecount == 1)
- $write("<SPI-START>");
- $write("<SPI:%02x:%02x>", spi_in, spi_out);
- end
-
- end
- endtask
-
- task ddr_rd_edge;
- begin
- buffer = {buffer, io3_delayed, io2_delayed, io1_delayed, io0_delayed};
- bitcount = bitcount + 4;
- if (bitcount == 8) begin
- bitcount = 0;
- bytecount = bytecount + 1;
- spi_action;
- end
- end
- endtask
-
- task ddr_wr_edge;
- begin
- io0_oe = 1;
- io1_oe = 1;
- io2_oe = 1;
- io3_oe = 1;
-
- io0_dout = buffer[4];
- io1_dout = buffer[5];
- io2_dout = buffer[6];
- io3_dout = buffer[7];
-
- buffer = {buffer, 4'h 0};
- bitcount = bitcount + 4;
- if (bitcount == 8) begin
- bitcount = 0;
- bytecount = bytecount + 1;
- spi_action;
- end
- end
- endtask
-
- always @(csb) begin
- if (csb) begin
- if (verbose) begin
- $display("");
- $fflush;
- end
- buffer = 0;
- bitcount = 0;
- bytecount = 0;
- mode = mode_spi;
- io0_oe = 0;
- io1_oe = 0;
- io2_oe = 0;
- io3_oe = 0;
- end else
- if (xip_cmd) begin
- buffer = xip_cmd;
- bitcount = 0;
- bytecount = 1;
- spi_action;
- end
- end
-
- always @(csb, clk) begin
- spi_io_vld = 0;
- if (!csb && !clk) begin
- if (dummycount > 0) begin
- io0_oe = 0;
- io1_oe = 0;
- io2_oe = 0;
- io3_oe = 0;
- end else
- case (mode)
- mode_spi: begin
- io0_oe = 0;
- io1_oe = 1;
- io2_oe = 0;
- io3_oe = 0;
- io1_dout = buffer[7];
- end
- mode_dspi_rd: begin
- io0_oe = 0;
- io1_oe = 0;
- io2_oe = 0;
- io3_oe = 0;
- end
- mode_dspi_wr: begin
- io0_oe = 1;
- io1_oe = 1;
- io2_oe = 0;
- io3_oe = 0;
- io0_dout = buffer[6];
- io1_dout = buffer[7];
- end
- mode_qspi_rd: begin
- io0_oe = 0;
- io1_oe = 0;
- io2_oe = 0;
- io3_oe = 0;
- end
- mode_qspi_wr: begin
- io0_oe = 1;
- io1_oe = 1;
- io2_oe = 1;
- io3_oe = 1;
- io0_dout = buffer[4];
- io1_dout = buffer[5];
- io2_dout = buffer[6];
- io3_dout = buffer[7];
- end
- mode_qspi_ddr_rd: begin
- ddr_rd_edge;
- end
- mode_qspi_ddr_wr: begin
- ddr_wr_edge;
- end
- endcase
- if (next_mode) begin
- case (next_mode)
- mode_qspi_ddr_rd: begin
- io0_oe = 0;
- io1_oe = 0;
- io2_oe = 0;
- io3_oe = 0;
- end
- mode_qspi_ddr_wr: begin
- io0_oe = 1;
- io1_oe = 1;
- io2_oe = 1;
- io3_oe = 1;
- io0_dout = buffer[4];
- io1_dout = buffer[5];
- io2_dout = buffer[6];
- io3_dout = buffer[7];
- end
- endcase
- mode = next_mode;
- next_mode = 0;
- end
- end
- end
-
- always @(posedge clk) begin
- if (!csb) begin
- if (dummycount > 0) begin
- dummycount = dummycount - 1;
- end else
- case (mode)
- mode_spi: begin
- buffer = {buffer, io0};
- bitcount = bitcount + 1;
- if (bitcount == 8) begin
- bitcount = 0;
- bytecount = bytecount + 1;
- spi_action;
- end
- end
- mode_dspi_rd, mode_dspi_wr: begin
- buffer = {buffer, io1, io0};
- bitcount = bitcount + 2;
- if (bitcount == 8) begin
- bitcount = 0;
- bytecount = bytecount + 1;
- spi_action;
- end
- end
- mode_qspi_rd, mode_qspi_wr: begin
- buffer = {buffer, io3, io2, io1, io0};
- bitcount = bitcount + 4;
- if (bitcount == 8) begin
- bitcount = 0;
- bytecount = bytecount + 1;
- spi_action;
- end
- end
- mode_qspi_ddr_rd: begin
- ddr_rd_edge;
- end
- mode_qspi_ddr_wr: begin
- ddr_wr_edge;
- end
- endcase
- end
- end
-endmodule
diff --git a/verilog/rtl/spimemio.v b/verilog/rtl/spimemio.v
index f5cc5c0..053aa61 100644
--- a/verilog/rtl/spimemio.v
+++ b/verilog/rtl/spimemio.v
@@ -17,585 +17,700 @@
*
*/
-module spimemio (
- input clk, resetn,
+module spimemio_wb (
+ input wb_clk_i,
+ input wb_rst_i,
- input valid,
- output ready,
- input [23:0] addr,
- output reg [31:0] rdata,
+ input [31:0] wb_adr_i,
+ input [31:0] wb_dat_i,
+ input [3:0] wb_sel_i,
+ input wb_we_i,
+ input wb_cyc_i,
- output flash_csb,
- output flash_clk,
+ input wb_flash_stb_i,
+ input wb_cfg_stb_i,
- output flash_csb_oeb,
- output flash_clk_oeb,
+ output wb_flash_ack_o,
+ output wb_cfg_ack_o,
- output flash_io0_oeb,
- output flash_io1_oeb,
- output flash_io2_oeb,
- output flash_io3_oeb,
+ output [31:0] wb_flash_dat_o,
+ output [31:0] wb_cfg_dat_o,
- output flash_csb_ieb,
- output flash_clk_ieb,
+ output flash_csb,
+ output flash_clk,
- output flash_io0_ieb,
- output flash_io1_ieb,
- output flash_io2_ieb,
- output flash_io3_ieb,
+ output flash_csb_oeb,
+ output flash_clk_oeb,
- output flash_io0_do,
- output flash_io1_do,
- output flash_io2_do,
- output flash_io3_do,
+ output flash_io0_oeb,
+ output flash_io1_oeb,
+ output flash_io2_oeb,
+ output flash_io3_oeb,
- input flash_io0_di,
- input flash_io1_di,
- input flash_io2_di,
- input flash_io3_di,
+ output flash_csb_ieb,
+ output flash_clk_ieb,
- input [3:0] cfgreg_we,
- input [31:0] cfgreg_di,
- output [31:0] cfgreg_do
+ output flash_io0_ieb,
+ output flash_io1_ieb,
+ output flash_io2_ieb,
+ output flash_io3_ieb,
+
+ output flash_io0_do,
+ output flash_io1_do,
+ output flash_io2_do,
+ output flash_io3_do,
+
+ input flash_io0_di,
+ input flash_io1_di,
+ input flash_io2_di,
+ input flash_io3_di
+
);
- reg xfer_resetn;
- reg din_valid;
- wire din_ready;
- reg [7:0] din_data;
- reg [3:0] din_tag;
- reg din_cont;
- reg din_qspi;
- reg din_ddr;
- reg din_rd;
+ wire spimem_ready;
+ wire [23:0] mem_addr;
+ wire [31:0] spimem_rdata;
+ wire [31:0] spimemio_cfgreg_do;
+ wire [3:0] cfgreg_we;
+ wire spimemio_cfgreg_sel;
+ wire valid;
+ wire resetn;
- wire dout_valid;
- wire [7:0] dout_data;
- wire [3:0] dout_tag;
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_cyc_i && wb_flash_stb_i;
+ assign wb_flash_ack_o = spimem_ready;
+ assign wb_cfg_ack_o = spimemio_cfgreg_sel;
- reg [23:0] buffer;
+ assign mem_addr = wb_adr_i[23:0];
+ assign spimemio_cfgreg_sel = wb_cyc_i && wb_cfg_stb_i;
- reg [23:0] rd_addr;
- reg rd_valid;
- reg rd_wait;
- reg rd_inc;
+ assign cfgreg_we = spimemio_cfgreg_sel ? wb_sel_i & {4{wb_we_i}} : 4'b 0000;
+ assign wb_flash_dat_o = spimem_rdata;
+ assign wb_cfg_dat_o = spimemio_cfgreg_do;
- assign ready = valid && (addr == rd_addr) && rd_valid;
- wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
+ spimemio spimemio (
+ .clk (wb_clk_i),
+ .resetn (resetn),
+ .valid (valid),
+ .ready (spimem_ready),
+ .addr (mem_addr),
+ .rdata (spimem_rdata),
- reg softreset;
+ .flash_csb (flash_csb),
+ .flash_clk (flash_clk),
- reg config_en; // cfgreg[31]
- reg config_ddr; // cfgreg[22]
- reg config_qspi; // cfgreg[21]
- reg config_cont; // cfgreg[20]
- reg [3:0] config_dummy; // cfgreg[19:16]
- reg [3:0] config_oe; // cfgreg[11:8]
- reg config_csb; // cfgreg[5]
- reg config_clk; // cfgref[4]
- reg [3:0] config_do; // cfgreg[3:0]
+ .flash_csb_oeb (flash_csb_oeb),
+ .flash_clk_oeb (flash_clk_oeb),
- assign cfgreg_do[31] = config_en;
- assign cfgreg_do[30:23] = 0;
- assign cfgreg_do[22] = config_ddr;
- assign cfgreg_do[21] = config_qspi;
- assign cfgreg_do[20] = config_cont;
- assign cfgreg_do[19:16] = config_dummy;
- assign cfgreg_do[15:12] = 0;
- assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb};
- assign cfgreg_do[7:6] = 0;
- assign cfgreg_do[5] = flash_csb;
- assign cfgreg_do[4] = flash_clk;
- assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
+ .flash_io0_oeb (flash_io0_oeb),
+ .flash_io1_oeb (flash_io1_oeb),
+ .flash_io2_oeb (flash_io2_oeb),
+ .flash_io3_oeb (flash_io3_oeb),
- always @(posedge clk) begin
- softreset <= !config_en || cfgreg_we;
- if (!resetn) begin
- softreset <= 1;
- config_en <= 1;
- config_csb <= 0;
- config_clk <= 0;
- config_oe <= 0;
- config_do <= 0;
- config_ddr <= 0;
- config_qspi <= 0;
- config_cont <= 0;
- config_dummy <= 8;
- end else begin
- if (cfgreg_we[0]) begin
- config_csb <= cfgreg_di[5];
- config_clk <= cfgreg_di[4];
- config_do <= cfgreg_di[3:0];
- end
- if (cfgreg_we[1]) begin
- config_oe <= cfgreg_di[11:8];
- end
- if (cfgreg_we[2]) begin
- config_ddr <= cfgreg_di[22];
- config_qspi <= cfgreg_di[21];
- config_cont <= cfgreg_di[20];
- config_dummy <= cfgreg_di[19:16];
- end
- if (cfgreg_we[3]) begin
- config_en <= cfgreg_di[31];
- end
- end
- end
+ .flash_csb_ieb (flash_csb_ieb),
+ .flash_clk_ieb (flash_clk_ieb),
- wire xfer_csb;
- wire xfer_clk;
+ .flash_io0_ieb (flash_io0_ieb),
+ .flash_io1_ieb (flash_io1_ieb),
+ .flash_io2_ieb (flash_io2_ieb),
+ .flash_io3_ieb (flash_io3_ieb),
- wire xfer_io0_oe;
- wire xfer_io1_oe;
- wire xfer_io2_oe;
- wire xfer_io3_oe;
+ .flash_io0_do (flash_io0_do),
+ .flash_io1_do (flash_io1_do),
+ .flash_io2_do (flash_io2_do),
+ .flash_io3_do (flash_io3_do),
- wire xfer_io0_do;
- wire xfer_io1_do;
- wire xfer_io2_do;
- wire xfer_io3_do;
+ .flash_io0_di (flash_io0_di),
+ .flash_io1_di (flash_io1_di),
+ .flash_io2_di (flash_io2_di),
+ .flash_io3_di (flash_io3_di),
- reg xfer_io0_90;
- reg xfer_io1_90;
- reg xfer_io2_90;
- reg xfer_io3_90;
+ .cfgreg_we(cfgreg_we),
+ .cfgreg_di(wb_dat_i),
+ .cfgreg_do(spimemio_cfgreg_do)
+ );
- always @(negedge clk) begin
- xfer_io0_90 <= xfer_io0_do;
- xfer_io1_90 <= xfer_io1_do;
- xfer_io2_90 <= xfer_io2_do;
- xfer_io3_90 <= xfer_io3_do;
- end
+endmodule
- assign flash_csb = config_en ? xfer_csb : config_csb;
- assign flash_clk = config_en ? xfer_clk : config_clk;
+module spimemio (
+ input clk, resetn,
- assign flash_csb_oeb = ~resetn;
- assign flash_clk_oeb = ~resetn;
+ input valid,
+ output ready,
+ input [23:0] addr,
+ output reg [31:0] rdata,
- assign flash_io0_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]);
- assign flash_io1_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]);
- assign flash_io2_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]);
- assign flash_io3_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]);
- assign flash_csb_ieb = 1'b1; /* Always disabled */
- assign flash_clk_ieb = 1'b1; /* Always disabled */
+ output flash_csb,
+ output flash_clk,
- assign flash_io0_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]);
- assign flash_io1_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]);
- assign flash_io2_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]);
- assign flash_io3_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]);
+ output flash_csb_oeb,
+ output flash_clk_oeb,
- assign flash_io0_do = config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0];
- assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1];
- assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
- assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
+ output flash_io0_oeb,
+ output flash_io1_oeb,
+ output flash_io2_oeb,
+ output flash_io3_oeb,
- wire xfer_dspi = din_ddr && !din_qspi;
- wire xfer_ddr = din_ddr && din_qspi;
+ output flash_csb_ieb,
+ output flash_clk_ieb,
- spimemio_xfer xfer (
- .clk (clk ),
- .resetn (resetn ),
- .xfer_resetn (xfer_resetn ),
- .din_valid (din_valid ),
- .din_ready (din_ready ),
- .din_data (din_data ),
- .din_tag (din_tag ),
- .din_cont (din_cont ),
- .din_dspi (xfer_dspi ),
- .din_qspi (din_qspi ),
- .din_ddr (xfer_ddr ),
- .din_rd (din_rd ),
- .dout_valid (dout_valid ),
- .dout_data (dout_data ),
- .dout_tag (dout_tag ),
- .flash_csb (xfer_csb ),
- .flash_clk (xfer_clk ),
- .flash_io0_oe (xfer_io0_oe ),
- .flash_io1_oe (xfer_io1_oe ),
- .flash_io2_oe (xfer_io2_oe ),
- .flash_io3_oe (xfer_io3_oe ),
- .flash_io0_do (xfer_io0_do ),
- .flash_io1_do (xfer_io1_do ),
- .flash_io2_do (xfer_io2_do ),
- .flash_io3_do (xfer_io3_do ),
- .flash_io0_di (flash_io0_di),
- .flash_io1_di (flash_io1_di),
- .flash_io2_di (flash_io2_di),
- .flash_io3_di (flash_io3_di)
- );
+ output flash_io0_ieb,
+ output flash_io1_ieb,
+ output flash_io2_ieb,
+ output flash_io3_ieb,
- reg [3:0] state;
+ output flash_io0_do,
+ output flash_io1_do,
+ output flash_io2_do,
+ output flash_io3_do,
- always @(posedge clk) begin
- xfer_resetn <= 1;
- din_valid <= 0;
+ input flash_io0_di,
+ input flash_io1_di,
+ input flash_io2_di,
+ input flash_io3_di,
- if (!resetn || softreset) begin
- state <= 0;
- xfer_resetn <= 0;
- rd_valid <= 0;
- din_tag <= 0;
- din_cont <= 0;
- din_qspi <= 0;
- din_ddr <= 0;
- din_rd <= 0;
- end else begin
- if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
- if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
- if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
- if (dout_valid && dout_tag == 4) begin
- rdata <= {dout_data, buffer};
- rd_addr <= rd_inc ? rd_addr + 4 : addr;
- rd_valid <= 1;
- rd_wait <= rd_inc;
- rd_inc <= 1;
- end
+ input [3:0] cfgreg_we,
+ input [31:0] cfgreg_di,
+ output [31:0] cfgreg_do
+);
+ reg xfer_resetn;
+ reg din_valid;
+ wire din_ready;
+ reg [7:0] din_data;
+ reg [3:0] din_tag;
+ reg din_cont;
+ reg din_qspi;
+ reg din_ddr;
+ reg din_rd;
- if (valid)
- rd_wait <= 0;
+ wire dout_valid;
+ wire [7:0] dout_data;
+ wire [3:0] dout_tag;
- case (state)
- 0: begin
- din_valid <= 1;
- din_data <= 8'h ff;
- din_tag <= 0;
- if (din_ready) begin
- din_valid <= 0;
- state <= 1;
- end
- end
- 1: begin
- if (dout_valid) begin
- xfer_resetn <= 0;
- state <= 2;
- end
- end
- 2: begin
- din_valid <= 1;
- din_data <= 8'h ab;
- din_tag <= 0;
- if (din_ready) begin
- din_valid <= 0;
- state <= 3;
- end
- end
- 3: begin
- if (dout_valid) begin
- xfer_resetn <= 0;
- state <= 4;
- end
- end
- 4: begin
- rd_inc <= 0;
- din_valid <= 1;
- din_tag <= 0;
- case ({config_ddr, config_qspi})
- 2'b11: din_data <= 8'h ED;
- 2'b01: din_data <= 8'h EB;
- 2'b10: din_data <= 8'h BB;
- 2'b00: din_data <= 8'h 03;
- endcase
- if (din_ready) begin
- din_valid <= 0;
- state <= 5;
- end
- end
- 5: begin
- if (valid && !ready) begin
- din_valid <= 1;
- din_tag <= 0;
- din_data <= addr[23:16];
- din_qspi <= config_qspi;
- din_ddr <= config_ddr;
- if (din_ready) begin
- din_valid <= 0;
- state <= 6;
- end
- end
- end
- 6: begin
- din_valid <= 1;
- din_tag <= 0;
- din_data <= addr[15:8];
- if (din_ready) begin
- din_valid <= 0;
- state <= 7;
- end
- end
- 7: begin
- din_valid <= 1;
- din_tag <= 0;
- din_data <= addr[7:0];
- if (din_ready) begin
- din_valid <= 0;
- din_data <= 0;
- state <= config_qspi || config_ddr ? 8 : 9;
- end
- end
- 8: begin
- din_valid <= 1;
- din_tag <= 0;
- din_data <= config_cont ? 8'h A5 : 8'h FF;
- if (din_ready) begin
- din_rd <= 1;
- din_data <= config_dummy;
- din_valid <= 0;
- state <= 9;
- end
- end
- 9: begin
- din_valid <= 1;
- din_tag <= 1;
- if (din_ready) begin
- din_valid <= 0;
- state <= 10;
- end
- end
- 10: begin
- din_valid <= 1;
- din_data <= 8'h 00;
- din_tag <= 2;
- if (din_ready) begin
- din_valid <= 0;
- state <= 11;
- end
- end
- 11: begin
- din_valid <= 1;
- din_tag <= 3;
- if (din_ready) begin
- din_valid <= 0;
- state <= 12;
- end
- end
- 12: begin
- if (!rd_wait || valid) begin
- din_valid <= 1;
- din_tag <= 4;
- if (din_ready) begin
- din_valid <= 0;
- state <= 9;
- end
- end
- end
- endcase
+ reg [23:0] buffer;
- if (jump) begin
- rd_inc <= 0;
- rd_valid <= 0;
- xfer_resetn <= 0;
- if (config_cont) begin
- state <= 5;
- end else begin
- state <= 4;
- din_qspi <= 0;
- din_ddr <= 0;
- end
- din_rd <= 0;
- end
- end
- end
+ reg [23:0] rd_addr;
+ reg rd_valid;
+ reg rd_wait;
+ reg rd_inc;
+
+ assign ready = valid && (addr == rd_addr) && rd_valid;
+ wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
+
+ reg softreset;
+
+ reg config_en; // cfgreg[31]
+ reg config_ddr; // cfgreg[22]
+ reg config_qspi; // cfgreg[21]
+ reg config_cont; // cfgreg[20]
+ reg [3:0] config_dummy; // cfgreg[19:16]
+ reg [3:0] config_oe; // cfgreg[11:8]
+ reg config_csb; // cfgreg[5]
+ reg config_clk; // cfgref[4]
+ reg [3:0] config_do; // cfgreg[3:0]
+
+ assign cfgreg_do[31] = config_en;
+ assign cfgreg_do[30:23] = 0;
+ assign cfgreg_do[22] = config_ddr;
+ assign cfgreg_do[21] = config_qspi;
+ assign cfgreg_do[20] = config_cont;
+ assign cfgreg_do[19:16] = config_dummy;
+ assign cfgreg_do[15:12] = 0;
+ assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb};
+ assign cfgreg_do[7:6] = 0;
+ assign cfgreg_do[5] = flash_csb;
+ assign cfgreg_do[4] = flash_clk;
+ assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
+
+ always @(posedge clk) begin
+ softreset <= !config_en || cfgreg_we;
+ if (!resetn) begin
+ softreset <= 1;
+ config_en <= 1;
+ config_csb <= 0;
+ config_clk <= 0;
+ config_oe <= 0;
+ config_do <= 0;
+ config_ddr <= 0;
+ config_qspi <= 0;
+ config_cont <= 0;
+ config_dummy <= 8;
+ end else begin
+ if (cfgreg_we[0]) begin
+ config_csb <= cfgreg_di[5];
+ config_clk <= cfgreg_di[4];
+ config_do <= cfgreg_di[3:0];
+ end
+ if (cfgreg_we[1]) begin
+ config_oe <= cfgreg_di[11:8];
+ end
+ if (cfgreg_we[2]) begin
+ config_ddr <= cfgreg_di[22];
+ config_qspi <= cfgreg_di[21];
+ config_cont <= cfgreg_di[20];
+ config_dummy <= cfgreg_di[19:16];
+ end
+ if (cfgreg_we[3]) begin
+ config_en <= cfgreg_di[31];
+ end
+ end
+ end
+
+ wire xfer_csb;
+ wire xfer_clk;
+
+ wire xfer_io0_oe;
+ wire xfer_io1_oe;
+ wire xfer_io2_oe;
+ wire xfer_io3_oe;
+
+ wire xfer_io0_do;
+ wire xfer_io1_do;
+ wire xfer_io2_do;
+ wire xfer_io3_do;
+
+ reg xfer_io0_90;
+ reg xfer_io1_90;
+ reg xfer_io2_90;
+ reg xfer_io3_90;
+
+ always @(negedge clk) begin
+ xfer_io0_90 <= xfer_io0_do;
+ xfer_io1_90 <= xfer_io1_do;
+ xfer_io2_90 <= xfer_io2_do;
+ xfer_io3_90 <= xfer_io3_do;
+ end
+
+ assign flash_csb = config_en ? xfer_csb : config_csb;
+ assign flash_clk = config_en ? xfer_clk : config_clk;
+
+ assign flash_csb_oeb = ~resetn;
+ assign flash_clk_oeb = ~resetn;
+
+ assign flash_io0_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]);
+ assign flash_io1_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]);
+ assign flash_io2_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]);
+ assign flash_io3_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]);
+ assign flash_csb_ieb = 1'b1; /* Always disabled */
+ assign flash_clk_ieb = 1'b1; /* Always disabled */
+
+ assign flash_io0_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]);
+ assign flash_io1_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]);
+ assign flash_io2_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]);
+ assign flash_io3_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]);
+
+ assign flash_io0_do = config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0];
+ assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1];
+ assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
+ assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
+
+ wire xfer_dspi = din_ddr && !din_qspi;
+ wire xfer_ddr = din_ddr && din_qspi;
+
+ spimemio_xfer xfer (
+ .clk (clk ),
+ .resetn (resetn ),
+ .xfer_resetn (xfer_resetn ),
+ .din_valid (din_valid ),
+ .din_ready (din_ready ),
+ .din_data (din_data ),
+ .din_tag (din_tag ),
+ .din_cont (din_cont ),
+ .din_dspi (xfer_dspi ),
+ .din_qspi (din_qspi ),
+ .din_ddr (xfer_ddr ),
+ .din_rd (din_rd ),
+ .dout_valid (dout_valid ),
+ .dout_data (dout_data ),
+ .dout_tag (dout_tag ),
+ .flash_csb (xfer_csb ),
+ .flash_clk (xfer_clk ),
+ .flash_io0_oe (xfer_io0_oe ),
+ .flash_io1_oe (xfer_io1_oe ),
+ .flash_io2_oe (xfer_io2_oe ),
+ .flash_io3_oe (xfer_io3_oe ),
+ .flash_io0_do (xfer_io0_do ),
+ .flash_io1_do (xfer_io1_do ),
+ .flash_io2_do (xfer_io2_do ),
+ .flash_io3_do (xfer_io3_do ),
+ .flash_io0_di (flash_io0_di),
+ .flash_io1_di (flash_io1_di),
+ .flash_io2_di (flash_io2_di),
+ .flash_io3_di (flash_io3_di)
+ );
+
+ reg [3:0] state;
+
+ always @(posedge clk) begin
+ xfer_resetn <= 1;
+ din_valid <= 0;
+
+ if (!resetn || softreset) begin
+ state <= 0;
+ xfer_resetn <= 0;
+ rd_valid <= 0;
+ din_tag <= 0;
+ din_cont <= 0;
+ din_qspi <= 0;
+ din_ddr <= 0;
+ din_rd <= 0;
+ end else begin
+ if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
+ if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
+ if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
+ if (dout_valid && dout_tag == 4) begin
+ rdata <= {dout_data, buffer};
+ rd_addr <= rd_inc ? rd_addr + 4 : addr;
+ rd_valid <= 1;
+ rd_wait <= rd_inc;
+ rd_inc <= 1;
+ end
+
+ if (valid)
+ rd_wait <= 0;
+
+ case (state)
+ 0: begin
+ din_valid <= 1;
+ din_data <= 8'h ff;
+ din_tag <= 0;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 1;
+ end
+ end
+ 1: begin
+ if (dout_valid) begin
+ xfer_resetn <= 0;
+ state <= 2;
+ end
+ end
+ 2: begin
+ din_valid <= 1;
+ din_data <= 8'h ab;
+ din_tag <= 0;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 3;
+ end
+ end
+ 3: begin
+ if (dout_valid) begin
+ xfer_resetn <= 0;
+ state <= 4;
+ end
+ end
+ 4: begin
+ rd_inc <= 0;
+ din_valid <= 1;
+ din_tag <= 0;
+ case ({config_ddr, config_qspi})
+ 2'b11: din_data <= 8'h ED;
+ 2'b01: din_data <= 8'h EB;
+ 2'b10: din_data <= 8'h BB;
+ 2'b00: din_data <= 8'h 03;
+ endcase
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 5;
+ end
+ end
+ 5: begin
+ if (valid && !ready) begin
+ din_valid <= 1;
+ din_tag <= 0;
+ din_data <= addr[23:16];
+ din_qspi <= config_qspi;
+ din_ddr <= config_ddr;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 6;
+ end
+ end
+ end
+ 6: begin
+ din_valid <= 1;
+ din_tag <= 0;
+ din_data <= addr[15:8];
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 7;
+ end
+ end
+ 7: begin
+ din_valid <= 1;
+ din_tag <= 0;
+ din_data <= addr[7:0];
+ if (din_ready) begin
+ din_valid <= 0;
+ din_data <= 0;
+ state <= config_qspi || config_ddr ? 8 : 9;
+ end
+ end
+ 8: begin
+ din_valid <= 1;
+ din_tag <= 0;
+ din_data <= config_cont ? 8'h A5 : 8'h FF;
+ if (din_ready) begin
+ din_rd <= 1;
+ din_data <= config_dummy;
+ din_valid <= 0;
+ state <= 9;
+ end
+ end
+ 9: begin
+ din_valid <= 1;
+ din_tag <= 1;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 10;
+ end
+ end
+ 10: begin
+ din_valid <= 1;
+ din_data <= 8'h 00;
+ din_tag <= 2;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 11;
+ end
+ end
+ 11: begin
+ din_valid <= 1;
+ din_tag <= 3;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 12;
+ end
+ end
+ 12: begin
+ if (!rd_wait || valid) begin
+ din_valid <= 1;
+ din_tag <= 4;
+ if (din_ready) begin
+ din_valid <= 0;
+ state <= 9;
+ end
+ end
+ end
+ endcase
+
+ if (jump) begin
+ rd_inc <= 0;
+ rd_valid <= 0;
+ xfer_resetn <= 0;
+ if (config_cont) begin
+ state <= 5;
+ end else begin
+ state <= 4;
+ din_qspi <= 0;
+ din_ddr <= 0;
+ end
+ din_rd <= 0;
+ end
+ end
+ end
endmodule
module spimemio_xfer (
- input clk, resetn, xfer_resetn,
+ input clk, resetn, xfer_resetn,
- input din_valid,
- output din_ready,
- input [7:0] din_data,
- input [3:0] din_tag,
- input din_cont,
- input din_dspi,
- input din_qspi,
- input din_ddr,
- input din_rd,
+ input din_valid,
+ output din_ready,
+ input [7:0] din_data,
+ input [3:0] din_tag,
+ input din_cont,
+ input din_dspi,
+ input din_qspi,
+ input din_ddr,
+ input din_rd,
- output dout_valid,
- output [7:0] dout_data,
- output [3:0] dout_tag,
+ output dout_valid,
+ output [7:0] dout_data,
+ output [3:0] dout_tag,
- output reg flash_csb,
- output reg flash_clk,
+ output reg flash_csb,
+ output reg flash_clk,
- output reg flash_io0_oe,
- output reg flash_io1_oe,
- output reg flash_io2_oe,
- output reg flash_io3_oe,
+ output reg flash_io0_oe,
+ output reg flash_io1_oe,
+ output reg flash_io2_oe,
+ output reg flash_io3_oe,
- output reg flash_io0_do,
- output reg flash_io1_do,
- output reg flash_io2_do,
- output reg flash_io3_do,
+ output reg flash_io0_do,
+ output reg flash_io1_do,
+ output reg flash_io2_do,
+ output reg flash_io3_do,
- input flash_io0_di,
- input flash_io1_di,
- input flash_io2_di,
- input flash_io3_di
+ input flash_io0_di,
+ input flash_io1_di,
+ input flash_io2_di,
+ input flash_io3_di
);
- reg [7:0] obuffer;
- reg [7:0] ibuffer;
+ reg [7:0] obuffer;
+ reg [7:0] ibuffer;
- reg [3:0] count;
- reg [3:0] dummy_count;
+ reg [3:0] count;
+ reg [3:0] dummy_count;
- reg xfer_cont;
- reg xfer_dspi;
- reg xfer_qspi;
- reg xfer_ddr;
- reg xfer_ddr_q;
- reg xfer_rd;
- reg [3:0] xfer_tag;
- reg [3:0] xfer_tag_q;
+ reg xfer_cont;
+ reg xfer_dspi;
+ reg xfer_qspi;
+ reg xfer_ddr;
+ reg xfer_ddr_q;
+ reg xfer_rd;
+ reg [3:0] xfer_tag;
+ reg [3:0] xfer_tag_q;
- reg [7:0] next_obuffer;
- reg [7:0] next_ibuffer;
- reg [3:0] next_count;
+ reg [7:0] next_obuffer;
+ reg [7:0] next_ibuffer;
+ reg [3:0] next_count;
- reg fetch;
- reg next_fetch;
- reg last_fetch;
+ reg fetch;
+ reg next_fetch;
+ reg last_fetch;
- always @(posedge clk) begin
- xfer_ddr_q <= xfer_ddr;
- xfer_tag_q <= xfer_tag;
- end
+ always @(posedge clk) begin
+ xfer_ddr_q <= xfer_ddr;
+ xfer_tag_q <= xfer_tag;
+ end
- assign din_ready = din_valid && xfer_resetn && next_fetch;
+ assign din_ready = din_valid && xfer_resetn && next_fetch;
- assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn;
- assign dout_data = ibuffer;
- assign dout_tag = xfer_tag_q;
+ assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn;
+ assign dout_data = ibuffer;
+ assign dout_tag = xfer_tag_q;
- always @* begin
- flash_io0_oe = 0;
- flash_io1_oe = 0;
- flash_io2_oe = 0;
- flash_io3_oe = 0;
+ always @* begin
+ flash_io0_oe = 0;
+ flash_io1_oe = 0;
+ flash_io2_oe = 0;
+ flash_io3_oe = 0;
- flash_io0_do = 0;
- flash_io1_do = 0;
- flash_io2_do = 0;
- flash_io3_do = 0;
+ flash_io0_do = 0;
+ flash_io1_do = 0;
+ flash_io2_do = 0;
+ flash_io3_do = 0;
- next_obuffer = obuffer;
- next_ibuffer = ibuffer;
- next_count = count;
- next_fetch = 0;
+ next_obuffer = obuffer;
+ next_ibuffer = ibuffer;
+ next_count = count;
+ next_fetch = 0;
- if (dummy_count == 0) begin
- casez ({xfer_ddr, xfer_qspi, xfer_dspi})
- 3'b 000: begin
- flash_io0_oe = 1;
- flash_io0_do = obuffer[7];
+ if (dummy_count == 0) begin
+ casez ({xfer_ddr, xfer_qspi, xfer_dspi})
+ 3'b 000: begin
+ flash_io0_oe = 1;
+ flash_io0_do = obuffer[7];
- if (flash_clk) begin
- next_obuffer = {obuffer[6:0], 1'b 0};
- next_count = count - |count;
- end else begin
- next_ibuffer = {ibuffer[6:0], flash_io1_di};
- end
+ if (flash_clk) begin
+ next_obuffer = {obuffer[6:0], 1'b 0};
+ next_count = count - |count;
+ end else begin
+ next_ibuffer = {ibuffer[6:0], flash_io1_di};
+ end
- next_fetch = (next_count == 0);
- end
- 3'b 01?: begin
- flash_io0_oe = !xfer_rd;
- flash_io1_oe = !xfer_rd;
- flash_io2_oe = !xfer_rd;
- flash_io3_oe = !xfer_rd;
+ next_fetch = (next_count == 0);
+ end
+ 3'b 01?: begin
+ flash_io0_oe = !xfer_rd;
+ flash_io1_oe = !xfer_rd;
+ flash_io2_oe = !xfer_rd;
+ flash_io3_oe = !xfer_rd;
- flash_io0_do = obuffer[4];
- flash_io1_do = obuffer[5];
- flash_io2_do = obuffer[6];
- flash_io3_do = obuffer[7];
+ flash_io0_do = obuffer[4];
+ flash_io1_do = obuffer[5];
+ flash_io2_do = obuffer[6];
+ flash_io3_do = obuffer[7];
- if (flash_clk) begin
- next_obuffer = {obuffer[3:0], 4'b 0000};
- next_count = count - {|count, 2'b00};
- end else begin
- next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
- end
+ if (flash_clk) begin
+ next_obuffer = {obuffer[3:0], 4'b 0000};
+ next_count = count - {|count, 2'b00};
+ end else begin
+ next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
+ end
- next_fetch = (next_count == 0);
- end
- 3'b 11?: begin
- flash_io0_oe = !xfer_rd;
- flash_io1_oe = !xfer_rd;
- flash_io2_oe = !xfer_rd;
- flash_io3_oe = !xfer_rd;
+ next_fetch = (next_count == 0);
+ end
+ 3'b 11?: begin
+ flash_io0_oe = !xfer_rd;
+ flash_io1_oe = !xfer_rd;
+ flash_io2_oe = !xfer_rd;
+ flash_io3_oe = !xfer_rd;
- flash_io0_do = obuffer[4];
- flash_io1_do = obuffer[5];
- flash_io2_do = obuffer[6];
- flash_io3_do = obuffer[7];
+ flash_io0_do = obuffer[4];
+ flash_io1_do = obuffer[5];
+ flash_io2_do = obuffer[6];
+ flash_io3_do = obuffer[7];
- next_obuffer = {obuffer[3:0], 4'b 0000};
- next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
- next_count = count - {|count, 2'b00};
+ next_obuffer = {obuffer[3:0], 4'b 0000};
+ next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
+ next_count = count - {|count, 2'b00};
- next_fetch = (next_count == 0);
- end
- 3'b ??1: begin
- flash_io0_oe = !xfer_rd;
- flash_io1_oe = !xfer_rd;
+ next_fetch = (next_count == 0);
+ end
+ 3'b ??1: begin
+ flash_io0_oe = !xfer_rd;
+ flash_io1_oe = !xfer_rd;
- flash_io0_do = obuffer[6];
- flash_io1_do = obuffer[7];
+ flash_io0_do = obuffer[6];
+ flash_io1_do = obuffer[7];
- if (flash_clk) begin
- next_obuffer = {obuffer[5:0], 2'b 00};
- next_count = count - {|count, 1'b0};
- end else begin
- next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
- end
+ if (flash_clk) begin
+ next_obuffer = {obuffer[5:0], 2'b 00};
+ next_count = count - {|count, 1'b0};
+ end else begin
+ next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
+ end
- next_fetch = (next_count == 0);
- end
- endcase
- end
- end
+ next_fetch = (next_count == 0);
+ end
+ endcase
+ end
+ end
- always @(posedge clk) begin
- if (!resetn || !xfer_resetn) begin
- fetch <= 1;
- last_fetch <= 1;
- flash_csb <= 1;
- flash_clk <= 0;
- count <= 0;
- dummy_count <= 0;
- xfer_tag <= 0;
- xfer_cont <= 0;
- xfer_dspi <= 0;
- xfer_qspi <= 0;
- xfer_ddr <= 0;
- xfer_rd <= 0;
- end else begin
- fetch <= next_fetch;
- last_fetch <= xfer_ddr ? fetch : 1;
- if (dummy_count) begin
- flash_clk <= !flash_clk && !flash_csb;
- dummy_count <= dummy_count - flash_clk;
- end else
- if (count) begin
- flash_clk <= !flash_clk && !flash_csb;
- obuffer <= next_obuffer;
- ibuffer <= next_ibuffer;
- count <= next_count;
- end
- if (din_valid && din_ready) begin
- flash_csb <= 0;
- flash_clk <= 0;
+ always @(posedge clk) begin
+ if (!resetn || !xfer_resetn) begin
+ fetch <= 1;
+ last_fetch <= 1;
+ flash_csb <= 1;
+ flash_clk <= 0;
+ count <= 0;
+ dummy_count <= 0;
+ xfer_tag <= 0;
+ xfer_cont <= 0;
+ xfer_dspi <= 0;
+ xfer_qspi <= 0;
+ xfer_ddr <= 0;
+ xfer_rd <= 0;
+ end else begin
+ fetch <= next_fetch;
+ last_fetch <= xfer_ddr ? fetch : 1;
+ if (dummy_count) begin
+ flash_clk <= !flash_clk && !flash_csb;
+ dummy_count <= dummy_count - flash_clk;
+ end else
+ if (count) begin
+ flash_clk <= !flash_clk && !flash_csb;
+ obuffer <= next_obuffer;
+ ibuffer <= next_ibuffer;
+ count <= next_count;
+ end
+ if (din_valid && din_ready) begin
+ flash_csb <= 0;
+ flash_clk <= 0;
- count <= 8;
- dummy_count <= din_rd ? din_data : 0;
- obuffer <= din_data;
+ count <= 8;
+ dummy_count <= din_rd ? din_data : 0;
+ obuffer <= din_data;
- xfer_tag <= din_tag;
- xfer_cont <= din_cont;
- xfer_dspi <= din_dspi;
- xfer_qspi <= din_qspi;
- xfer_ddr <= din_ddr;
- xfer_rd <= din_rd;
- end
- end
- end
+ xfer_tag <= din_tag;
+ xfer_cont <= din_cont;
+ xfer_dspi <= din_dspi;
+ xfer_qspi <= din_qspi;
+ xfer_ddr <= din_ddr;
+ xfer_rd <= din_rd;
+ end
+ end
+ end
endmodule
+
diff --git a/verilog/rtl/sram_1rw1r_32_256_8_sky130.v b/verilog/rtl/sram_1rw1r_32_256_8_sky130.v
new file mode 100644
index 0000000..2dd1c62
--- /dev/null
+++ b/verilog/rtl/sram_1rw1r_32_256_8_sky130.v
@@ -0,0 +1,108 @@
+// OpenRAM SRAM model
+// Words: 256
+// Word size: 32
+// Write size: 8
+
+module sram_1rw1r_32_256_8_sky130(
+// Port 0: RW
+ clk0,csb0,web0,wmask0,addr0,din0,dout0,
+// Port 1: R
+ clk1,csb1,addr1,dout1
+ );
+
+ parameter NUM_WMASKS = 4 ;
+ parameter DATA_WIDTH = 32 ;
+ parameter ADDR_WIDTH = 8 ;
+ parameter RAM_DEPTH = 1 << ADDR_WIDTH;
+ // FIXME: This delay is arbitrary.
+ parameter DELAY = 1 ;
+
+ input clk0; // clock
+ input csb0; // active low chip select
+ input web0; // active low write control
+ input [NUM_WMASKS-1:0] wmask0; // write mask
+ input [ADDR_WIDTH-1:0] addr0;
+ input [DATA_WIDTH-1:0] din0;
+ output [DATA_WIDTH-1:0] dout0;
+ input clk1; // clock
+ input csb1; // active low chip select
+ input [ADDR_WIDTH-1:0] addr1;
+ output [DATA_WIDTH-1:0] dout1;
+
+ reg csb0_reg;
+ reg web0_reg;
+ reg [NUM_WMASKS-1:0] wmask0_reg;
+ reg [ADDR_WIDTH-1:0] addr0_reg;
+ reg [DATA_WIDTH-1:0] din0_reg;
+ reg [DATA_WIDTH-1:0] dout0;
+
+ // All inputs are registers
+ always @(posedge clk0)
+ begin
+ csb0_reg = csb0;
+ web0_reg = web0;
+ wmask0_reg = wmask0;
+ addr0_reg = addr0;
+ din0_reg = din0;
+ dout0 = 32'bx;
+`ifdef DBG
+ if ( !csb0_reg && web0_reg )
+ $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]);
+ if ( !csb0_reg && !web0_reg )
+ $display($time," Writing %m addr0=%b din0=%b wmask0=%b",addr0_reg,din0_reg,wmask0_reg);
+`endif
+ end
+
+ reg csb1_reg;
+ reg [ADDR_WIDTH-1:0] addr1_reg;
+ reg [DATA_WIDTH-1:0] dout1;
+
+ // All inputs are registers
+ always @(posedge clk1)
+ begin
+ csb1_reg = csb1;
+ addr1_reg = addr1;
+`ifdef DBG
+ if (!csb0 && !web0 && !csb1 && (addr0 == addr1))
+ $display($time," WARNING: Writing and reading addr0=%b and addr1=%b simultaneously!",addr0,addr1);
+ dout1 = 32'bx;
+ if ( !csb1_reg )
+ $display($time," Reading %m addr1=%b dout1=%b",addr1_reg,mem[addr1_reg]);
+`endif
+ end
+
+reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
+
+ // Memory Write Block Port 0
+ // Write Operation : When web0 = 0, csb0 = 0
+ always @ (negedge clk0)
+ begin : MEM_WRITE0
+ if ( !csb0_reg && !web0_reg ) begin
+ if (wmask0_reg[0])
+ mem[addr0_reg][7:0] = din0_reg[7:0];
+ if (wmask0_reg[1])
+ mem[addr0_reg][15:8] = din0_reg[15:8];
+ if (wmask0_reg[2])
+ mem[addr0_reg][23:16] = din0_reg[23:16];
+ if (wmask0_reg[3])
+ mem[addr0_reg][31:24] = din0_reg[31:24];
+ end
+ end
+
+ // Memory Read Block Port 0
+ // Read Operation : When web0 = 1, csb0 = 0
+ always @ (negedge clk0)
+ begin : MEM_READ0
+ if (!csb0_reg && web0_reg)
+ dout0 <= #(DELAY) mem[addr0_reg];
+ end
+
+ // Memory Read Block Port 1
+ // Read Operation : When web1 = 1, csb1 = 0
+ always @ (negedge clk1)
+ begin : MEM_READ1
+ if (!csb1_reg)
+ dout1 <= #(DELAY) mem[addr1_reg];
+ end
+
+endmodule
diff --git a/verilog/rtl/striVe_clkrst.v b/verilog/rtl/striVe_clkrst.v
index 6310274..ff42831 100644
--- a/verilog/rtl/striVe_clkrst.v
+++ b/verilog/rtl/striVe_clkrst.v
@@ -1,31 +1,35 @@
module striVe_clkrst(
- input ext_clk_sel,
- input ext_clk,
- input pll_clk,
- input reset,
- input ext_reset,
- output clk,
- output resetn
+`ifdef LVS
+ input vdd1v8,
+ input vss,
+`endif
+ input ext_clk_sel,
+ input ext_clk,
+ input pll_clk,
+ input reset,
+ input ext_reset,
+ output clk,
+ output resetn
);
- // Clock assignment (to do: make this glitch-free)
- assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk;
+ // Clock assignment (to do: make this glitch-free)
+ assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk;
- // Reset assignment. "reset" comes from POR, while "ext_reset"
- // comes from standalone SPI (and is normally zero unless
- // activated from the SPI).
+ // Reset assignment. "reset" comes from POR, while "ext_reset"
+ // comes from standalone SPI (and is normally zero unless
+ // activated from the SPI).
- // Staged-delay reset
- reg [2:0] reset_delay;
+ // Staged-delay reset
+ reg [2:0] reset_delay;
- always @(posedge clk or posedge reset) begin
- if (reset == 1'b1) begin
- reset_delay <= 3'b111;
- end else begin
- reset_delay <= {1'b0, reset_delay[2:1]};
- end
- end
+ always @(posedge clk or posedge reset) begin
+ if (reset == 1'b1) begin
+ reset_delay <= 3'b111;
+ end else begin
+ reset_delay <= {1'b0, reset_delay[2:1]};
+ end
+ end
- assign resetn = ~(reset_delay[0] | ext_reset);
+ assign resetn = ~(reset_delay[0] | ext_reset);
endmodule
diff --git a/verilog/rtl/striVe_soc.v b/verilog/rtl/striVe_soc.v
deleted file mode 100644
index 1899a99..0000000
--- a/verilog/rtl/striVe_soc.v
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * PicoSoC - A simple example SoC using PicoRV32
- *
- * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
- *
- * 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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Revision 1, July 2019: Added signals to drive flash_clk and flash_csb
- * output enable (inverted), tied to reset so that the flash is completely
- * isolated from the processor when the processor is in reset.
- *
- * Also: Made ram_wenb a 4-bit bus so that the memory access can be made
- * byte-wide for byte-wide instructions.
- */
-
-`ifdef PICORV32_V
-`error "openstriVe_soc.v must be read before picorv32.v!"
-`endif
-
-/* Note: Synthesize register memory from flops */
-/* Inefficient, but not terribly so */
-
-/* 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 openstriVe_soc I/O so that openstriVe_soc.v itself is fully synthesizable */
-/* and routable with qflow as-is. */
-
-`define PICORV32_REGS openstriVe_soc_regs
-
-module striVe_soc (
-`ifdef LVS
- inout vdd1v8, /* 1.8V domain */
- inout vss,
-`endif
- input pll_clk,
- input ext_clk,
- input ext_clk_sel,
- /*
- input ext_reset,
- input reset,
- */
-
- input clk,
- input resetn,
- // Main SRAM, including clk and resetn above
- // (Not used: RAM is synthesized in this version)
- /*
- output [3:0] ram_wenb,
- output [9:0] ram_addr,
- output [31:0] ram_wdata,
- input [31:0] ram_rdata,
- */
-
- // Memory mapped I/O signals
- output [15:0] gpio_out_pad, // Connect to out on gpio pad
- input [15:0] gpio_in_pad, // Connect to in on gpio pad
- output [15:0] gpio_mode0_pad, // Connect to dm[0] on gpio pad
- output [15:0] gpio_mode1_pad, // Connect to dm[2] on gpio pad
- output [15:0] gpio_outenb_pad, // Connect to oe_n on gpio pad
- output [15:0] gpio_inenb_pad, // Connect to inp_dis on gpio pad
-
- output adc0_ena,
- output adc0_convert,
- input [9:0] adc0_data,
- input adc0_done,
- output adc0_clk,
- output [1:0] adc0_inputsrc,
- output adc1_ena,
- output adc1_convert,
- output adc1_clk,
- output [1:0] adc1_inputsrc,
- input [9:0] adc1_data,
- input adc1_done,
-
- output dac_ena,
- output [9:0] dac_value,
-
- output analog_out_sel, // Analog output select (DAC or bandgap)
- output opamp_ena, // Op-amp enable for analog output
- output opamp_bias_ena, // Op-amp bias enable for analog output
- output bg_ena, // Bandgap enable
-
- output comp_ena,
- output [1:0] comp_ninputsrc,
- output [1:0] comp_pinputsrc,
- output rcosc_ena,
-
- output overtemp_ena,
- input overtemp,
- input rcosc_in, // RC oscillator output
- input xtal_in, // crystal oscillator output
- input comp_in, // comparator output
- input spi_sck,
-
- input [7:0] spi_ro_config,
- input spi_ro_xtal_ena,
- input spi_ro_reg_ena,
- input spi_ro_pll_dco_ena,
- input [4:0] spi_ro_pll_div,
- input [2:0] spi_ro_pll_sel,
- input [25:0] spi_ro_pll_trim,
-
- input [11:0] spi_ro_mfgr_id,
- input [7:0] spi_ro_prod_id,
- input [3:0] spi_ro_mask_rev,
-
- output ser_tx,
- input ser_rx,
-
- // IRQ
- input irq_pin, // dedicated IRQ pin
- input irq_spi, // IRQ from standalone SPI
-
- // trap
- output trap,
-
- // Flash memory control (SPI master)
- output flash_csb,
- output flash_clk,
-
- output flash_csb_oeb,
- output flash_clk_oeb,
-
- output flash_io0_oeb,
- output flash_io1_oeb,
- output flash_io2_oeb,
- output flash_io3_oeb,
-
- output flash_csb_ieb,
- output flash_clk_ieb,
-
- output flash_io0_ieb,
- output flash_io1_ieb,
- output flash_io2_ieb,
- output flash_io3_ieb,
-
- output flash_io0_do,
- output flash_io1_do,
- output flash_io2_do,
- output flash_io3_do,
-
- input flash_io0_di,
- input flash_io1_di,
- input flash_io2_di,
- input flash_io3_di
-);
- /* Increase scratchpad memory to 1K words */
- /* parameter integer MEM_WORDS = 1024; */
- /* Memory reverted back to 256 words while memory has to be synthesized */
- parameter integer MEM_WORDS = 256;
- parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
- parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash
-
-// wire resetn;
-// wire clk;
-
- wire iomem_valid;
- reg iomem_ready;
- wire [ 3:0] iomem_wstrb;
- wire [31:0] iomem_addr;
- wire [31:0] iomem_wdata;
- reg [31:0] iomem_rdata;
-
- // memory-mapped I/O control registers
-
- wire [15:0] gpio_pullup; // Intermediate GPIO pullup
- wire [15:0] gpio_pulldown; // Intermediate GPIO pulldown
- wire [15:0] gpio_outenb; // Intermediate GPIO out enable (bar)
- wire [15:0] gpio_out; // Intermediate GPIO output
-
- reg [15:0] gpio; // GPIO output data
- reg [15:0] gpio_pu; // GPIO pull-up enable
- reg [15:0] gpio_pd; // GPIO pull-down enable
- reg [15:0] gpio_oeb; // GPIO output enable (sense negative)
- reg adc0_ena; // ADC0 enable
- reg adc0_convert; // ADC0 convert
- reg [1:0] adc0_clksrc; // ADC0 clock source
- reg [1:0] adc0_inputsrc; // ADC0 input source
- reg adc1_ena; // ADC1 enable
- reg adc1_convert; // ADC1 convert
- reg [1:0] adc1_clksrc; // ADC1 clock source
- reg [1:0] adc1_inputsrc; // ADC1 input source
- reg dac_ena; // DAC enable
- reg [9:0] dac_value; // DAC output value
- reg comp_ena; // Comparator enable
- reg [1:0] comp_ninputsrc; // Comparator negative input source
- reg [1:0] comp_pinputsrc; // Comparator positive input source
- reg rcosc_ena; // RC oscillator enable
- reg overtemp_ena; // Over-temperature alarm enable
- reg [1:0] comp_output_dest; // Comparator output destination
- reg [1:0] rcosc_output_dest; // RC oscillator output destination
- reg [1:0] overtemp_dest; // Over-temperature alarm destination
- reg [1:0] pll_output_dest; // PLL clock output destination
- reg [1:0] xtal_output_dest; // Crystal oscillator output destination
- reg [1:0] trap_output_dest; // Trap signal output destination
- reg [1:0] irq_7_inputsrc; // IRQ 5 source
- reg [1:0] irq_8_inputsrc; // IRQ 6 source
- reg analog_out_sel; // Analog output select
- reg opamp_ena; // Analog output op-amp enable
- reg opamp_bias_ena; // Analog output op-amp bias enable
- reg bg_ena; // Bandgap enable
- wire adc0_clk; // ADC0 clock (multiplexed)
- wire adc1_clk; // ADC1 clock (multiplexed)
-
- wire [3:0] ram_wenb;
- wire [9:0] ram_addr;
- wire [31:0] ram_wdata;
-
-// // Clock assignment (to do: make this glitch-free)
-// assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk;
-//
-// // Reset assignment. "reset" comes from POR, while "ext_reset"
-// // comes from standalone SPI (and is normally zero unless
-// // activated from the SPI).
-//
-// // Staged-delay reset
-// reg [2:0] reset_delay;
-//
-// always @(posedge clk or posedge reset) begin
-// if (reset == 1'b1) begin
-// reset_delay <= 3'b111;
-// end else begin
-// reset_delay <= {1'b0, reset_delay[2:1]};
-// end
-// end
-//
-// assign resetn = ~(reset_delay[0] | ext_reset);
-
- // ADC clock assignments
-
- assign adc0_clk = (adc0_clksrc == 2'b00) ? rcosc_in :
- (adc0_clksrc == 2'b01) ? spi_sck :
- (adc0_clksrc == 2'b10) ? xtal_in :
- ext_clk;
-
- assign adc1_clk = (adc1_clksrc == 2'b00) ? rcosc_in :
- (adc1_clksrc == 2'b01) ? spi_sck :
- (adc1_clksrc == 2'b10) ? xtal_in :
- ext_clk;
-
- // GPIO assignments
-
- assign gpio_out[0] = (comp_output_dest == 2'b01) ? comp_in : gpio[0];
- assign gpio_out[1] = (comp_output_dest == 2'b10) ? comp_in : gpio[1];
- assign gpio_out[2] = (rcosc_output_dest == 2'b01) ? rcosc_in : gpio[2];
- assign gpio_out[3] = (rcosc_output_dest == 2'b10) ? rcosc_in : gpio[3];
- assign gpio_out[4] = (rcosc_output_dest == 2'b11) ? rcosc_in : gpio[4];
- assign gpio_out[5] = (xtal_output_dest == 2'b01) ? xtal_in : gpio[5];
- assign gpio_out[6] = (xtal_output_dest == 2'b10) ? xtal_in : gpio[6];
- assign gpio_out[7] = (xtal_output_dest == 2'b11) ? xtal_in : gpio[7];
- assign gpio_out[8] = (pll_output_dest == 2'b01) ? pll_clk : gpio[8];
- assign gpio_out[9] = (pll_output_dest == 2'b10) ? pll_clk : gpio[9];
- assign gpio_out[10] = (pll_output_dest == 2'b11) ? clk : gpio[10];
- assign gpio_out[11] = (trap_output_dest == 2'b01) ? trap : gpio[11];
- assign gpio_out[12] = (trap_output_dest == 2'b10) ? trap : gpio[12];
- assign gpio_out[13] = (trap_output_dest == 2'b11) ? trap : gpio[13];
- assign gpio_out[14] = (overtemp_dest == 2'b01) ? overtemp : gpio[14];
- assign gpio_out[15] = (overtemp_dest == 2'b10) ? overtemp : gpio[15];
-
- assign gpio_outenb[0] = (comp_output_dest == 2'b00) ? gpio_oeb[0] : 1'b0;
- assign gpio_outenb[1] = (comp_output_dest == 2'b00) ? gpio_oeb[1] : 1'b0;
- assign gpio_outenb[2] = (rcosc_output_dest == 2'b00) ? gpio_oeb[2] : 1'b0;
- assign gpio_outenb[3] = (rcosc_output_dest == 2'b00) ? gpio_oeb[3] : 1'b0;
- assign gpio_outenb[4] = (rcosc_output_dest == 2'b00) ? gpio_oeb[4] : 1'b0;
- assign gpio_outenb[5] = (xtal_output_dest == 2'b00) ? gpio_oeb[5] : 1'b0;
- assign gpio_outenb[6] = (xtal_output_dest == 2'b00) ? gpio_oeb[6] : 1'b0;
- assign gpio_outenb[7] = (xtal_output_dest == 2'b00) ? gpio_oeb[7] : 1'b0;
- assign gpio_outenb[8] = (pll_output_dest == 2'b00) ? gpio_oeb[8] : 1'b0;
- assign gpio_outenb[9] = (pll_output_dest == 2'b00) ? gpio_oeb[9] : 1'b0;
- assign gpio_outenb[10] = (pll_output_dest == 2'b00) ? gpio_oeb[10] : 1'b0;
- assign gpio_outenb[11] = (trap_output_dest == 2'b00) ? gpio_oeb[11] : 1'b0;
- assign gpio_outenb[12] = (trap_output_dest == 2'b00) ? gpio_oeb[12] : 1'b0;
- assign gpio_outenb[13] = (trap_output_dest == 2'b00) ? gpio_oeb[13] : 1'b0;
- assign gpio_outenb[14] = (overtemp_dest == 2'b00) ? gpio_oeb[14] : 1'b0;
- assign gpio_outenb[15] = (overtemp_dest == 2'b00) ? gpio_oeb[15] : 1'b0;
-
- assign gpio_pullup[0] = (comp_output_dest == 2'b00) ? gpio_pu[0] : 1'b0;
- assign gpio_pullup[1] = (comp_output_dest == 2'b00) ? gpio_pu[1] : 1'b0;
- assign gpio_pullup[2] = (rcosc_output_dest == 2'b00) ? gpio_pu[2] : 1'b0;
- assign gpio_pullup[3] = (rcosc_output_dest == 2'b00) ? gpio_pu[3] : 1'b0;
- assign gpio_pullup[4] = (rcosc_output_dest == 2'b00) ? gpio_pu[4] : 1'b0;
- assign gpio_pullup[5] = (xtal_output_dest == 2'b00) ? gpio_pu[5] : 1'b0;
- assign gpio_pullup[6] = (xtal_output_dest == 2'b00) ? gpio_pu[6] : 1'b0;
- assign gpio_pullup[7] = (xtal_output_dest == 2'b00) ? gpio_pu[7] : 1'b0;
- assign gpio_pullup[8] = (pll_output_dest == 2'b00) ? gpio_pu[8] : 1'b0;
- assign gpio_pullup[9] = (pll_output_dest == 2'b00) ? gpio_pu[9] : 1'b0;
- assign gpio_pullup[10] = (pll_output_dest == 2'b00) ? gpio_pu[10] : 1'b0;
- assign gpio_pullup[11] = (trap_output_dest == 2'b00) ? gpio_pu[11] : 1'b0;
- assign gpio_pullup[12] = (trap_output_dest == 2'b00) ? gpio_pu[12] : 1'b0;
- assign gpio_pullup[13] = (trap_output_dest == 2'b00) ? gpio_pu[13] : 1'b0;
- assign gpio_pullup[14] = (overtemp_dest == 2'b00) ? gpio_pu[14] : 1'b0;
- assign gpio_pullup[15] = (overtemp_dest == 2'b00) ? gpio_pu[15] : 1'b0;
-
- assign gpio_pulldown[0] = (comp_output_dest == 2'b00) ? gpio_pd[0] : 1'b0;
- assign gpio_pulldown[1] = (comp_output_dest == 2'b00) ? gpio_pd[1] : 1'b0;
- assign gpio_pulldown[2] = (rcosc_output_dest == 2'b00) ? gpio_pd[2] : 1'b0;
- assign gpio_pulldown[3] = (rcosc_output_dest == 2'b00) ? gpio_pd[3] : 1'b0;
- assign gpio_pulldown[4] = (rcosc_output_dest == 2'b00) ? gpio_pd[4] : 1'b0;
- assign gpio_pulldown[5] = (xtal_output_dest == 2'b00) ? gpio_pd[5] : 1'b0;
- assign gpio_pulldown[6] = (xtal_output_dest == 2'b00) ? gpio_pd[6] : 1'b0;
- assign gpio_pulldown[7] = (xtal_output_dest == 2'b00) ? gpio_pd[7] : 1'b0;
- assign gpio_pulldown[8] = (pll_output_dest == 2'b00) ? gpio_pd[8] : 1'b0;
- assign gpio_pulldown[9] = (pll_output_dest == 2'b00) ? gpio_pd[9] : 1'b0;
- assign gpio_pulldown[10] = (pll_output_dest == 2'b00) ? gpio_pd[10] : 1'b0;
- assign gpio_pulldown[11] = (trap_output_dest == 2'b00) ? gpio_pd[11] : 1'b0;
- assign gpio_pulldown[12] = (trap_output_dest == 2'b00) ? gpio_pd[12] : 1'b0;
- assign gpio_pulldown[13] = (trap_output_dest == 2'b00) ? gpio_pd[13] : 1'b0;
- assign gpio_pulldown[14] = (overtemp_dest == 2'b00) ? gpio_pd[14] : 1'b0;
- assign gpio_pulldown[15] = (overtemp_dest == 2'b00) ? gpio_pd[15] : 1'b0;
-
- // Convert GPIO signals to s8 pad signals
- convert_gpio_sigs convert_gpio_bit [15:0] (
- .gpio_out(gpio_out),
- .gpio_outenb(gpio_outenb),
- .gpio_pu(gpio_pullup),
- .gpio_pd(gpio_pulldown),
- .gpio_out_pad(gpio_out_pad),
- .gpio_outenb_pad(gpio_outenb_pad),
- .gpio_inenb_pad(gpio_inenb_pad),
- .gpio_mode1_pad(gpio_mode1_pad),
- .gpio_mode0_pad(gpio_mode0_pad)
- );
-
- wire irq_7, irq_8;
-
- assign irq_7 = (irq_7_inputsrc == 2'b01) ? gpio_in_pad[0] :
- (irq_7_inputsrc == 2'b10) ? gpio_in_pad[1] :
- (irq_7_inputsrc == 2'b11) ? gpio_in_pad[2] : 1'b0;
- assign irq_8 = (irq_8_inputsrc == 2'b01) ? gpio_in_pad[3] :
- (irq_8_inputsrc == 2'b10) ? gpio_in_pad[4] :
- (irq_8_inputsrc == 2'b11) ? gpio_in_pad[5] : 1'b0;
-
- assign ram_wenb = (mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ?
- {~mem_wstrb[3], ~mem_wstrb[2], ~mem_wstrb[1], ~mem_wstrb[0]} : 4'b1111;
- assign ram_addr = mem_addr[11:2];
- assign ram_wdata = mem_wdata; // Just for naming conventions.
-
- reg [31:0] irq;
- wire irq_stall = 0;
- wire irq_uart = 0;
-
- always @* begin
- irq = 0;
- irq[3] = irq_stall;
- irq[4] = irq_uart;
- irq[5] = irq_pin;
- irq[6] = irq_spi;
- irq[7] = irq_7;
- irq[8] = irq_8;
- irq[9] = comp_output_dest[0] & comp_output_dest[1] & comp_in;
- irq[10] = overtemp_dest[0] & overtemp_dest[1] & overtemp;
- end
-
- wire mem_valid;
- wire mem_instr;
- wire mem_ready;
- wire [31:0] mem_addr;
- wire [31:0] mem_wdata;
- wire [3:0] mem_wstrb;
- wire [31:0] mem_rdata;
-
- wire spimem_ready;
- wire [31:0] spimem_rdata;
-
- reg ram_ready;
- wire [31:0] ram_rdata;
-
- assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
- assign iomem_wstrb = mem_wstrb;
- assign iomem_addr = mem_addr;
- assign iomem_wdata = mem_wdata;
-
- wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000);
- wire [31:0] spimemio_cfgreg_do;
-
- wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004);
- wire [31:0] simpleuart_reg_div_do;
-
- wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008);
- wire [31:0] simpleuart_reg_dat_do;
- wire simpleuart_reg_dat_wait;
-
- assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel ||
- simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait);
-
- assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata :
- spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do :
- simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
-
- picorv32 #(
- .STACKADDR(STACKADDR),
- .PROGADDR_RESET(PROGADDR_RESET),
- .PROGADDR_IRQ(32'h 0000_0000),
- .BARREL_SHIFTER(1),
- .COMPRESSED_ISA(1),
- .ENABLE_MUL(1),
- .ENABLE_DIV(1),
- .ENABLE_IRQ(1),
- .ENABLE_IRQ_QREGS(0)
- ) cpu (
- .clk (clk ),
- .resetn (resetn ),
- .mem_valid (mem_valid ),
- .mem_instr (mem_instr ),
- .mem_ready (mem_ready ),
- .mem_addr (mem_addr ),
- .mem_wdata (mem_wdata ),
- .mem_wstrb (mem_wstrb ),
- .mem_rdata (mem_rdata ),
- .irq (irq ),
- .trap (trap )
- );
-
- spimemio spimemio (
- .clk (clk),
- .resetn (resetn),
- .valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000),
- .ready (spimem_ready),
- .addr (mem_addr[23:0]),
- .rdata (spimem_rdata),
-
- .flash_csb (flash_csb ),
- .flash_clk (flash_clk ),
-
- .flash_csb_oeb (flash_csb_oeb),
- .flash_clk_oeb (flash_clk_oeb),
-
- .flash_io0_oeb (flash_io0_oeb),
- .flash_io1_oeb (flash_io1_oeb),
- .flash_io2_oeb (flash_io2_oeb),
- .flash_io3_oeb (flash_io3_oeb),
-
- .flash_csb_ieb (flash_csb_ieb),
- .flash_clk_ieb (flash_clk_ieb),
-
- .flash_io0_ieb (flash_io0_ieb),
- .flash_io1_ieb (flash_io1_ieb),
- .flash_io2_ieb (flash_io2_ieb),
- .flash_io3_ieb (flash_io3_ieb),
-
- .flash_io0_do (flash_io0_do),
- .flash_io1_do (flash_io1_do),
- .flash_io2_do (flash_io2_do),
- .flash_io3_do (flash_io3_do),
-
- .flash_io0_di (flash_io0_di),
- .flash_io1_di (flash_io1_di),
- .flash_io2_di (flash_io2_di),
- .flash_io3_di (flash_io3_di),
-
- .cfgreg_we(spimemio_cfgreg_sel ? mem_wstrb : 4'b 0000),
- .cfgreg_di(mem_wdata),
- .cfgreg_do(spimemio_cfgreg_do)
- );
-
- simpleuart simpleuart (
- .clk (clk ),
- .resetn (resetn ),
-
- .ser_tx (ser_tx ),
- .ser_rx (ser_rx ),
-
- .reg_div_we (simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000),
- .reg_div_di (mem_wdata),
- .reg_div_do (simpleuart_reg_div_do),
-
- .reg_dat_we (simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0),
- .reg_dat_re (simpleuart_reg_dat_sel && !mem_wstrb),
- .reg_dat_di (mem_wdata),
- .reg_dat_do (simpleuart_reg_dat_do),
- .reg_dat_wait(simpleuart_reg_dat_wait)
- );
-
- always @(posedge clk)
- ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
-
- // PicoSoC memory mapped IP
- // 2 ADCs (1 multiplexed from internal signals, including core 1.8V VDD,
- // DAC output, comparator input, external input)
- // 1 DAC
- // 1 comparator (1 end tied to DAC, other could be shared w/ADC input)
- // 1 RC oscillator (output can be tied to one or both ADC clocks)
- // 1 crystal oscillator (output to level-shift-down = 3V buffer powered at 1.8V)
- // 1 1.8V regulator (sets VDD on padframe)
- // 1 bandgap
- // 1 power-on-reset (POR)
- // 1 temperature alarm
-
- // 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) 1.8V regulator enable (default on)
- // 3) bandgap enable (default on)
- // 4) picorv32 internal debug signals (TBD)
- // 5) additional picorv32 IRQ (TBD)
- // 6) PLL enables (default on)
- // 7) 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:
- // NOTE:
-
- // SPI master: 0x02000000 (control)
- // UART: 0x02000004-8 (clock, data)
- // GPIO: 0x03000000 (in/out, pu/pd, data)
- // ADC0: 0x03000020
- // ADC1: 0x03000040
- // DAC: 0x03000060
- // comparator: 0x03000080
- // RC osc: 0x030000a0
- // SPI slave: 0x030000c0 (read-only)
-
- // Memory map details:
- // GPIO: 32 channels total.
- // addr 0x03000000 data (16 bits)
- // addr 0x03000001 out (=1) or in (=0) (default 0)
- // addr 0x03000002 pu (=1) or none (=0) (default 0)
- // addr 0x03000003 pd (=1) or none (=0) (default 0)
- // addr 0x03000004-f reserved (may be used for other pad I/O)
- //
- // ADC0: addr 0x03000020 enable
- // addr 0x03000021 data (read-only)
- // addr 0x03000022 done (read-only)
- // addr 0x03000023 start conversion
- // addr 0x03000024 clock source (RC osc, SPI clk, xtal, core)
- // addr 0x03000025 input source (core VDD, ext, DAC, comp in)
- //
- // ADC1: addr 0x03000040 enable
- // addr 0x03000041 data (read-only)
- // addr 0x03000042 done (read-only)
- // addr 0x03000043 start conversion
- // addr 0x03000044 clock source (RC osc, SPI clk, xtal, core)
- // addr 0x03000045 input source (bg, ext, I/O vdd, gnd)
- //
- // DAC: addr 0x03000060 enable
- // addr 0x03000061 value
- //
- // comparator: addr 0x03000080 enable
- // addr 0x03000081 value
- // addr 0x03000082 input source (DAC, bg, core VDD, ext)
- // addr 0x03000083 output dest (ext gpio pin 0-1, IRQ, none)
- //
- // bandgap: addr 0x03000090 enable
- //
- // RC osc: addr 0x030000a0 enable
- // addr 0x030000a1 output dest (ext gpio pin 2-4)
- //
- // SPI slave: addr 0x030000c0 SPI configuration
- // addr 0x030000c1 xtal osc, reg, bg enables
- // addr 0x030000c2 PLL enables, trim
- // addr 0x030000c3 manufacturer ID
- // addr 0x030000c4 product ID
- // addr 0x030000c5 product mask revision
- // Xtal mon: addr 0x030000c6 xtal osc output dest (ext gpio pin 5-7)
- // PLL mon: addr 0x030000c7 PLL output dest (ext gpio pin 8-10)
- // trap mon: addr 0x030000c8 trap output dest (ext gpio pin 11-13)
- // IRQ7 src: addr 0x030000c9 IRQ 7 source (ext gpio pin 0-3)
- // IRQ8 src: addr 0x030000ca IRQ 8 source (ext gpio pin 4-7)
- // Analog: addr 0x030000cb analog output select (DAC, bg)
- //
- // Overtemp: addr 0x030000e0 over-temperature alarm enable
- // addr 0x030000e1 over-temperature alarm data
- // addr 0x030000e2 output dest (ext gpio pin 14-15, IRQ)
-
- always @(posedge clk) begin
- if (!resetn) begin
- gpio <= 0;
- gpio_oeb <= 16'hffff;
- gpio_pu <= 0;
- gpio_pd <= 0;
- adc0_ena <= 0;
- adc0_convert <= 0;
- adc0_clksrc <= 0;
- adc0_inputsrc <= 0;
- adc1_ena <= 0;
- adc1_convert <= 0;
- adc1_clksrc <= 0;
- adc1_inputsrc <= 0;
- dac_ena <= 0;
- dac_value <= 0;
- comp_ena <= 0;
- comp_ninputsrc <= 0;
- comp_pinputsrc <= 0;
- rcosc_ena <= 0;
- comp_output_dest <= 0;
- rcosc_output_dest <= 0;
- overtemp_dest <= 0;
- overtemp_ena <= 0;
- pll_output_dest <= 0;
- xtal_output_dest <= 0;
- trap_output_dest <= 0;
- irq_7_inputsrc <= 0;
- irq_8_inputsrc <= 0;
- analog_out_sel <= 0;
- opamp_ena <= 0;
- opamp_bias_ena <= 0;
- bg_ena <= 0;
-
- end else begin
- iomem_ready <= 0;
- if (iomem_valid && !iomem_ready && iomem_addr[31:8] == 24'h030000) begin
- iomem_ready <= 1;
- if (iomem_addr[7:0] == 8'h00) begin
- iomem_rdata <= {gpio_out, gpio_in_pad};
- if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0];
- if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8];
- end else if (iomem_addr[7:0] == 8'h04) begin
- iomem_rdata <= {16'd0, gpio_oeb};
- if (iomem_wstrb[0]) gpio_oeb[ 7: 0] <= iomem_wdata[ 7: 0];
- if (iomem_wstrb[1]) gpio_oeb[15: 8] <= iomem_wdata[15: 8];
- end else if (iomem_addr[7:0] == 8'h08) begin
- iomem_rdata <= {16'd0, gpio_pu};
- if (iomem_wstrb[0]) gpio_pu[ 7: 0] <= iomem_wdata[ 7: 0];
- if (iomem_wstrb[1]) gpio_pu[15: 8] <= iomem_wdata[15: 8];
- end else if (iomem_addr[7:0] == 8'h0c) begin
- iomem_rdata <= {16'd0, gpio_pu};
- if (iomem_wstrb[0]) gpio_pd[ 7: 0] <= iomem_wdata[ 7: 0];
- if (iomem_wstrb[1]) gpio_pd[15: 8] <= iomem_wdata[15: 8];
- end else if (iomem_addr[7:0] == 8'h10) begin
- iomem_rdata <= {31'd0, adc0_ena};
- if (iomem_wstrb[0]) adc0_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h14) begin
- iomem_rdata <= {22'd0, adc0_data};
- end else if (iomem_addr[7:0] == 8'h18) begin
- iomem_rdata <= {31'd0, adc0_done};
- end else if (iomem_addr[7:0] == 8'h1c) begin
- iomem_rdata <= {31'd0, adc0_convert};
- if (iomem_wstrb[0]) adc0_convert <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h20) begin
- iomem_rdata <= {30'd0, adc0_clksrc};
- if (iomem_wstrb[0]) adc0_clksrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h24) begin
- iomem_rdata <= {30'd0, adc0_inputsrc};
- if (iomem_wstrb[0]) adc0_inputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h30) begin
- iomem_rdata <= {31'd0, adc1_ena};
- if (iomem_wstrb[0]) adc1_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h34) begin
- iomem_rdata <= {22'd0, adc1_data};
- end else if (iomem_addr[7:0] == 8'h38) begin
- iomem_rdata <= {31'd0, adc1_done};
- end else if (iomem_addr[7:0] == 8'h3c) begin
- iomem_rdata <= {31'd0, adc1_convert};
- if (iomem_wstrb[0]) adc1_convert <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h40) begin
- iomem_rdata <= {30'd0, adc1_clksrc};
- if (iomem_wstrb[0]) adc1_clksrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h44) begin
- iomem_rdata <= {30'd0, adc1_inputsrc};
- if (iomem_wstrb[0]) adc1_inputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h50) begin
- iomem_rdata <= {31'd0, dac_ena};
- if (iomem_wstrb[0]) dac_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h54) begin
- iomem_rdata <= {22'd0, dac_value};
- if (iomem_wstrb[0]) dac_value[7:0] <= iomem_wdata[7:0];
- if (iomem_wstrb[1]) dac_value[9:8] <= iomem_wdata[9:8];
- end else if (iomem_addr[7:0] == 8'h60) begin
- iomem_rdata <= {31'd0, comp_ena};
- if (iomem_wstrb[0]) comp_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h64) begin
- iomem_rdata <= {30'd0, comp_ninputsrc};
- if (iomem_wstrb[0]) comp_ninputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h68) begin
- iomem_rdata <= {30'd0, comp_pinputsrc};
- if (iomem_wstrb[0]) comp_pinputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h6c) begin
- iomem_rdata <= {30'd0, comp_output_dest};
- if (iomem_wstrb[0]) comp_output_dest <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h70) begin
- iomem_rdata <= {31'd0, rcosc_ena};
- if (iomem_wstrb[0]) rcosc_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'h74) begin
- iomem_rdata <= {30'd0, rcosc_output_dest};
- if (iomem_wstrb[0]) rcosc_output_dest <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'h80) begin
- iomem_rdata <= {24'd0, spi_ro_config};
- end else if (iomem_addr[7:0] == 8'h84) begin
- iomem_rdata <= {22'd0, spi_ro_pll_div, spi_ro_pll_sel, spi_ro_xtal_ena, spi_ro_reg_ena};
- end else if (iomem_addr[7:0] == 8'h88) begin
- iomem_rdata <= {5'd0, spi_ro_pll_trim, spi_ro_pll_dco_ena};
- end else if (iomem_addr[7:0] == 8'h8c) begin
- iomem_rdata <= {20'd0, spi_ro_mfgr_id};
- end else if (iomem_addr[7:0] == 8'h90) begin
- iomem_rdata <= {24'd0, spi_ro_prod_id};
- end else if (iomem_addr[7:0] == 8'h94) begin
- iomem_rdata <= {28'd0, spi_ro_mask_rev};
- end else if (iomem_addr[7:0] == 8'h98) begin
- iomem_rdata <= {31'd0, ext_clk_sel};
- end else if (iomem_addr[7:0] == 8'ha0) begin
- iomem_rdata <= {30'd0, xtal_output_dest};
- if (iomem_wstrb[0]) xtal_output_dest <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'ha4) begin
- iomem_rdata <= {30'd0, pll_output_dest};
- if (iomem_wstrb[0]) pll_output_dest <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'ha8) begin
- iomem_rdata <= {30'd0, trap_output_dest};
- if (iomem_wstrb[0]) trap_output_dest <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'hb0) begin
- iomem_rdata <= {30'd0, irq_7_inputsrc};
- if (iomem_wstrb[0]) irq_7_inputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'hb4) begin
- iomem_rdata <= {30'd0, irq_8_inputsrc};
- if (iomem_wstrb[0]) irq_8_inputsrc <= iomem_wdata[1:0];
- end else if (iomem_addr[7:0] == 8'hc0) begin
- iomem_rdata <= {31'd0, analog_out_sel};
- if (iomem_wstrb[0]) analog_out_sel <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'hc4) begin
- iomem_rdata <= {31'd0, opamp_bias_ena};
- if (iomem_wstrb[0]) opamp_bias_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'hc8) begin
- iomem_rdata <= {31'd0, opamp_ena};
- if (iomem_wstrb[0]) opamp_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'hd0) begin
- iomem_rdata <= {31'd0, bg_ena};
- if (iomem_wstrb[0]) bg_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'he0) begin
- iomem_rdata <= {31'd0, overtemp_ena};
- if (iomem_wstrb[0]) overtemp_ena <= iomem_wdata[0];
- end else if (iomem_addr[7:0] == 8'he4) begin
- iomem_rdata <= {31'd0, overtemp};
- end else if (iomem_addr[7:0] == 8'he8) begin
- iomem_rdata <= {30'd0, overtemp_dest};
- if (iomem_wstrb[0]) overtemp_dest <= iomem_wdata[1:0];
- end
- end
- end
- end
-
- openstriVe_soc_mem #(.WORDS(MEM_WORDS)) picomem (
- .clk(clk),
- .ena(resetn),
- .wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0),
- .addr(mem_addr[23:2]),
- .wdata(mem_wdata),
- .rdata(ram_rdata)
- );
-endmodule
-
-`include "picorv32.v"
-`include "spimemio.v"
-`include "simpleuart.v"
-
-// Implementation note:
-// Replace the following two modules with wrappers for your SRAM cells.
-
-module openstriVe_soc_regs (
- input clk, 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 openstriVe_soc_mem #(
- parameter integer WORDS = 256
-) (
- input clk,
- input ena,
- input [3:0] wen,
- input [21:0] addr,
- input [31:0] wdata,
- output reg [31:0] rdata
-);
- reg [31:0] mem [0:WORDS-1];
-
- always @(posedge clk) begin
- if (ena == 1'b1) 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
- end
-endmodule
-
-/* Convert the standard set of GPIO signals: input, output, output_enb,
- * pullup, and pulldown into the set needed by the s8 GPIO pads:
- * input, output, output_enb, input_enb, mode. Note that dm[2] on
- * thepads is always equal to dm[1] in this setup, so mode is shown as
- * only a 2-bit signal.
- *
- * This module is bit-sliced. Instantiate once for each GPIO pad.
- */
-
-module convert_gpio_sigs (
- input gpio_out,
- input gpio_outenb,
- input gpio_pu,
- input gpio_pd,
- output gpio_out_pad,
- output gpio_outenb_pad,
- output gpio_inenb_pad,
- output gpio_mode1_pad,
- output gpio_mode0_pad
-);
-
- assign gpio_out_pad = (gpio_pu == 1'b0 && gpio_pd == 1'b0) ? gpio_out :
- (gpio_pu == 1'b1) ? 1 : 0;
-
- assign gpio_outenb_pad = (gpio_outenb == 1'b0) ? 0 :
- (gpio_pu == 1'b1 || gpio_pd == 1'b1) ? 0 : 1;
-
- assign gpio_inenb_pad = ~gpio_outenb;
-
- assign gpio_mode1_pad = ~gpio_outenb_pad;
- assign gpio_mode0_pad = gpio_outenb;
-
-endmodule
-
diff --git a/verilog/rtl/striVe_spi.v b/verilog/rtl/striVe_spi.v
index 323ecf6..54643c3 100644
--- a/verilog/rtl/striVe_spi.v
+++ b/verilog/rtl/striVe_spi.v
@@ -40,12 +40,12 @@
module striVe_spi(
`ifdef LVS
- vdd, vss,
+ vdd, vss,
`endif
- RSTB, SCK, SDI, CSB, SDO, sdo_enb,
- xtal_ena, reg_ena, pll_dco_ena, pll_div, pll_sel,
- pll_trim, pll_bypass, irq, reset, RST, trap,
- mfgr_id, prod_id, mask_rev_in, mask_rev);
+ RSTB, SCK, SDI, CSB, SDO, sdo_enb,
+ xtal_ena, reg_ena, pll_dco_ena, pll_div, pll_sel,
+ pll_trim, pll_bypass, irq, reset, RST, trap,
+ mfgr_id, prod_id, mask_rev_in, mask_rev);
`ifdef LVS
inout vdd; // 3.3V supply
@@ -97,16 +97,16 @@
// Instantiate the SPI slave module
spi_slave U1 (
- .SCK(SCK),
- .SDI(SDI),
- .CSB(CSB),
- .SDO(SDO),
- .sdoenb(sdo_enb),
- .idata(odata),
- .odata(idata),
- .oaddr(iaddr),
- .rdstb(rdstb),
- .wrstb(wrstb)
+ .SCK(SCK),
+ .SDI(SDI),
+ .CSB(CSB),
+ .SDO(SDO),
+ .sdoenb(sdo_enb),
+ .idata(odata),
+ .odata(idata),
+ .oaddr(iaddr),
+ .rdstb(rdstb),
+ .wrstb(wrstb)
);
wire [11:0] mfgr_id;
@@ -121,74 +121,74 @@
// All values are 1-4 bits and no shadow registers are required.
assign odata =
- (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed)
- (iaddr == 8'h01) ? {mask_rev, mfgr_id[11:8]} : // Mask rev (metal programmed)
- (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed)
- (iaddr == 8'h03) ? prod_id : // Product ID (fixed)
- (iaddr == 8'h04) ? {5'b00000, xtal_ena, reg_ena, pll_dco_ena} :
- (iaddr == 8'h05) ? {7'b0000000, pll_bypass} :
- (iaddr == 8'h06) ? {7'b0000000, irq} :
- (iaddr == 8'h07) ? {7'b0000000, reset} :
- (iaddr == 8'h08) ? {7'b0000000, trap} :
- (iaddr == 8'h09) ? pll_trim[7:0] :
- (iaddr == 8'h0a) ? pll_trim[15:8] :
- (iaddr == 8'h0b) ? pll_trim[23:16] :
- (iaddr == 8'h0c) ? {6'b000000, pll_trim[25:24]} :
- (iaddr == 8'h0d) ? {5'b00000, pll_sel} :
- (iaddr == 8'h0e) ? {3'b000, pll_div} :
- 8'h00; // Default
+ (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed)
+ (iaddr == 8'h01) ? {mask_rev, mfgr_id[11:8]} : // Mask rev (metal programmed)
+ (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed)
+ (iaddr == 8'h03) ? prod_id : // Product ID (fixed)
+ (iaddr == 8'h04) ? {5'b00000, xtal_ena, reg_ena, pll_dco_ena} :
+ (iaddr == 8'h05) ? {7'b0000000, pll_bypass} :
+ (iaddr == 8'h06) ? {7'b0000000, irq} :
+ (iaddr == 8'h07) ? {7'b0000000, reset} :
+ (iaddr == 8'h08) ? {7'b0000000, trap} :
+ (iaddr == 8'h09) ? pll_trim[7:0] :
+ (iaddr == 8'h0a) ? pll_trim[15:8] :
+ (iaddr == 8'h0b) ? pll_trim[23:16] :
+ (iaddr == 8'h0c) ? {6'b000000, pll_trim[25:24]} :
+ (iaddr == 8'h0d) ? {5'b00000, pll_sel} :
+ (iaddr == 8'h0e) ? {3'b000, pll_div} :
+ 8'h00; // Default
// Register mapping and I/O to slave module
always @(posedge SCK or negedge RSTB) begin
- if (RSTB == 1'b0) begin
- // Set trim for PLL at (almost) slowest rate (~90MHz). However,
- // pll_trim[12] must be set to zero for proper startup.
- pll_trim <= 26'b11111111111110111111111111;
- pll_sel <= 3'b000;
- pll_div <= 5'b00100; // Default divide-by-8
- xtal_ena <= 1'b1;
- reg_ena <= 1'b1;
- pll_dco_ena <= 1'b1; // Default free-running PLL
- pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL)
- irq <= 1'b0;
- reset <= 1'b0;
- end else if (wrstb == 1'b1) begin
- case (iaddr)
- 8'h04: begin
- pll_dco_ena <= idata[2];
- reg_ena <= idata[1];
- xtal_ena <= idata[0];
- end
- 8'h05: begin
- pll_bypass <= idata[0];
- end
- 8'h06: begin
- irq <= idata[0];
- end
- 8'h07: begin
- reset <= idata[0];
- end
- // Register 8 is read-only
- 8'h09: begin
- pll_trim[7:0] <= idata;
- end
- 8'h0a: begin
- pll_trim[15:8] <= idata;
- end
- 8'h0b: begin
- pll_trim[23:16] <= idata;
- end
- 8'h0c: begin
- pll_trim[25:24] <= idata[1:0];
- end
- 8'h0d: begin
- pll_sel <= idata[2:0];
- end
- 8'h0e: begin
- pll_div <= idata[4:0];
- end
- endcase // (iaddr)
- end
+ if (RSTB == 1'b0) begin
+ // Set trim for PLL at (almost) slowest rate (~90MHz). However,
+ // pll_trim[12] must be set to zero for proper startup.
+ pll_trim <= 26'b11111111111110111111111111;
+ pll_sel <= 3'b000;
+ pll_div <= 5'b00100; // Default divide-by-8
+ xtal_ena <= 1'b1;
+ reg_ena <= 1'b1;
+ pll_dco_ena <= 1'b1; // Default free-running PLL
+ pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL)
+ irq <= 1'b0;
+ reset <= 1'b0;
+ end else if (wrstb == 1'b1) begin
+ case (iaddr)
+ 8'h04: begin
+ pll_dco_ena <= idata[2];
+ reg_ena <= idata[1];
+ xtal_ena <= idata[0];
+ end
+ 8'h05: begin
+ pll_bypass <= idata[0];
+ end
+ 8'h06: begin
+ irq <= idata[0];
+ end
+ 8'h07: begin
+ reset <= idata[0];
+ end
+ // Register 8 is read-only
+ 8'h09: begin
+ pll_trim[7:0] <= idata;
+ end
+ 8'h0a: begin
+ pll_trim[15:8] <= idata;
+ end
+ 8'h0b: begin
+ pll_trim[23:16] <= idata;
+ end
+ 8'h0c: begin
+ pll_trim[25:24] <= idata[1:0];
+ end
+ 8'h0d: begin
+ pll_sel <= idata[2:0];
+ end
+ 8'h0e: begin
+ pll_div <= idata[4:0];
+ end
+ endcase // (iaddr)
+ end
end
endmodule // striVe_spi_orig
diff --git a/verilog/rtl/sysctrl.v b/verilog/rtl/sysctrl.v
new file mode 100644
index 0000000..5daf5b3
--- /dev/null
+++ b/verilog/rtl/sysctrl.v
@@ -0,0 +1,219 @@
+module sysctrl_wb #(
+ parameter BASE_ADR = 32'h2F00_0000,
+ parameter OSC_ENA = 8'h00,
+ parameter OSC_OUT = 8'h04,
+ parameter XTAL_OUT = 8'h08,
+ parameter PLL_OUT = 8'h0c,
+ parameter TRAP_OUT = 8'h10,
+ parameter IRQ7_SRC = 8'h14,
+ parameter IRQ8_SRC = 8'h18,
+ parameter OVERTEMP_ENA = 8'h1c,
+ parameter OVERTEMP_DATA = 8'h20,
+ parameter OVERTEMP_OUT = 8'h24
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_dat_i,
+ input [31:0] wb_adr_i,
+ input [3:0] wb_sel_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+ input wb_we_i,
+
+ output [31:0] wb_dat_o,
+ output wb_ack_o,
+
+ input overtemp,
+
+ output rcosc_ena,
+ output [1:0] rcosc_output_dest,
+ output [1:0] xtal_output_dest,
+ output [1:0] pll_output_dest,
+ output [1:0] trap_output_dest,
+ output [1:0] irq_7_inputsrc,
+ output [1:0] irq_8_inputsrc,
+ output overtemp_ena,
+ output [1:0] overtemp_dest
+
+);
+
+ wire resetn;
+ wire valid;
+ wire ready;
+ wire [3:0] iomem_we;
+
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_stb_i && wb_cyc_i;
+
+ assign iomem_we = wb_sel_i & {4{wb_we_i}};
+ assign wb_ack_o = ready;
+
+ sysctrl #(
+ .BASE_ADR(BASE_ADR),
+ .OSC_ENA(OSC_ENA),
+ .OSC_OUT(OSC_OUT),
+ .XTAL_OUT(XTAL_OUT),
+ .PLL_OUT(PLL_OUT),
+ .TRAP_OUT(TRAP_OUT),
+ .IRQ7_SRC(IRQ7_SRC),
+ .IRQ8_SRC(IRQ8_SRC),
+ .OVERTEMP_ENA(OVERTEMP_ENA),
+ .OVERTEMP_DATA(OVERTEMP_DATA),
+ .OVERTEMP_OUT(OVERTEMP_OUT)
+ ) sysctrl (
+ .clk(wb_clk_i),
+ .resetn(resetn),
+
+ .overtemp(overtemp),
+
+ .iomem_addr(wb_adr_i),
+ .iomem_valid(valid),
+ .iomem_wstrb(iomem_we),
+ .iomem_wdata(wb_dat_i),
+ .iomem_rdata(wb_dat_o),
+ .iomem_ready(ready),
+
+ .rcosc_ena(rcosc_ena), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ?
+ .rcosc_output_dest(rcosc_output_dest),
+ .xtal_output_dest(xtal_output_dest),
+ .pll_output_dest(pll_output_dest),
+ .trap_output_dest(trap_output_dest),
+
+ .irq_7_inputsrc(irq_7_inputsrc),
+ .irq_8_inputsrc(irq_8_inputsrc),
+
+ .overtemp_ena(overtemp_ena),
+ .overtemp_dest(overtemp_dest)
+ );
+
+endmodule
+
+module sysctrl #(
+ parameter BASE_ADR = 32'h2300_0000,
+ parameter OSC_ENA = 8'h00,
+ parameter OSC_OUT = 8'h04,
+ parameter XTAL_OUT = 8'h08,
+ parameter PLL_OUT = 8'h0c,
+ parameter TRAP_OUT = 8'h10,
+ parameter IRQ7_SRC = 8'h14,
+ parameter IRQ8_SRC = 8'h18,
+ parameter OVERTEMP_ENA = 8'h1c,
+ parameter OVERTEMP_DATA = 8'h20,
+ parameter OVERTEMP_OUT = 8'h24
+) (
+ input clk,
+ input resetn,
+
+ input overtemp,
+
+ input [31:0] iomem_addr,
+ input iomem_valid,
+ input [3:0] iomem_wstrb,
+ input [31:0] iomem_wdata,
+ output reg [31:0] iomem_rdata,
+ output reg iomem_ready,
+
+ output rcosc_ena,
+ output [1:0] rcosc_output_dest,
+ output [1:0] xtal_output_dest,
+ output [1:0] pll_output_dest,
+ output [1:0] trap_output_dest,
+ output [1:0] irq_7_inputsrc,
+ output [1:0] irq_8_inputsrc,
+ output overtemp_ena,
+ output [1:0] overtemp_dest
+);
+ reg rcosc_ena;
+ reg [1:0] rcosc_output_dest;
+ reg [1:0] xtal_output_dest;
+ reg [1:0] pll_output_dest;
+ reg [1:0] trap_output_dest;
+ reg [1:0] irq_7_inputsrc;
+ reg [1:0] irq_8_inputsrc;
+ reg overtemp_ena;
+ reg [1:0] overtemp_dest;
+
+ assign osc_ena_sel = (iomem_addr[7:0] == OSC_ENA);
+ assign osc_out_sel = (iomem_addr[7:0] == OSC_OUT);
+ assign pll_out_sel = (iomem_addr[7:0] == PLL_OUT);
+ assign trap_out_sel = (iomem_addr[7:0] == TRAP_OUT);
+ assign xtal_out_sel = (iomem_addr[7:0] == XTAL_OUT);
+
+ assign irq7_sel = (iomem_addr[7:0] == IRQ7_SRC);
+ assign irq8_sel = (iomem_addr[7:0] == IRQ8_SRC);
+
+ assign overtemp_sel = (iomem_addr[7:0] == OVERTEMP_DATA);
+ assign overtemp_ena_sel = (iomem_addr[7:0] == OVERTEMP_ENA);
+ assign overtemp_dest_sel = (iomem_addr[7:0] == OVERTEMP_OUT);
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ rcosc_ena <= 0;
+ rcosc_output_dest <= 0;
+ pll_output_dest <= 0;
+ xtal_output_dest <= 0;
+ trap_output_dest <= 0;
+ irq_7_inputsrc <= 0;
+ irq_8_inputsrc <= 0;
+ overtemp_dest <= 0;
+ overtemp_ena <= 0;
+ end else begin
+ iomem_ready <= 0;
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ iomem_ready <= 1'b 1;
+
+ if (osc_ena_sel) begin
+ iomem_rdata <= {31'd0, rcosc_ena};
+ if (iomem_wstrb[0])
+ rcosc_ena <= iomem_wdata[0];
+
+ end else if (osc_out_sel) begin
+ iomem_rdata <= {30'd0, rcosc_output_dest};
+ if (iomem_wstrb[0])
+ rcosc_output_dest <= iomem_wdata[1:0];
+
+ end else if (xtal_out_sel) begin
+ iomem_rdata <= {30'd0, xtal_output_dest};
+ if (iomem_wstrb[0])
+ xtal_output_dest <= iomem_wdata[1:0];
+
+ end else if (pll_out_sel) begin
+ iomem_rdata <= {30'd0, pll_output_dest};
+ if (iomem_wstrb[0])
+ pll_output_dest <= iomem_wdata[1:0];
+
+ end else if (trap_out_sel) begin
+ iomem_rdata <= {30'd0, trap_output_dest};
+ if (iomem_wstrb[0])
+ trap_output_dest <= iomem_wdata[1:0];
+
+ end else if (irq7_sel) begin
+ iomem_rdata <= {30'd0, irq_7_inputsrc};
+ if (iomem_wstrb[0])
+ irq_7_inputsrc <= iomem_wdata[1:0];
+
+ end else if (irq8_sel) begin
+ iomem_rdata <= {30'd0, irq_8_inputsrc};
+ if (iomem_wstrb[0])
+ irq_8_inputsrc <= iomem_wdata[1:0];
+
+ end else if (overtemp_ena_sel) begin
+ iomem_rdata <= {31'd0, overtemp_ena};
+ if (iomem_wstrb[0])
+ overtemp_ena <= iomem_wdata[0];
+
+ end else if (overtemp_sel) begin
+ iomem_rdata <= {31'd0, overtemp};
+
+ end else if (overtemp_dest_sel) begin
+ iomem_rdata <= {30'd0, overtemp_dest};
+ if (iomem_wstrb[0])
+ overtemp_dest <= iomem_wdata[1:0];
+
+ end
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/wb_intercon.v b/verilog/rtl/wb_intercon.v
new file mode 100644
index 0000000..3a2c58f
--- /dev/null
+++ b/verilog/rtl/wb_intercon.v
@@ -0,0 +1,57 @@
+module wb_intercon #(
+ parameter DW = 32, // Data Width
+ parameter AW = 32, // Address Width
+ parameter NS = 6 // Number of Slaves
+) (
+ // Master Interface
+ input [AW-1:0] wbm_adr_i,
+ input wbm_stb_i,
+
+ output reg [DW-1:0] wbm_dat_o,
+ output wbm_ack_o,
+
+ // Slave Interface
+ input [NS*DW-1:0] wbs_dat_i,
+ input [NS-1:0] wbs_ack_i,
+ output [NS-1:0] wbs_stb_o
+);
+ parameter [NS*AW-1:0] ADR_MASK = { // Page & Sub-page bits
+ {8'hFF, {24{1'b0}} },
+ {8'hFF, {24{1'b0}} },
+ {8'hFF, {24{1'b0}} },
+ {8'hFF, {24{1'b0}} },
+ {8'hFF, {24{1'b0}} },
+ {8'hFF, {24{1'b0}} }
+ };
+ parameter [NS*AW-1:0] SLAVE_ADR = {
+ {8'h28, {24{1'b0}} }, // Flash Configuration Register
+ {8'h23, {24{1'b0}} }, // System Control
+ {8'h21, {24{1'b0}} }, // GPIOs
+ {8'h20, {24{1'b0}} }, // UART
+ {8'h10, {24{1'b0}} }, // Flash
+ {8'h00, {24{1'b0}} } // RAM
+ };
+
+ wire [NS-1: 0] slave_sel;
+
+ // Address decoder
+ genvar iS;
+ generate
+ for (iS = 0; iS < NS; iS = iS + 1) begin
+ assign slave_sel[iS] =
+ ((wbm_adr_i & ADR_MASK[(iS+1)*AW-1:iS*AW]) == SLAVE_ADR[(iS+1)*AW-1:iS*AW]);
+ end
+ endgenerate
+
+ // Data-out Assignment
+ assign wbm_ack_o = |(wbs_ack_i & slave_sel);
+ assign wbs_stb_o = {NS{wbm_stb_i}} & slave_sel;
+
+ integer i;
+ always @(*) begin
+ wbm_dat_o = {DW{1'b0}};
+ for (i=0; i<(NS*DW); i=i+1)
+ wbm_dat_o[i%DW] = wbm_dat_o[i%DW] | (slave_sel[i/DW] & wbs_dat_i[i]);
+ end
+
+endmodule
\ No newline at end of file