blob: 23b9ece937c359b249025c89eebbf5295f6caf1a [file] [log] [blame]
/*
* 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 "raven_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 raven_soc I/O so that raven_soc.v itself is fully synthesizable */
/* and routable with qflow as-is. */
`define PICORV32_REGS raven_soc_regs
module raven_soc (
input pll_clk,
input ext_clk,
input ext_clk_sel,
input ext_reset,
input reset,
`ifdef SRAM_COMPILER
// Main SRAM, including clk and resetn above
output [3:0] ram_wenb,
output [9:0] ram_addr,
output [31:0] ram_wdata,
input [31:0] ram_rdata,
`endif
// Memory mapped I/O signals
output [15:0] gpio_out,
input [15:0] gpio_in,
output [15:0] gpio_pullup,
output [15:0] gpio_pulldown,
output [15:0] gpio_outenb,
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_cp_ena,
input spi_ro_pll_vco_ena,
input spi_ro_pll_bias_ena,
input [3: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_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
);
/* parameter integer MEM_WORDS = 256; */
/* Increase scratchpad memory to 1K words */
parameter integer MEM_WORDS = 128;
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;
wire [15:0] gpio_pulldown;
wire [15:0] gpio_outenb;
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;
// Reset assignment. "reset" comes from POR, while "ext_reset"
// comes from standalone SPI (and is normally zero unless
// activated from the SPI).
assign resetn = ~(reset | ext_reset);
// Clock assignment
assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk;
// 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;
wire irq_7, irq_8;
assign irq_7 = (irq_7_inputsrc == 2'b01) ? gpio_in[0] :
(irq_7_inputsrc == 2'b10) ? gpio_in[1] :
(irq_7_inputsrc == 2'b11) ? gpio_in[2] : 1'b0;
assign irq_8 = (irq_8_inputsrc == 2'b01) ? gpio_in[3] :
(irq_8_inputsrc == 2'b10) ? gpio_in[4] :
(irq_8_inputsrc == 2'b11) ? gpio_in[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_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};
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 <= {30'd0, spi_ro_xtal_ena, spi_ro_reg_ena};
end else if (iomem_addr[7:0] == 8'h88) begin
iomem_rdata <= {25'd0, spi_ro_pll_trim, spi_ro_pll_cp_ena, spi_ro_pll_vco_ena, spi_ro_pll_bias_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
`ifndef SRAM_COMPILER
raven_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),
.wdata(mem_wdata),
.rdata(ram_rdata)
);
`endif
endmodule
`include "picorv32.v"
`include "spimemio.v"
`include "simpleuart.v"
// Implementation note:
// Replace the following two modules with wrappers for your SRAM cells.
module raven_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
/* Removing original raven_soc_mem and replacing it with */
/* an external SRAM compiled on the X-Fab memory compiler */
`ifndef SRAM_COMPILER
module raven_soc_mem #(
parameter integer WORDS = 256
) (
input clk,
input ena,
input [3:0] wen,
input [31:0] addr,
input [31:0] wdata,
output reg [31:0] rdata
);
wire [63:0] rdata_w;
sram_16_256_8_scn4m_subm sram1 (.clk0(clk), .csb0(ena), .web0(wen[0]), .wmask0({wen[0], wen[0]}), .addr0(addr[7:0]), .din0(wdata[7:0]), .dout0(rdata_w[15:0]));
sram_16_256_8_scn4m_subm sram2 (.clk0(clk), .csb0(ena), .web0(wen[1]), .wmask0({wen[1], wen[1]}), .addr0(addr[15:8]), .din0(wdata[15:8]), .dout0(rdata_w[31:16]));
sram_16_256_8_scn4m_subm sram3 (.clk0(clk), .csb0(ena), .web0(wen[2]), .wmask0({wen[2], wen[2]}), .addr0(addr[23:16]), .din0(wdata[23:16]), .dout0(rdata_w[47:32]));
sram_16_256_8_scn4m_subm sram4 (.clk0(clk), .csb0(ena), .web0(wen[3]), .wmask0({wen[3], wen[3]}), .addr0(addr[31:24]), .din0(wdata[31:24]), .dout0(rdata_w[63:48]));
always @(posedge clk) begin
if (ena == 1'b1) begin
rdata <= wen[0]? rdata_w[31:0] : rdata_w[63:32];
end
end
endmodule
`endif