feat: add sort of IPs

This commit is contained in:
maksyuki committed 2025-01-31 01:16:07 +08:00
1 parent fe5f447c2f
commit a16e2d8441
5 files changed
+861 -278

No files matched your search

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