Started adding RTL for the Caravel project
diff --git a/verilog/rtl/striVe_soc.v b/verilog/rtl/striVe_soc.v
new file mode 100644
index 0000000..1899a99
--- /dev/null
+++ b/verilog/rtl/striVe_soc.v
@@ -0,0 +1,837 @@
+/*
+ *  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
+