initial commit
diff --git a/verilog/dv/dummy_slave.v b/verilog/dv/dummy_slave.v new file mode 100644 index 0000000..857ce0e --- /dev/null +++ b/verilog/dv/dummy_slave.v
@@ -0,0 +1,33 @@ +module dummy_slave( + input wb_clk_i, + input wb_rst_i, + + input wb_stb_i, + input wb_cyc_i, + input wb_we_i, + input [3:0] wb_sel_i, + input [31:0] wb_adr_i, + input [31:0] wb_dat_i, + + output reg [31:0] wb_dat_o, + output reg wb_ack_o +); + reg [31:0] store; + + wire valid = wb_cyc_i & wb_stb_i; + + always @(posedge wb_clk_i) begin + if (wb_rst_i == 1'b 1) begin + wb_ack_o <= 1'b 0; + end else begin + if (wb_we_i == 1'b 1) begin + if (wb_sel_i[0]) store[7:0] <= wb_dat_i[7:0]; + if (wb_sel_i[1]) store[15:8] <= wb_dat_i[15:8]; + if (wb_sel_i[2]) store[23:16] <= wb_dat_i[23:16]; + if (wb_sel_i[3]) store[31:24] <= wb_dat_i[31:24]; + end + wb_dat_o <= store; + wb_ack_o <= valid & !wb_ack_o; + end + end +endmodule \ No newline at end of file
diff --git a/verilog/dv/harness/mgmt_soc/Makefile b/verilog/dv/harness/mgmt_soc/Makefile new file mode 100644 index 0000000..c934af3 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/Makefile
@@ -0,0 +1,18 @@ +# ---- Test patterns for project striVe ---- + +.SUFFIXES: +.SILENT: clean all + +PATTERNS = gpio mem uart perf hkspi sysctrl xbar + +all: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + done + +clean: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make clean ) ; \ + done + +.PHONY: clean all
diff --git a/verilog/dv/harness/mgmt_soc/defs.h b/verilog/dv/harness/mgmt_soc/defs.h new file mode 100644 index 0000000..e2d777f --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/defs.h
@@ -0,0 +1,96 @@ +#ifndef _STRIVE_H_ +#define _STRIVE_H_ + +#include <stdint.h> +#include <stdbool.h> + +// a pointer to this is a null pointer, but the compiler does not +// know that because "sram" is a linker symbol from sections.lds. +extern uint32_t sram; + +// Pointer to firmware flash routines +extern uint32_t flashio_worker_begin; +extern uint32_t flashio_worker_end; + +// IOs: UART (0x2000_0000), GPIO (0x2100_0000), LA (0x2200_0000) +#define reg_uart_clkdiv (*(volatile uint32_t*)0x20000000) +#define reg_uart_data (*(volatile uint32_t*)0x20000004) + +#define reg_gpio_data (*(volatile uint32_t*)0x21000000) +#define reg_gpio_ena (*(volatile uint32_t*)0x21000004) +#define reg_gpio_pu (*(volatile uint32_t*)0x21000008) +#define reg_gpio_pd (*(volatile uint32_t*)0x2100000c) + +#define reg_la0_data (*(volatile uint32_t*)0x22000000) +#define reg_la1_data (*(volatile uint32_t*)0x22000004) +#define reg_la2_data (*(volatile uint32_t*)0x22000008) +#define reg_la3_data (*(volatile uint32_t*)0x2200000c) + +#define reg_la0_ena (*(volatile uint32_t*)0x22000010) +#define reg_la1_ena (*(volatile uint32_t*)0x22000014) +#define reg_la2_ena (*(volatile uint32_t*)0x22000018) +#define reg_la3_ena (*(volatile uint32_t*)0x2200001c) + +// Flash Control SPI Configuration (2D00_0000) +#define reg_spictrl (*(volatile uint32_t*)0x2D000000) + +// House-Keeping SPI Read-Only Registers (0x2E00_0000) +#define reg_spi_config (*(volatile uint32_t*)0x2E000000) +#define reg_spi_enables (*(volatile uint32_t*)0x2E000004) +#define reg_spi_pll_config (*(volatile uint32_t*)0x2E000008) +#define reg_spi_mfgr_id (*(volatile uint32_t*)0x2E00000c) +#define reg_spi_prod_id (*(volatile uint32_t*)0x2E000010) +#define reg_spi_mask_rev (*(volatile uint32_t*)0x2E000014) +#define reg_spi_pll_bypass (*(volatile uint32_t*)0x2E000018) + +// System Area (0x2F00_0000) +#define reg_rcosc_enable (*(volatile uint32_t*)0x2F000000) +#define reg_rcosc_out_dest (*(volatile uint32_t*)0x2F000004) + +#define reg_xtal_out_dest (*(volatile uint32_t*)0x2F000008) +#define reg_pll_out_dest (*(volatile uint32_t*)0x2F00000c) +#define reg_trap_out_dest (*(volatile uint32_t*)0x2F000010) + +#define reg_irq7_source (*(volatile uint32_t*)0x2F000014) +#define reg_irq8_source (*(volatile uint32_t*)0x2F000018) + +#define reg_overtemp_ena (*(volatile uint32_t*)0x2F00001c) +#define reg_overtemp_data (*(volatile uint32_t*)0x2F000020) +#define reg_overtemp_out_dest (*(volatile uint32_t*)0x2F000024) + +// Crosbbar Slave Addresses (0x8000_0000 - 0xB000_0000) +#define qspi_ctrl_slave (*(volatile uint32_t*)0x80000000) +#define storage_area_slave (*(volatile uint32_t*)0x90000000) +#define mega_any_slave1 (*(volatile uint32_t*)0xA0000000) +#define mega_any_slave2 (*(volatile uint32_t*)0xB0000000) + +// #define reg_adc0_ena (*(volatile uint32_t*)0x21000010) +// #define reg_adc0_data (*(volatile uint32_t*)0x21000014) +// #define reg_adc0_done (*(volatile uint32_t*)0x21000018) +// #define reg_adc0_convert (*(volatile uint32_t*)0x2100001c) +// #define reg_adc0_clk_source (*(volatile uint32_t*)0x21000020) +// #define reg_adc0_input_source (*(volatile uint32_t*)0x21000024) + +// #define reg_adc1_ena (*(volatile uint32_t*)0x21000030) +// #define reg_adc1_data (*(volatile uint32_t*)0x21000034) +// #define reg_adc1_done (*(volatile uint32_t*)0x21000038) +// #define reg_adc1_convert (*(volatile uint32_t*)0x2100003c) +// #define reg_adc1_clk_source (*(volatile uint32_t*)0x21000040) +// #define reg_adc1_input_source (*(volatile uint32_t*)0x21000044) + +// #define reg_dac_ena (*(volatile uint32_t*)0x21000050) +// #define reg_dac_data (*(volatile uint32_t*)0x21000054) + +// #define reg_comp_enable (*(volatile uint32_t*)0x21000060) +// #define reg_comp_n_source (*(volatile uint32_t*)0x21000064) +// #define reg_comp_p_source (*(volatile uint32_t*)0x21000068) +// #define reg_comp_out_dest (*(volatile uint32_t*)0x2100006c) + +// #define reg_analog_out_sel (*(volatile uint32_t*)0x210000c0) +// #define reg_analog_out_bias_ena (*(volatile uint32_t*)0x210000c4) +// #define reg_analog_out_ena (*(volatile uint32_t*)0x210000c8) + +// #define reg_bandgap_ena (*(volatile uint32_t*)0x210000d0) + +// -------------------------------------------------------- +#endif
diff --git a/verilog/dv/harness/mgmt_soc/gpio/Makefile b/verilog/dv/harness/mgmt_soc/gpio/Makefile new file mode 100644 index 0000000..e9253c0 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/gpio/Makefile
@@ -0,0 +1,33 @@ +.SUFFIXES: + +PATTERN = gpio + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/gpio/gpio.c b/verilog/dv/harness/mgmt_soc/gpio/gpio.c new file mode 100644 index 0000000..17a4885 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/gpio/gpio.c
@@ -0,0 +1,39 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +/* + GPIO Test + Tests PU and PD on the lower 8 pins while being driven from outside + Tests Writing to the upper 8 pins + Tests reading from the lower 8 pins +*/ +void main() +{ + int i; + + /* Lower 8 pins are input and upper 8 pins are o/p */ + reg_gpio_data = 0; + reg_gpio_ena = 0x00ff; + + // change the pull up and pull down (checked by the TB) + reg_gpio_data = 0xA000; + reg_gpio_pu = 0x000f; + reg_gpio_pd = 0x00f0; + + reg_gpio_data = 0x0B00; + reg_gpio_pu = 0x00f0; + reg_gpio_pd = 0x000f; + + reg_gpio_pu = 0x000f; + reg_gpio_pd = 0x00f0; + + // read the lower 8 pins, add 1 then o/p the result + // checked by the TB + reg_gpio_data = 0xAB00; + while (1){ + int x = reg_gpio_data & 0xff; + reg_gpio_data = (x+1) << 8; + } +} +
diff --git a/verilog/dv/harness/mgmt_soc/gpio/gpio_tb.v b/verilog/dv/harness/mgmt_soc/gpio/gpio_tb.v new file mode 100644 index 0000000..c20ba26 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/gpio/gpio_tb.v
@@ -0,0 +1,194 @@ +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" + +module gpio_tb; + reg XCLK; + + wire VDD3V3; + assign VDD3V3 = 1'b1; + + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + // Analog input pin values + adc_h = 0.0; + adc_l = 0.0; + adc_0 = 0.0; + adc_1 = 0.0; + comp_n = 0.0; + comp_p = 0.0; + #2000; + adc_h = 3.25; + adc_l = 0.05; + adc_0 = 1.0; + adc_1 = 1.5; + comp_n = 2.0; + comp_p = 2.5; + end + + initial begin + $dumpfile("gpio.vcd"); + $dumpvars(0, gpio_tb); + + // Repeat cycles of 1000 XCLK edges as needed to complete testbench + repeat (25) begin + repeat (1000) @(posedge XCLK); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test GPIO (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + wire [15:0] gpio; + + reg [7:0] gpio_lo; + wire [7:0] gpio_hi; + + assign gpio[7:0] = gpio_lo; + assign gpio_hi = gpio[15:8]; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + reg SDI, CSB, SCK, RSTB; + wire SDO; + + // Transactor + initial begin + gpio_lo = {8{1'bz}}; + wait(gpio_hi==8'hA0); + gpio_lo = 8'hF0; + wait(gpio_hi==8'h0B); + gpio_lo = 8'h0F; + wait(gpio_hi==8'hAB); + gpio_lo = 8'h0; + repeat (1000) @(posedge XCLK); + gpio_lo = 8'h1; + repeat (1000) @(posedge XCLK); + gpio_lo = 8'h3; + end + + // Monitor + initial begin + wait(gpio_hi==8'hA0); + wait(gpio[7:0]==8'hF0); + wait(gpio_hi==8'h0B); + wait(gpio[7:0]==8'h0F); + wait(gpio_hi==8'hAB); + wait(gpio[7:0]==8'h00); + wait(gpio_hi==8'h01); + wait(gpio[7:0]==8'h01); + wait(gpio_hi==8'h02); + wait(gpio[7:0]==8'h03); + wait(gpio_hi==8'h04); + $display("Monitor: Test GPIO (RTL) Passed"); + $finish; + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; // Apply CSB to start transmission + end + + always @(gpio) begin + #1 $display("GPIO state = %b (%d - %d)", gpio, gpio_hi, gpio_lo); + end + + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("gpio.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/hkspi/Makefile b/verilog/dv/harness/mgmt_soc/hkspi/Makefile new file mode 100644 index 0000000..2850baa --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/hkspi/Makefile
@@ -0,0 +1,31 @@ +.SUFFIXES: + +PATTERN = hkspi + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< /dev/stdout | sed -e '1 s/@10000000/@00000000/; 2,65537 d;' > $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/hkspi/hkspi.c b/verilog/dv/harness/mgmt_soc/hkspi/hkspi.c new file mode 100644 index 0000000..d572727 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/hkspi/hkspi.c
@@ -0,0 +1,38 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} + +// -------------------------------------------------------- + +void main() +{ + // Set clock to 64 kbaud + reg_uart_clkdiv = 625; + + // NOTE: Crystal is running in simulation at 5MHz + // Internal clock is 8x crystal, or 40MHz + // Divided by clkdiv is 64 kHz + // So at this crystal rate, use clkdiv = 4167 for 9600 baud. + + // This should appear at the output, received by the testbench UART. + print("\n"); + print(" ____ _ ____ ____\n"); + print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n"); + print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n"); + print(" | __/| | (_| (_) |__) | (_) | |___\n"); + print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); +} +
diff --git a/verilog/dv/harness/mgmt_soc/hkspi/hkspi_tb.v b/verilog/dv/harness/mgmt_soc/hkspi/hkspi_tb.v new file mode 100644 index 0000000..0edc43d --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/hkspi/hkspi_tb.v
@@ -0,0 +1,256 @@ +/* + StriVe housekeeping SPI testbench. +*/ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" +`include "tbuart.v" + +module hkspi_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + + wire [15:0] gpio; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + wire SDO; + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + // Analog input pin values (static) + adc_h = 0.0; + adc_l = 0.0; + adc_0 = 0.0; + adc_1 = 0.0; + comp_n = 0.0; + comp_p = 0.0; + end + + // The main testbench is here. Put the housekeeping SPI into + // pass-thru mode and read several bytes from the flash SPI. + + // First define tasks for SPI functions + + task start_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b0; + #50; + end + endtask + + task end_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b1; + #50; + end + endtask + + task write_byte; + input [7:0] odata; + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_byte; + output [7:0] idata; + begin + SCK <= 1'b0; + SDI <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_write_byte + (input [7:0] odata, + output [7:0] idata); + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + integer i; + + // Now drive the digital signals on the housekeeping SPI + reg [7:0] tbdata; + + initial begin + $dumpfile("hkspi.vcd"); + $dumpvars(0, hkspi_tb); + + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + // Delay, then bring chip out of reset + #1000; + RSTB <= 1'b1; + #2000; + + // First do a normal read from the housekeeping SPI to + // make sure the housekeeping SPI works. + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + $display("Read data = 0x%02x (should be 0x05)", tbdata); + + // Toggle external reset + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h01); // Data = 0x01 (apply external reset) + end_csb(); + + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h00); // Data = 0x00 (release external reset) + end_csb(); + + // Read all registers (0 to 8) + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h00); // Address (register 3 = product ID) + read_byte(tbdata); + $display("Read register 0 = 0x%02x (should be 0x00)", tbdata); + if(tbdata != 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 1 = 0x%02x (should be 0x04)", tbdata); + if(tbdata != 8'h14) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 2 = 0x%02x (should be 0x56)", tbdata); + if(tbdata != 8'h56) begin $display("Monitor: Test HK SPI (RTL) Failed, %02x", tbdata); $finish; end + read_byte(tbdata); + $display("Read register 3 = 0x%02x (should be 0x05)", tbdata); + if(tbdata != 8'h05) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 4 = 0x%02x (should be 0x07)", tbdata); + if(tbdata != 8'h07) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 5 = 0x%02x (should be 0x01)", tbdata); + if(tbdata != 8'h01) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 6 = 0x%02x (should be 0x00)", tbdata); + if(tbdata != 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 7 = 0x%02x (should be 0x00)", tbdata); + if(tbdata != 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 8 = 0x%02x (should be 0x00)", tbdata); + if(tbdata != 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + + end_csb(); + + $display("Monitor: Test HK SPI (RTL) Passed"); + + #10000; + $finish; + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = 1'b1; + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (tbuart_rx), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("hkspi.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + + tbuart tbuart ( + .ser_rx(tbuart_rx) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/mem/Makefile b/verilog/dv/harness/mgmt_soc/mem/Makefile new file mode 100644 index 0000000..d63df1b --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/mem/Makefile
@@ -0,0 +1,34 @@ + +.SUFFIXES: + +PATTERN = mem + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/mem/mem.c b/verilog/dv/harness/mgmt_soc/mem/mem.c new file mode 100644 index 0000000..0bff65d --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/mem/mem.c
@@ -0,0 +1,51 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +/* + Memory Test + It uses GPIO to flag the success or failure of the test +*/ +unsigned int ints[10]; +unsigned short shorts[10]; +unsigned char bytes[10]; + +void main() +{ + int i; + + /* All GPIO pins are configured to be output */ + reg_gpio_data = 0; + reg_gpio_ena = 0x0000; + + // start test + reg_gpio_data = 0xA040; + + // Test Word R/W + for(i=0; i<10; i++) + ints[i] = i*5000 + 10000; + + for(i=0; i<10; i++) + if((i*5000+10000) != ints[i]) reg_gpio_data = 0xAB40; + reg_gpio_data = 0xAB41; + + // Test Half Word R/W + reg_gpio_data = 0xA020; + for(i=0; i<10; i++) + shorts[i] = i*500 + 100; + + for(i=0; i<10; i++) + if((i*500+100) != shorts[i]) reg_gpio_data = 0xAB20; + reg_gpio_data = 0xAB21; + + // Test byte R/W + reg_gpio_data = 0xA010; + for(i=0; i<10; i++) + bytes[i] = i*5 + 10; + + for(i=0; i<10; i++) + if((i*5+10) != bytes[i]) reg_gpio_data = 0xAB10; + reg_gpio_data = 0xAB11; + +} +
diff --git a/verilog/dv/harness/mgmt_soc/mem/mem_tb.v b/verilog/dv/harness/mgmt_soc/mem/mem_tb.v new file mode 100644 index 0000000..09bb0a7 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/mem/mem_tb.v
@@ -0,0 +1,189 @@ +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" + +module mem_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + wire [15:0] gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + wire SDO; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + // Analog input pin values + adc_h = 0.0; + adc_l = 0.0; + adc_0 = 0.0; + adc_1 = 0.0; + comp_n = 0.0; + comp_p = 0.0; + #2000; + adc_h = 3.25; + adc_l = 0.05; + adc_0 = 1.0; + adc_1 = 1.5; + comp_n = 2.0; + comp_p = 2.5; + end + + initial begin + $dumpfile("mem.vcd"); + $dumpvars(0, mem_tb); + + // Repeat cycles of 1000 XCLK edges as needed to complete testbench + repeat (100) begin + repeat (1000) @(posedge XCLK); + //$display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test MEM (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; // Apply CSB to start transmission + end + + always @(gpio) begin + if(gpio == 16'hA040) begin + $display("Mem Test (word rw) started"); + end + else if(gpio == 16'hAB40) begin + $display("%c[1;31m",27); + $display("Monitor: Test MEM (RTL) [word rw] failed"); + $display("%c[0m",27); + $finish; + end + else if(gpio == 16'hAB41) begin + $display("Monitor: Test MEM (RTL) [word rw] passed"); + end + else if(gpio == 16'hA020) begin + $display("Mem Test (short rw) started"); + end + else if(gpio == 16'hAB20) begin + $display("%c[1;31m",27); + $display("Monitor: Test MEM (RTL) [short rw] failed"); + $display("%c[0m",27); + $finish; + end + else if(gpio == 16'hAB21) begin + $display("Monitor: Test MEM (RTL) [short rw] passed"); + end + else if(gpio == 16'hA010) begin + $display("Mem Test (byte rw) started"); + end + else if(gpio == 16'hAB10) begin + $display("%c[1;31m",27); + $display("Monitor: Test MEM (RTL) [byte rw] failed"); + $display("%c[0m",27); + $finish; + end + else if(gpio == 16'hAB11) begin + $display("Monitor: Test MEM (RTL) [byte rw] passed"); + $finish; + end + + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD3V3 = 1'b1; + assign VDD1V8 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("mem.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/perf/Makefile b/verilog/dv/harness/mgmt_soc/perf/Makefile new file mode 100644 index 0000000..dad371f --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/perf/Makefile
@@ -0,0 +1,34 @@ +.SUFFIXES: + +PATTERN = perf + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/perf/perf.c b/verilog/dv/harness/mgmt_soc/perf/perf.c new file mode 100644 index 0000000..4dc34b1 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/perf/perf.c
@@ -0,0 +1,33 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +/* + Performance Test + It uses GPIO to flag the success or failure of the test +*/ +unsigned int ints[50]; +unsigned short shorts[50]; +unsigned char bytes[50]; + +int main() +{ + int i; + int sum = 0; + + /* All GPIO pins are configured to be output */ + reg_gpio_data = 0; + reg_gpio_ena = 0x0000; + + // start test + reg_gpio_data = 0xA000; + + for(i=0; i<100; i++) + sum+=(sum + i); + + reg_gpio_data = 0xAB00; + + return sum; + +} +
diff --git a/verilog/dv/harness/mgmt_soc/perf/perf_tb.v b/verilog/dv/harness/mgmt_soc/perf/perf_tb.v new file mode 100644 index 0000000..edd10ba --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/perf/perf_tb.v
@@ -0,0 +1,165 @@ +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" + +module striVe_perf_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + wire [15:0] gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + wire SDO; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + // Analog input pin values + adc_h = 0.0; + adc_l = 0.0; + adc_0 = 0.0; + adc_1 = 0.0; + comp_n = 0.0; + comp_p = 0.0; + #2000; + adc_h = 3.25; + adc_l = 0.05; + adc_0 = 1.0; + adc_1 = 1.5; + comp_n = 2.0; + comp_p = 2.5; + end + + reg [31:0] kcycles; + + initial begin + $dumpfile("striVe_perf.vcd"); + $dumpvars(0, striVe_perf_tb); + + kcycles = 0; + // Repeat cycles of 1000 XCLK edges as needed to complete testbench + repeat (150) begin + repeat (1000) @(posedge XCLK); + //$display("+1000 cycles"); + kcycles<=kcycles+1; + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Performance (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; // Apply CSB to start transmission + end + + always @(gpio) begin + //#1 $display("GPIO state = %X ", gpio); + if(gpio == 16'hA000) begin + kcycles = 0; + $display("Performance Test started"); + end + else if(gpio == 16'hAB00) begin + //$display("Monitor: number of cycles/100 iterations: %d KCycles", kcycles); + $display("Monitor: Test Performance (RTL) passed [%0d KCycles]", kcycles); + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + assign VDD3V3 = 1'b1; + + harness uut ( + .vdd (VDD3V3 ), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx ( ), + .irq (1'b0 ), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("perf.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/sections.lds b/verilog/dv/harness/mgmt_soc/sections.lds new file mode 100644 index 0000000..4392c6d --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/sections.lds
@@ -0,0 +1,58 @@ +MEMORY { + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x400000 /* 4MB */ + RAM(xrw) : ORIGIN = 0x00000000, LENGTH = 0x400 /* 256 words ( 1024 ? ) */ +} + +SECTIONS { + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.srodata) /* .srodata sections (constants, strings, etc.) */ + *(.srodata*) /* .srodata*sections (constants, strings, etc.) */ + . = ALIGN(4); + _etext = .; /* define a global symbol at end of code */ + _sidata = _etext; /* This is used by the startup to initialize data */ + } >FLASH + + /* Initialized data section */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; + _ram_start = .; + . = ALIGN(4); + *(.data) + *(.data*) + *(.sdata) + *(.sdata*) + . = ALIGN(4); + _edata = .; + } >RAM + + /* Uninitialized data section */ + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + *(.bss*) + *(.sbss) + *(.sbss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; + } >RAM + + /* Define the start of the heap */ + .heap : + { + . = ALIGN(4); + _heap_start = .; + } >RAM +}
diff --git a/verilog/rtl/spiflash.v b/verilog/dv/harness/mgmt_soc/spiflash.v old mode 100755 new mode 100644 similarity index 100% rename from verilog/rtl/spiflash.v rename to verilog/dv/harness/mgmt_soc/spiflash.v
diff --git a/verilog/dv/harness/mgmt_soc/start.s b/verilog/dv/harness/mgmt_soc/start.s new file mode 100644 index 0000000..62a6f42 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/start.s
@@ -0,0 +1,159 @@ +.section .text + +start: + +# zero-initialize register file +addi x1, zero, 0 +# x2 (sp) is initialized by reset +addi x3, zero, 0 +addi x4, zero, 0 +addi x5, zero, 0 +addi x6, zero, 0 +addi x7, zero, 0 +addi x8, zero, 0 +addi x9, zero, 0 +addi x10, zero, 0 +addi x11, zero, 0 +addi x12, zero, 0 +addi x13, zero, 0 +addi x14, zero, 0 +addi x15, zero, 0 +addi x16, zero, 0 +addi x17, zero, 0 +addi x18, zero, 0 +addi x19, zero, 0 +addi x20, zero, 0 +addi x21, zero, 0 +addi x22, zero, 0 +addi x23, zero, 0 +addi x24, zero, 0 +addi x25, zero, 0 +addi x26, zero, 0 +addi x27, zero, 0 +addi x28, zero, 0 +addi x29, zero, 0 +addi x30, zero, 0 +addi x31, zero, 0 + +# zero initialize scratchpad memory +# setmemloop: +# sw zero, 0(x1) +# addi x1, x1, 4 +# blt x1, sp, setmemloop + +# copy data section +la a0, _sidata +la a1, _sdata +la a2, _edata +bge a1, a2, end_init_data +loop_init_data: +lw a3, 0(a0) +sw a3, 0(a1) +addi a0, a0, 4 +addi a1, a1, 4 +blt a1, a2, loop_init_data +end_init_data: + +# zero-init bss section +la a0, _sbss +la a1, _ebss +bge a0, a1, end_init_bss +loop_init_bss: +sw zero, 0(a0) +addi a0, a0, 4 +blt a0, a1, loop_init_bss +end_init_bss: + +# call main +call main +loop: +j loop + +.global flashio_worker_begin +.global flashio_worker_end + +.balign 4 + +flashio_worker_begin: +# a0 ... data pointer +# a1 ... data length +# a2 ... optional WREN cmd (0 = disable) + +# address of SPI ctrl reg +li t0, 0x28000000 + +# Set CS high, IO0 is output +li t1, 0x120 +sh t1, 0(t0) + +# Enable Manual SPI Ctrl +sb zero, 3(t0) + +# Send optional WREN cmd +beqz a2, flashio_worker_L1 +li t5, 8 +andi t2, a2, 0xff +flashio_worker_L4: +srli t4, t2, 7 +sb t4, 0(t0) +ori t4, t4, 0x10 +sb t4, 0(t0) +slli t2, t2, 1 +andi t2, t2, 0xff +addi t5, t5, -1 +bnez t5, flashio_worker_L4 +sb t1, 0(t0) + +# SPI transfer +flashio_worker_L1: + +# If byte count is zero, we're done +beqz a1, flashio_worker_L3 + +# Set t5 to count down 32 bits +li t5, 32 +# Load t2 from address a0 (4 bytes) +lw t2, 0(a0) + +flashio_worker_LY: +# Set t6 to count down 8 bits +li t6, 8 + +flashio_worker_L2: +# Clock out the bit (msb first) on IO0 and read bit in from IO1 +srli t4, t2, 31 +sb t4, 0(t0) +ori t4, t4, 0x10 +sb t4, 0(t0) +lbu t4, 0(t0) +andi t4, t4, 2 +srli t4, t4, 1 +slli t2, t2, 1 +or t2, t2, t4 + +# Decrement 32 bit count +addi t5, t5, -1 +bnez t5, flashio_worker_LX + +sw t2, 0(a0) +addi a0, a0, 4 +lw t2, 0(a0) + +flashio_worker_LX: +addi t6, t6, -1 +bnez t6, flashio_worker_L2 +addi a1, a1, -1 +bnez a1, flashio_worker_LY + +beqz t5, flashio_worker_L3 +sw t2, 0(a0) + +flashio_worker_L3: +# Back to MEMIO mode +li t1, 0x80 +sb t1, 3(t0) + +ret +.balign 4 +flashio_worker_end: +
diff --git a/verilog/dv/harness/mgmt_soc/sysctrl/Makefile b/verilog/dv/harness/mgmt_soc/sysctrl/Makefile new file mode 100644 index 0000000..0b43365 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/sysctrl/Makefile
@@ -0,0 +1,33 @@ +.SUFFIXES: + +PATTERN = sysctrl + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl.c b/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl.c new file mode 100644 index 0000000..a4a6762 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl.c
@@ -0,0 +1,43 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +/* + System Control Test + - Reads default value of SPI-Controlled registers + - Flags failure/success using gpio +*/ +void main() +{ + int i; + + reg_gpio_data = 0; + reg_gpio_ena = 0x0000; + + // start test + reg_gpio_data = 0xA040; + + // Read Product ID value + if(0x05 != reg_spi_prod_id) reg_gpio_data = 0xAB40; + reg_gpio_data = 0xAB41; + + // Read Manufacturer ID value + if(0x456 != reg_spi_mfgr_id) reg_gpio_data = 0xAB50; + reg_gpio_data = 0xAB51; + + // Read Mask revision + if(0x1 != reg_spi_mask_rev) reg_gpio_data = 0xAB60; + reg_gpio_data = 0xAB61; + + // Read PLL-Bypass + if(0x1 != reg_spi_pll_bypass) reg_gpio_data = 0xAB70; + reg_gpio_data = 0xAB71; + + if(0x7FFDFFF != reg_spi_pll_config) reg_gpio_data = 0xAB80; + reg_gpio_data = 0xAB81; + + // Read spi enables + if(0x83 != reg_spi_enables) reg_gpio_data = 0xAB90; + reg_gpio_data = 0xAB91; +} +
diff --git a/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl_tb.v b/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl_tb.v new file mode 100644 index 0000000..d1e4439 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/sysctrl/sysctrl_tb.v
@@ -0,0 +1,170 @@ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" + +module sysctrl_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + wire [15:0] gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + wire SDO; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + $dumpfile("sysctrl_tb.vcd"); + $dumpvars(0, sysctrl_tb); + repeat (25) begin + repeat (1000) @(posedge XCLK); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test GPIO (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + always @(gpio) begin + if(gpio == 16'hA040) begin + $display("System control Test started"); + end + else if(gpio == 16'hAB40) begin + $display("%c[1;31m",27); + $display("Monitor: System control (RTL) Test failed"); + $display("%c[0m",27); + $finish; + end + else if(gpio == 16'hAB41) begin + $display("Monitor: System control product ID read passed"); + end + else if(gpio == 16'hAB50) begin + $display("%c[1;31m",27); + $display("Monitor: System control manufacture ID read failed"); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB51) begin + $display("Monitor: System control manufacture ID read passed"); + end + else if(gpio == 16'hAB60) begin + $display("%c[1;31m",27); + $display("Monitor: System control mask rev read failed"); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB61) begin + $display("Monitor: System control mask rev read passed"); + end + else if(gpio == 16'hAB70) begin + $display("%c[1;31m",27); + $display("Monitor: System control pll-bypass read failed"); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB71) begin + $display("Monitor: System control pll-bypass read passed"); + end + else if(gpio == 16'hAB80) begin + $display("%c[1;31m",27); + $display("Monitor: System control pll-config read failed"); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB81) begin + $display("Monitor: System control pll-config read passed"); + end + else if(gpio == 16'hAB90) begin + $display("%c[1;31m",27); + $display("Monitor: System control spi-enables read failed"); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB91) begin + $display("Monitor: System control spi-enables read passed"); + $display("Monitor: Sysctrl (RTL) test passed."); + $finish; + end + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; // Apply CSB to start transmission + end + + always @(gpio) begin + #1 $display("GPIO state = %b ", gpio); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + assign VDD3V3 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("sysctrl.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/tbuart.v b/verilog/dv/harness/mgmt_soc/tbuart.v new file mode 100644 index 0000000..97c4283 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/tbuart.v
@@ -0,0 +1,89 @@ +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +/* tbuart --- mimic an external UART display, operating at 9600 baud */ +/* and accepting ASCII characters for display. */ + +/* To do: Match a known UART 3.3V 16x2 LCD display. However, it */ +/* should be possible on a testing system to interface to the UART */ +/* pins on a Raspberry Pi, also running at 3.3V. */ + +module tbuart ( + input ser_rx +); + reg [3:0] recv_state; + reg [2:0] recv_divcnt; + reg [7:0] recv_pattern; + reg [8*50-1:0] recv_buf_data; // 50 characters. Increase as needed for tests. + + reg clk; + + initial begin + clk <= 1'b0; + recv_state <= 0; + recv_divcnt <= 0; + recv_pattern <= 0; + recv_buf_data <= 0; + end + + // NOTE: Running at 3.0us clock period @ 5 clocks per bit = 15.0us per + // bit ~= 64 kbaud. Not tuned to any particular UART. Most run at + // 9600 baud default and will bounce up to higher baud rates when + // passed specific command words. + + always #1500 clk <= (clk === 1'b0); + + always @(posedge clk) begin + recv_divcnt <= recv_divcnt + 1; + case (recv_state) + 0: begin + if (!ser_rx) + recv_state <= 1; + recv_divcnt <= 0; + end + 1: begin + if (2*recv_divcnt > 3'd3) begin + recv_state <= 2; + recv_divcnt <= 0; + end + end + 10: begin + if (recv_divcnt > 3'd3) begin + // 0x0a = '\n' + if (recv_pattern == 8'h0a) begin + $display("output: %s", recv_buf_data); + end else begin + recv_buf_data <= {recv_buf_data, recv_pattern}; + end + recv_state <= 0; + end + end + default: begin + if (recv_divcnt > 3'd3) begin + recv_pattern <= {ser_rx, recv_pattern[7:1]}; + recv_state <= recv_state + 1; + recv_divcnt <= 0; + end + end + endcase + end + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/uart/Makefile b/verilog/dv/harness/mgmt_soc/uart/Makefile new file mode 100644 index 0000000..057be64 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/uart/Makefile
@@ -0,0 +1,35 @@ +# ---- Test patterns for project striVe ---- + +.SUFFIXES: + +PATTERN = uart + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/harness/mgmt_soc/uart/uart.c b/verilog/dv/harness/mgmt_soc/uart/uart.c new file mode 100644 index 0000000..fe362f8 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/uart/uart.c
@@ -0,0 +1,41 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} + +// -------------------------------------------------------- + +void main() +{ + // Set clock to 64 kbaud + reg_uart_clkdiv = 625; + + // NOTE: XCLK is running in simulation at 40MHz + // Divided by clkdiv is 64 kHz + // So at this crystal rate, use clkdiv = 4167 for 9600 baud. + + /* All GPIO pins are configured to be output */ + reg_gpio_data = 0; + reg_gpio_ena = 0x0000; + + // start test + reg_gpio_data = 0xA000; + + // This should appear at the output, received by the testbench UART. + print("\n"); + print("Monitor: Test UART (RTL) passed\n\n"); + reg_gpio_data = 0xAB00; +} +
diff --git a/verilog/dv/harness/mgmt_soc/uart/uart_tb.v b/verilog/dv/harness/mgmt_soc/uart/uart_tb.v new file mode 100644 index 0000000..56c76f2 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/uart/uart_tb.v
@@ -0,0 +1,154 @@ +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" +`include "tbuart.v" + +module uart_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + wire [15:0] gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + wire SDO; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #12.5 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + // Analog input pin values (static) + adc_h = 0.0; + adc_l = 0.0; + adc_0 = 0.0; + adc_1 = 0.0; + comp_n = 0.0; + comp_p = 0.0; + end + + initial begin + $dumpfile("uart.vcd"); + $dumpvars(0, uart_tb); + + $display("Wait for UART o/p"); + repeat (150) begin + repeat (10000) @(posedge XCLK); + // Diagnostic. . . interrupts output pattern. + end + $finish; + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; + end + + always @(gpio) begin + if(gpio == 16'hA000) begin + $display("UART Test started"); + end + else if(gpio == 16'hAB00) begin + #1000; + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + assign VDD3V3 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xo (), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (tbuart_rx), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("uart.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + + // Testbench UART + tbuart tbuart ( + .ser_rx(tbuart_rx) + ); + +endmodule
diff --git a/verilog/dv/harness/mgmt_soc/verify.log b/verilog/dv/harness/mgmt_soc/verify.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/verify.log
diff --git a/verilog/dv/harness/mgmt_soc/xbar/Makefile b/verilog/dv/harness/mgmt_soc/xbar/Makefile new file mode 100644 index 0000000..5302d06 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/xbar/Makefile
@@ -0,0 +1,32 @@ +.SUFFIXES: + +PATTERN = xbar + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex + iverilog -I ../ -I ../../../../ip -I ../../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +%.elf: %.c ../sections.lds ../start.s + /ef/apps/bin/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,../sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ ../start.s $< + +%.hex: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + /ef/apps/bin/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/harness/mgmt_soc/xbar/xbar.c b/verilog/dv/harness/mgmt_soc/xbar/xbar.c new file mode 100644 index 0000000..5565f1f --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/xbar/xbar.c
@@ -0,0 +1,41 @@ +#include "../defs.h" + +// -------------------------------------------------------- + +/* + Crosbbar Switch Test + - Reads default value of SPI-Controlled registers + - Flags failure/success using gpio +*/ +void main() +{ + int i; + + reg_gpio_data = 0; + reg_gpio_ena = 0x0000; + + // start test + reg_gpio_data = 0xA040; + + // Write & Read from QSPI CTRL Slave + qspi_ctrl_slave = 0xA0A1; + if(0xA0A1 != qspi_ctrl_slave) reg_gpio_data = 0xAB40; + reg_gpio_data = 0xAB41; + + // Write & Read from storage area Slave + storage_area_slave = 0xB0B1; + if(0xB0B1 != storage_area_slave) reg_gpio_data = 0xAB50; + reg_gpio_data = 0xAB51; + + // Write & Read from Mega Project 1st slave + mega_any_slave1 = 0xC0C1; + if(0xC0C1 != mega_any_slave1) reg_gpio_data = 0xAB60; + reg_gpio_data = 0xAB61; + + // Write & Read from Mega Project 1st slave + mega_any_slave2 = 0xD0D1; + if(0xD0D1 != mega_any_slave2) reg_gpio_data = 0xAB70; + reg_gpio_data = 0xAB71; + +} +
diff --git a/verilog/dv/harness/mgmt_soc/xbar/xbar_tb.v b/verilog/dv/harness/mgmt_soc/xbar/xbar_tb.v new file mode 100644 index 0000000..b9357f0 --- /dev/null +++ b/verilog/dv/harness/mgmt_soc/xbar/xbar_tb.v
@@ -0,0 +1,150 @@ + +`timescale 1 ns / 1 ps + +`include "harness.v" +`include "spiflash.v" + +module xbar_tb; + reg XCLK; + reg XI; + + reg real adc_h, adc_l; + reg real adc_0, adc_1; + reg real comp_n, comp_p; + reg SDI, CSB, SCK, RSTB; + + wire [15:0] gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + wire SDO; + + always #10 XCLK <= (XCLK === 1'b0); + always #220 XI <= (XI === 1'b0); + + initial begin + XI = 0; + XCLK = 0; + end + + initial begin + $dumpfile("xbar_tb.vcd"); + $dumpvars(0, xbar_tb); + repeat (25) begin + repeat (1000) @(posedge XCLK); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Crossbar Switch (RTL) Failed"); + $display("%c[0m", 27); + $finish; + end + + always @(gpio) begin + if(gpio == 16'hA040) begin + $display("Crossbar Switch Test started"); + end + else if(gpio == 16'hAB40) begin + $display("%c[1;31m",27); + $display("Monitor: Crossbar test R/W from QSPI CTRL slave failed."); + $display("%c[0m",27); + $finish; + end + else if(gpio == 16'hAB41) begin + $display("Monitor: Crossbar test R/W from QSPI CTRL slave passed"); + end + else if(gpio == 16'hAB50) begin + $display("%c[1;31m",27); + $display("Monitor: Crossbar test R/W from storage area failed."); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB51) begin + $display("Monitor: Crossbar test R/W from storage area passed."); + end + else if(gpio == 16'hAB60) begin + $display("%c[1;31m",27); + $display("Monitor: Crossbar test R/W from mega project 1st slave failed."); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB61) begin + $display("Monitor: Crossbar test R/W from mega project 1st slave passed."); + end + else if(gpio == 16'hAB70) begin + $display("%c[1;31m",27); + $display("Monitor: Crossbar test R/W from mega project 2nd slave passed."); + $display("%c[0m",27); + $finish; + end else if(gpio == 16'hAB71) begin + $display("Monitor: Crossbar test R/W from mega project 2nd slave passed."); + $display("Monitor: Timeout, Test Crossbar Switch (RTL) Passed."); + $finish; + end + end + + initial begin + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + CSB <= 1'b0; // Apply CSB to start transmission + end + + always @(gpio) begin + #1 $display("GPIO state = %b ", gpio); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD1V8 = 1'b1; + assign VDD3V3 = 1'b1; + + harness uut ( + .vdd (VDD3V3), + .vdd1v8 (VDD1V8), + .vss (VSS), + .xi (XI), + .xclk (XCLK), + .SDI (SDI), + .SDO (SDO), + .CSB (CSB), + .SCK (SCK), + .ser_rx (1'b0), + .ser_tx (), + .irq (1'b0), + .gpio (gpio), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .flash_io2(flash_io2), + .flash_io3(flash_io3), + .adc_high (adc_h), + .adc_low (adc_l), + .adc0_in (adc_0), + .adc1_in (adc_1), + .RSTB (RSTB), + .comp_inp (comp_p), + .comp_inn (comp_n) + ); + + spiflash #( + .FILENAME("xbar.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + +endmodule
diff --git a/verilog/dv/wb/Makefile b/verilog/dv/wb/Makefile new file mode 100644 index 0000000..7b0e09b --- /dev/null +++ b/verilog/dv/wb/Makefile
@@ -0,0 +1,18 @@ +# ---- Test patterns for project striVe ---- + +.SUFFIXES: +.SILENT: clean all + +PATTERNS = gpio_wb intercon_wb spimemio_wb uart_wb crossbar_wb arbiter_wb + +all: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + done + +clean: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make clean ) ; \ + done + +.PHONY: clean all
diff --git a/verilog/dv/wb/arbiter_wb/Makefile b/verilog/dv/wb/arbiter_wb/Makefile new file mode 100644 index 0000000..e792a4d --- /dev/null +++ b/verilog/dv/wb/arbiter_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = arbiter_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../ip -I .. -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb/arbiter_wb/arbiter_wb_tb.v b/verilog/dv/wb/arbiter_wb/arbiter_wb_tb.v new file mode 100644 index 0000000..164d526 --- /dev/null +++ b/verilog/dv/wb/arbiter_wb/arbiter_wb_tb.v
@@ -0,0 +1,232 @@ + +`timescale 1 ns / 1 ps + +`include "arbiter.v" +`include "dummy_slave.v" + +`ifndef AW +`define AW 32 +`endif +`ifndef DW +`define DW 32 +`endif +`ifndef NM +`define NM 2 +`endif + +module arbiter_wb_tb; + + localparam SEL = `DW / 8; + + reg wb_clk_i; + reg wb_rst_i; + + // Masters Interface + reg [`NM-1:0] wbm_stb_i; + reg [`NM-1:0] wbm_cyc_i; + reg [`NM-1:0] wbm_we_i; + reg [`NM*SEL-1:0] wbm_sel_i; + reg [`NM*`DW-1:0] wbm_dat_i; + reg [`NM*`AW-1:0] wbm_adr_i; + + wire [`NM-1:0] wbm_ack_o; + wire [`NM-1:0] wbm_err_o; + wire [`NM*`DW-1:0] wbm_dat_o; + + // Slave Interface + reg wbs_ack_i; + reg wbs_err_i; + wire [`DW-1:0] wbs_dat_i; + wire wbs_stb_i; + wire wbs_cyc_i; + wire wbs_we_i; + wire [SEL-1:0] wbs_sel_i; + wire [`AW-1:0] wbs_adr_i; + wire [`DW-1:0] wbs_dat_o; + + wb_arbiter #( + .AW(`AW), + .DW(`DW), + .NM(`NM) + ) uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + // Masters Interface + .wbm_stb_i(wbm_stb_i), + .wbm_cyc_i(wbm_cyc_i), + .wbm_we_i(wbm_we_i), + .wbm_sel_i(wbm_sel_i), + .wbm_dat_i(wbm_dat_i), + .wbm_adr_i(wbm_adr_i), + + .wbm_ack_o(wbm_ack_o), + .wbm_err_o(wbm_err_o), + .wbm_dat_o(wbm_dat_o), + + // Slave Interface + .wbs_ack_i(wbs_ack_o), + .wbs_err_i(wbs_err_o), + .wbs_dat_i(wbs_dat_o), + .wbs_stb_o(wbs_stb_i), + .wbs_cyc_o(wbs_cyc_i), + .wbs_we_o(wbs_we_i), + .wbs_sel_o(wbs_sel_i), + .wbs_adr_o(wbs_adr_i), + .wbs_dat_o(wbs_dat_i) + ); + + // Instantiate one dummy slave for testing + dummy_slave dummy_slave ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wbs_stb_i), + .wb_cyc_i(wbs_cyc_i), + .wb_we_i(wbs_we_i), + .wb_sel_i(wbs_sel_i), + .wb_adr_i(wbs_adr_i), + .wb_dat_i(wbs_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wbm_stb_i = 0; + wbm_cyc_i = 0; + wbm_we_i = 0; + wbm_sel_i = 0; + wbm_dat_i = 0; + wbm_adr_i = 0; + wbs_ack_i = 0; + wbs_err_i = 0; + end + + initial begin + $dumpfile("arbiter_wb_tb.vcd"); + $dumpvars(0, arbiter_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Arbiter Failed"); + $display("%c[0m",27); + $finish; + end + + + reg [`DW-1:0] data; + reg [`AW-1:0] address; + + integer i; + + initial begin + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Case 1: Initiate W/R requests from M0 -- MN + for (i=0; i<`NM; i=i+1) begin + data = $urandom_range(0, 255); + address = $urandom_range(0, 255); + write(address,data,i); + #2; + read(i); + if (wbm_dat_i[i*`DW +: `DW] !== data) begin + $display("Request Error from master %0b", i); + $finish; + end + end + + #10; + + // Case 2: Initiate W/R requests from MN -- M0 + for (i=`NM-1; i>=0; i=i-1) begin + data = $urandom_range(0, 255); + address = $urandom_range(0, 255); + write(address,data,i); + #2; + read(i); + if (wbm_dat_i[i*`DW +: `DW] !== data) begin + $display("Request Error from master %0b", i); + $finish; + end + end + + // Case 3: Initiate concurrent W/R requests from all masters + address = $urandom_range(0, 255); + wbm_stb_i = {`NM{1'b1}}; + wbm_cyc_i = {`NM{1'b1}}; + wbm_we_i = {`NM{1'b1}}; + wbm_sel_i = {`NM{4'hF}}; + wbm_adr_i = {`NM{address}}; + for (i=`NM-1; i>=0; i=i-1) begin + wbm_dat_i[i*`DW+: `DW] = $urandom_range(0, 2**32); + end + + // Make sure that served request is master 0 (highest priority) + wait(wbm_ack_o[0]); + if (wbm_ack_o[`NM-1:1] !== 0) begin + $display("Arbitration failed"); + $finish; + end + + // Read + wbm_we_i = {`NM{1'b0}}; + wait(wbm_ack_o[0]); + + // Make sure that the second master doesn't receive an ack + if (wbm_ack_o[`NM-1:1] !== 0) begin + $display("Arbitration failed"); + $finish; + end + #10; + $finish; + end + + task read; + input mindex; + begin + @(posedge wb_clk_i) begin + wbm_stb_i[mindex] = 1; + wbm_cyc_i[mindex] = 1; + wbm_we_i[mindex] = 0; + $display("Read Cycle from master %0b started", mindex); + end + wait(wbm_ack_o[mindex]); + wait(!wbm_ack_o[mindex]); + wbm_stb_i[mindex] = 0; + wbm_cyc_i[mindex] = 0; + $display("Read Cycle from master %0b ended.", mindex); + end + endtask + + task write; + input [`AW-1:0] adr; + input [`DW-1:0] data; + input integer mindex; + + begin + @(posedge wb_clk_i) begin + wbm_stb_i[mindex] = 1; + wbm_cyc_i[mindex] = 1; + wbm_we_i[mindex] = 1; + wbm_sel_i[mindex*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[mindex*`AW+: `AW] = adr; + wbm_dat_i[mindex*`DW+: `DW] = data; + $display("Write Cycle from master %0b started", mindex); + end + + wait(wbm_ack_o[mindex]); + wait(!wbm_ack_o[mindex]); + wbm_stb_i[mindex] = 0; + wbm_cyc_i[mindex] = 0; + $display("Write Cycle from master %0b ended.", mindex); + end + endtask + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/crossbar_wb/Makefile b/verilog/dv/wb/crossbar_wb/Makefile new file mode 100644 index 0000000..fcd10cc --- /dev/null +++ b/verilog/dv/wb/crossbar_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = crossbar_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../ip -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb/crossbar_wb/crossbar_wb_tb.v b/verilog/dv/wb/crossbar_wb/crossbar_wb_tb.v new file mode 100644 index 0000000..a9a35b4 --- /dev/null +++ b/verilog/dv/wb/crossbar_wb/crossbar_wb_tb.v
@@ -0,0 +1,292 @@ + +`timescale 1 ns / 1 ps + +`include "crossbar.v" +`include "dummy_slave.v" + +`ifndef AW + `define AW 32 +`endif +`ifndef DW + `define DW 32 +`endif +`ifndef NM + `define NM 2 +`endif + +`ifndef NS + `define NS 4 +`endif + +`ifndef SLAVE_ADR + `define SLAVE_ADR { \ + {8'hB0, {24{1'b0}}},\ + {8'hA0, {24{1'b0}}},\ + {8'h90, {24{1'b0}}},\ + {8'h80, {24{1'b0}}}\ + }\ +`endif + +`ifndef ADR_MASK + `define ADR_MASK { \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}} \ + }\ +`endif + +module crossbar_wb_tb; + + localparam SEL = `DW / 8; + + reg wb_clk_i; + reg wb_rst_i; + + // Masters interface + reg [`NM-1:0] wbm_cyc_i; + reg [`NM-1:0] wbm_stb_i; + reg [`NM-1:0] wbm_we_i; + reg [(`NM*(`DW/8))-1:0] wbm_sel_i; + reg [(`NM*`AW)-1:0] wbm_adr_i; + reg [(`NM*`DW)-1:0] wbm_dat_i; + wire [`NM-1:0] wbm_ack_o; + wire [`NM-1:0] wbm_err_o; + wire [(`NM*`DW)-1:0] wbm_dat_o; + + // Slaves interfaces + wire [`NS-1:0] wbs_ack_o; + wire [(`NS*`DW)-1:0] wbs_dat_i; + wire [`NS-1:0] wbs_cyc_o; + wire [`NS-1:0] wbs_stb_o; + wire [`NS-1:0] wbs_we_o; + wire [(`NS*(`DW/8))-1:0] wbs_sel_o; + wire [(`NS*`AW)-1:0] wbs_adr_o; + wire [(`NS*`DW)-1:0] wbs_dat_o; + + wb_xbar #( + .NM(`NM), + .NS(`NS), + .AW(`AW), + .DW(`DW), + .SLAVE_ADR(`SLAVE_ADR), + .ADR_MASK(`ADR_MASK) + ) + wb_xbar( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + // Masters interface + .wbm_cyc_i(wbm_cyc_i), + .wbm_stb_i(wbm_stb_i), + .wbm_we_i (wbm_we_i), + .wbm_sel_i(wbm_sel_i), + .wbm_adr_i(wbm_adr_i), + .wbm_dat_i(wbm_dat_i), + .wbm_ack_o(wbm_ack_o), + .wbm_dat_o(wbm_dat_o), + // Slaves interfaces + .wbs_ack_i(wbs_ack_o), + .wbs_dat_i(wbs_dat_o), + .wbs_cyc_o(wbs_cyc_o), + .wbs_stb_o(wbs_stb_o), + .wbs_we_o(wbs_we_o), + .wbs_sel_o(wbs_sel_o), + .wbs_adr_o(wbs_adr_o), + .wbs_dat_o(wbs_dat_i) + ); + + // Instantiate four dummy slaves for testing + dummy_slave dummy_slaves [`NS-1:0]( + .wb_clk_i({`NS{wb_clk_i}}), + .wb_rst_i({`NS{wb_rst_i}}), + .wb_stb_i(wbs_stb_o), + .wb_cyc_i(wbs_cyc_o), + .wb_we_i(wbs_we_o), + .wb_sel_i(wbs_sel_o), + .wb_adr_i(wbs_adr_o), + .wb_dat_i(wbs_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wbm_cyc_i = 0; + wbm_stb_i = 0; + wbm_we_i = 0; + wbm_sel_i = 0; + wbm_adr_i = 0; + wbm_dat_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("crossbar_wb_tb.vcd"); + $dumpvars(0, crossbar_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Crossbar Switch Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [`AW*`NS-1:0] addresses = { + {8'hB0, {24{1'b0}}}, + {8'hA0, {24{1'b0}}}, + {8'h90, {24{1'b0}}}, + {8'h80, {24{1'b0}}} + }; + + reg [`DW-1:0] m0_slave_data; + reg [`DW-1:0] m1_slave_data; + reg [`AW-1:0] slave_adr; + + initial begin + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Case 1: Master0 addresses slave 0 and Master 2 Addresses slave 1 + slave_adr = addresses[`AW-1:0]; + m0_slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, m0_slave_data, 0); + + #2; + read(slave_adr, 0); + if (wbm_dat_o[0*`DW+: `DW] !== m0_slave_data) begin + $display("Error reading from slave"); + $finish; + end + + #10; + slave_adr = addresses[`AW*2-1:`AW*1]; + m1_slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, m1_slave_data, 1); + #2; + read(slave_adr, 1); + #10; + if (wbm_dat_o[1*`DW+: `DW] !== m1_slave_data) begin + $display("Error reading from slave"); + $finish; + end + #10; + // Case 2: Master0 addresses slave 0 and Master 2 Addresses slave 1 simultaenously + slave_adr = addresses[`AW-1:0]; + m0_slave_data = $urandom_range(0, 2**(`DW-2)); + + wbm_stb_i[0] = 1; + wbm_cyc_i[0] = 1; + wbm_we_i [0] = 1; + wbm_sel_i[0*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[0*`AW+: `AW] = slave_adr; + wbm_dat_i[0*`DW+: `DW] = m0_slave_data; + + slave_adr = addresses[`AW*2-1:`AW*1]; + m1_slave_data = $urandom_range(0, 2**(`DW-2)); + + wbm_stb_i[1] = 1; + wbm_cyc_i[1] = 1; + wbm_we_i[1] = 1; + wbm_sel_i[1*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[1*`AW+: `AW] = slave_adr; + wbm_dat_i[1*`DW+: `DW] = m1_slave_data; + + wait(wbm_ack_o[0] && wbm_ack_o[1]); + wait(!wbm_ack_o[0] && !wbm_ack_o[1]); + + // Read + wbm_we_i = 2'b00; + wait(wbm_ack_o[0] && wbm_ack_o[1]); + wait(!wbm_ack_o[0] && !wbm_ack_o[1]); + + if (wbm_dat_o[0*`DW+: `DW] !== m0_slave_data) begin + $display("Error reading from slave"); + $finish; + end + + // Case 3: Master0 addresses slave 0 and Master 2 Addresses slave 1 simultaenously + slave_adr = addresses[`AW-1:0]; + m0_slave_data = $urandom_range(0, 2**(`DW-2)); + + wbm_stb_i[0] = 1; + wbm_cyc_i[0] = 1; + wbm_we_i [0] = 1; + wbm_sel_i[0*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[0*`AW+: `AW] = slave_adr; + wbm_dat_i[0*`DW+: `DW] = m0_slave_data; + + slave_adr = addresses[`AW-1:0]; + m1_slave_data = $urandom_range(0, 2**(`DW-2)); + + wbm_stb_i[1] = 1; + wbm_cyc_i[1] = 1; + wbm_we_i [1] = 1; + wbm_sel_i[1*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[1*`AW+: `AW] = slave_adr; + wbm_dat_i[1*`DW+: `DW] = m1_slave_data; + + wait(wbm_ack_o[0] && !wbm_ack_o[1]); + wait(!wbm_ack_o[0] && !wbm_ack_o[1]); + + // Read + wbm_we_i = 2'b00; + wait(wbm_ack_o[0]); + wait(!wbm_ack_o[0]); + if (wbm_dat_o[0*`DW+: `DW] !== m0_slave_data) begin + $display("Error reading from slave"); + $finish; + end + + $finish; + end + + task read; + input addr; + input mindex; + begin + @(posedge wb_clk_i) begin + wbm_stb_i[mindex] = 1; + wbm_cyc_i[mindex] = 1; + wbm_we_i[mindex] = 0; + $display("Read cycle from master %0b started", mindex); + end + wait(wbm_ack_o[mindex]); + wait(!wbm_ack_o[mindex]); + wbm_stb_i[mindex] = 0; + wbm_cyc_i[mindex] = 0; + $display("Read cycle from master %0b ended.", mindex); + end + endtask + + task write; + input [`AW-1:0] adr; + input [`DW-1:0] data; + input integer mindex; + + begin + @(posedge wb_clk_i) begin + wbm_stb_i[mindex] = 1; + wbm_cyc_i[mindex] = 1; + wbm_we_i[mindex] = 1; + wbm_sel_i[mindex*SEL+: SEL] = {SEL{1'b1}}; + wbm_adr_i[mindex*`AW+: `AW] = adr; + wbm_dat_i[mindex*`DW+: `DW] = data; + $display("Write cycle from master %0b started", mindex); + end + + wait(wbm_ack_o[mindex]); + wait(!wbm_ack_o[mindex]); + wbm_stb_i[mindex] = 0; + wbm_cyc_i[mindex] = 0; + $display("Write cycle from master %0b ended.", mindex); + end + endtask + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/distributor/Makefile b/verilog/dv/wb/distributor/Makefile new file mode 100644 index 0000000..f3a1273 --- /dev/null +++ b/verilog/dv/wb/distributor/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = distributor + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../ip -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb/distributor/distributor_tb.v b/verilog/dv/wb/distributor/distributor_tb.v new file mode 100644 index 0000000..ab8f929 --- /dev/null +++ b/verilog/dv/wb/distributor/distributor_tb.v
@@ -0,0 +1,226 @@ + +`timescale 1 ns / 1 ps + +`include "distributor.v" +`include "dummy_slave.v" + +`ifndef AW + `define AW 32 +`endif +`ifndef DW + `define DW 32 +`endif + +`ifndef NS + `define NS 4 +`endif + +`ifndef SLAVE_ADR + `define SLAVE_ADR { \ + {8'hB0, {24{1'b0}}},\ + {8'hA0, {24{1'b0}}},\ + {8'h90, {24{1'b0}}},\ + {8'h80, {24{1'b0}}}\ + }\ +`endif + +`ifndef ADR_MASK + `define ADR_MASK { \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}} \ + }\ +`endif + +module distributor_tb; + + localparam SEL = `DW / 8; + + reg wb_clk_i; + reg wb_rst_i; + + // Masters interface + reg wbm_cyc_i; + reg wbm_stb_i; + reg wbm_we_i; + reg [(`DW/8)-1:0] wbm_sel_i; + reg [`AW-1:0] wbm_adr_i; + reg [`DW-1:0] wbm_dat_i; + wire wbm_ack_o; + wire [`DW-1:0] wbm_dat_o; + + // Slaves interfaces + wire [`NS-1:0] wbs_ack_o; + wire [(`NS*`DW)-1:0] wbs_dat_i; + wire [`NS-1:0] wbs_cyc_o; + wire [`NS-1:0] wbs_stb_o; + wire [`NS-1:0] wbs_we_o; + wire [(`NS*(`DW/8))-1:0] wbs_sel_o; + wire [(`NS*`AW)-1:0] wbs_adr_o; + wire [(`NS*`DW)-1:0] wbs_dat_o; + + distributor #( + .NS(`NS), + .AW(`AW), + .DW(`DW), + .ADR_MASK(`ADR_MASK), + .SLAVE_ADR(`SLAVE_ADR) + ) + uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + // Masters interface + .wbm_cyc_i(wbm_cyc_i), + .wbm_stb_i(wbm_stb_i), + .wbm_we_i (wbm_we_i), + .wbm_sel_i(wbm_sel_i), + .wbm_adr_i(wbm_adr_i), + .wbm_dat_i(wbm_dat_i), + .wbm_ack_o(wbm_ack_o), + .wbm_dat_o(wbm_dat_o), + + // Slaves interfaces + .wbs_ack_i(wbs_ack_o), + .wbs_dat_i(wbs_dat_o), + .wbs_cyc_o(wbs_cyc_o), + .wbs_stb_o(wbs_stb_o), + .wbs_we_o(wbs_we_o), + .wbs_sel_o(wbs_sel_o), + .wbs_adr_o(wbs_adr_o), + .wbs_dat_o(wbs_dat_i) + ); + + // Instantiate four dummy slaves for testing + dummy_slave dummy_slaves [`NS-1:0]( + .wb_clk_i({`NS{wb_clk_i}}), + .wb_rst_i({`NS{wb_rst_i}}), + .wb_stb_i(wbs_stb_o), + .wb_cyc_i(wbs_cyc_o), + .wb_we_i(wbs_we_o), + .wb_sel_i(wbs_sel_o), + .wb_adr_i(wbs_adr_o), + .wb_dat_i(wbs_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wbm_cyc_i = 0; + wbm_stb_i = 0; + wbm_we_i = 0; + wbm_sel_i = 0; + wbm_adr_i = 0; + wbm_dat_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("distributor_tb.vcd"); + $dumpvars(0, distributor_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Distributor Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [`DW-1:0] slave_data; + reg [`AW-1:0] slave_adr; + + initial begin + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + slave_adr = 32'h 8000_0000; + slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, slave_data); + #2; + read(slave_adr); + if (wbm_dat_i !== slave_data) begin + $display("Failed R/W from slave"); + end + + #2; + slave_adr = 32'h 9000_0000; + slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, slave_data); + #2; + read(slave_adr); + if (wbm_dat_i !== slave_data) begin + $display("Failed R/W from slave"); + end + #2; + + slave_adr = 32'h A000_0000; + slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, slave_data); + #2; + read(slave_adr); + if (wbm_dat_i !== slave_data) begin + $display("Failed R/W from slave"); + end + + #2; + slave_adr = 32'h B000_0000; + slave_data = $urandom_range(0, 2**(`DW-2)); + write(slave_adr, slave_data); + #2; + read(slave_adr); + if (wbm_dat_i !== slave_data) begin + $display("Failed R/W from slave"); + end + + + $finish; + end + + task read; + input [`AW-1:0] addr; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_we_i = 0; + wbm_adr_i = addr; + $display("Read Cycle Started"); + end + wait(wbm_ack_o); + wait(!wbm_ack_o); + wbm_stb_i = 0; + wbm_cyc_i = 0; + $display("Read cycle Ended"); + end + endtask + + task write; + input [`AW-1:0] adr; + input [`DW-1:0] data; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_we_i = 1; + wbm_sel_i = {SEL{1'b1}}; + wbm_adr_i = adr; + wbm_dat_i = data; + $display("Write cycle started"); + end + wait(wbm_ack_o); + wait(!wbm_ack_o); + wbm_stb_i = 0; + wbm_cyc_i = 0; + $display("Write cycle ended."); + end + endtask + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/distributor/distributor_tb.vcd b/verilog/dv/wb/distributor/distributor_tb.vcd new file mode 100644 index 0000000..12f7ae8 --- /dev/null +++ b/verilog/dv/wb/distributor/distributor_tb.vcd
@@ -0,0 +1,963 @@ +$date + Fri Aug 21 14:18:15 2020 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module distributor_tb $end +$var wire 4 ! wbs_we_o [3:0] $end +$var wire 4 " wbs_stb_o [3:0] $end +$var wire 16 # wbs_sel_o [15:0] $end +$var wire 128 $ wbs_dat_o [127:0] $end +$var wire 128 % wbs_dat_i [127:0] $end +$var wire 4 & wbs_cyc_o [3:0] $end +$var wire 128 ' wbs_adr_o [127:0] $end +$var wire 4 ( wbs_ack_o [3:0] $end +$var wire 32 ) wbm_dat_o [31:0] $end +$var wire 1 * wbm_ack_o $end +$var reg 32 + slave_adr [31:0] $end +$var reg 32 , slave_data [31:0] $end +$var reg 1 - wb_clk_i $end +$var reg 1 . wb_rst_i $end +$var reg 32 / wbm_adr_i [31:0] $end +$var reg 1 0 wbm_cyc_i $end +$var reg 32 1 wbm_dat_i [31:0] $end +$var reg 4 2 wbm_sel_i [3:0] $end +$var reg 1 3 wbm_stb_i $end +$var reg 1 4 wbm_we_i $end +$scope module dummy_slaves[0] $end +$var wire 1 5 valid $end +$var wire 32 6 wb_adr_i [31:0] $end +$var wire 1 7 wb_clk_i $end +$var wire 1 8 wb_cyc_i $end +$var wire 32 9 wb_dat_i [31:0] $end +$var wire 1 : wb_rst_i $end +$var wire 4 ; wb_sel_i [3:0] $end +$var wire 1 < wb_stb_i $end +$var wire 1 = wb_we_i $end +$var reg 32 > store [31:0] $end +$var reg 1 ? wb_ack_o $end +$var reg 32 @ wb_dat_o [31:0] $end +$upscope $end +$scope module dummy_slaves[1] $end +$var wire 1 A valid $end +$var wire 32 B wb_adr_i [31:0] $end +$var wire 1 C wb_clk_i $end +$var wire 1 D wb_cyc_i $end +$var wire 32 E wb_dat_i [31:0] $end +$var wire 1 F wb_rst_i $end +$var wire 4 G wb_sel_i [3:0] $end +$var wire 1 H wb_stb_i $end +$var wire 1 I wb_we_i $end +$var reg 32 J store [31:0] $end +$var reg 1 K wb_ack_o $end +$var reg 32 L wb_dat_o [31:0] $end +$upscope $end +$scope module dummy_slaves[2] $end +$var wire 1 M valid $end +$var wire 32 N wb_adr_i [31:0] $end +$var wire 1 O wb_clk_i $end +$var wire 1 P wb_cyc_i $end +$var wire 32 Q wb_dat_i [31:0] $end +$var wire 1 R wb_rst_i $end +$var wire 4 S wb_sel_i [3:0] $end +$var wire 1 T wb_stb_i $end +$var wire 1 U wb_we_i $end +$var reg 32 V store [31:0] $end +$var reg 1 W wb_ack_o $end +$var reg 32 X wb_dat_o [31:0] $end +$upscope $end +$scope module dummy_slaves[3] $end +$var wire 1 Y valid $end +$var wire 32 Z wb_adr_i [31:0] $end +$var wire 1 [ wb_clk_i $end +$var wire 1 \ wb_cyc_i $end +$var wire 32 ] wb_dat_i [31:0] $end +$var wire 1 ^ wb_rst_i $end +$var wire 4 _ wb_sel_i [3:0] $end +$var wire 1 ` wb_stb_i $end +$var wire 1 a wb_we_i $end +$var reg 32 b store [31:0] $end +$var reg 1 c wb_ack_o $end +$var reg 32 d wb_dat_o [31:0] $end +$upscope $end +$scope module uut $end +$var wire 1 - wb_clk_i $end +$var wire 1 . wb_rst_i $end +$var wire 32 e wbm_adr_i [31:0] $end +$var wire 1 0 wbm_cyc_i $end +$var wire 32 f wbm_dat_i [31:0] $end +$var wire 4 g wbm_sel_i [3:0] $end +$var wire 1 3 wbm_stb_i $end +$var wire 1 4 wbm_we_i $end +$var wire 4 h wbs_ack_i [3:0] $end +$var wire 4 i wbs_cyc_o [3:0] $end +$var wire 128 j wbs_dat_i [127:0] $end +$var wire 4 k wbs_stb_o [3:0] $end +$var wire 4 l wbs_we_o [3:0] $end +$var wire 16 m wbs_sel_o [15:0] $end +$var wire 128 n wbs_dat_o [127:0] $end +$var wire 128 o wbs_adr_o [127:0] $end +$var wire 1 * wbm_ack_o $end +$var wire 4 p slave_sel [3:0] $end +$var reg 32 q wbm_dat_o [31:0] $end +$var integer 32 r i [31:0] $end +$scope begin genblk1[0] $end +$upscope $end +$scope begin genblk1[1] $end +$upscope $end +$scope begin genblk1[2] $end +$upscope $end +$scope begin genblk1[3] $end +$upscope $end +$upscope $end +$scope task read $end +$var reg 32 s addr [31:0] $end +$upscope $end +$scope task write $end +$var reg 32 t adr [31:0] $end +$var reg 32 u data [31:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +bx u +bx t +bx s +b10000000 r +b0 q +b0 p +b0 o +b0 n +b0 m +b0 l +b0 k +bx j +b0 i +bx h +b0 g +b0 f +b0 e +bx d +xc +bx b +0a +0` +b0 _ +1^ +b0 ] +0\ +0[ +b0 Z +0Y +bx X +xW +bx V +0U +0T +b0 S +1R +b0 Q +0P +0O +b0 N +0M +bx L +xK +bx J +0I +0H +b0 G +1F +b0 E +0D +0C +b0 B +0A +bx @ +x? +bx > +0= +0< +b0 ; +1: +b0 9 +08 +07 +b0 6 +05 +04 +03 +b0 2 +b0 1 +00 +b0 / +1. +0- +bx , +bx + +0* +b0 ) +bx ( +b0 ' +b0 & +b0 % +bx $ +b0 # +b0 " +b0 ! +$end +#1000 +0? +0K +0W +b0 ( +b0 h +0c +17 +1C +1O +1[ +1- +#2000 +07 +0C +0O +0[ +0: +0F +0R +0^ +0- +0. +#3000 +17 +1C +1O +1[ +1- +#4000 +07 +0C +0O +0[ +0- +b100100100001010100110101001001 u +b10000000000000000000000000000000 t +b100100100001010100110101001001 , +b10000000000000000000000000000000 + +#5000 +b100100100001010100110101001001 > +b100100100001010100110101001001 J +b100100100001010100110101001001 V +b100100100001010100110101001001 b +15 +1< +18 +b1 " +b1 k +b1 & +b1 i +bx ) +bx q +b10000000 r +b100100100001010100110101001001 9 +b100100100001010100110101001001 E +b100100100001010100110101001001 Q +b100100100001010100110101001001 ] +b10000000000000000000000000000000 6 +b10000000000000000000000000000000 B +b10000000000000000000000000000000 N +b10000000000000000000000000000000 Z +b1 p +b1111 ; +b1111 G +b1111 S +b1111 _ +1= +1I +1U +1a +17 +1C +1O +1[ +b100100100001010100110101001001001001001000010101001101010010010010010010000101010011010100100100100100100001010100110101001001 % +b100100100001010100110101001001001001001000010101001101010010010010010010000101010011010100100100100100100001010100110101001001 n +b100100100001010100110101001001 1 +b100100100001010100110101001001 f +b10000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000 ' +b10000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000 o +b10000000000000000000000000000000 / +b10000000000000000000000000000000 e +b1111111111111111 # +b1111111111111111 m +b1111 2 +b1111 g +b1111 ! +b1111 l +14 +10 +13 +1- +#6000 +07 +0C +0O +0[ +0- +#7000 +1* +b10000000 r +b100100100001010100110101001001 ) +b100100100001010100110101001001 q +b1 ( +b1 h +1? +b100100100001010100110101001001 @ +b100100100001010100110101001001 L +b100100100001010100110101001001 X +b100100100001010100110101001001001001001000010101001101010010010010010010000101010011010100100100100100100001010100110101001001 $ +b100100100001010100110101001001001001001000010101001101010010010010010010000101010011010100100100100100100001010100110101001001 j +b100100100001010100110101001001 d +17 +1C +1O +1[ +1- +#8000 +07 +0C +0O +0[ +0- +#9000 +05 +08 +0< +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0? +17 +1C +1O +1[ +1- +#10000 +07 +0C +0O +0[ +0- +#11000 +15 +18 +1< +0= +0I +0U +0a +b1 & +b1 i +b1 " +b1 k +17 +1C +1O +1[ +b0 ! +b0 l +04 +10 +13 +1- +b10000000000000000000000000000000 s +#12000 +07 +0C +0O +0[ +0- +#13000 +1* +b1 ( +b1 h +1? +17 +1C +1O +1[ +1- +#14000 +07 +0C +0O +0[ +0- +#15000 +05 +08 +0< +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0? +17 +1C +1O +1[ +1- +#16000 +07 +0C +0O +0[ +0- +#17000 +b10000001000100101011110100000 > +b10000001000100101011110100000 J +b10000001000100101011110100000 V +b10000001000100101011110100000 b +1A +1H +1D +05 +b10000000 r +b100100100001010100110101001001 ) +b100100100001010100110101001001 q +08 +0< +b10000001000100101011110100000 9 +b10000001000100101011110100000 E +b10000001000100101011110100000 Q +b10000001000100101011110100000 ] +b10010000000000000000000000000000 6 +b10010000000000000000000000000000 B +b10010000000000000000000000000000 N +b10010000000000000000000000000000 Z +b10 p +1= +1I +1U +1a +b10 & +b10 i +b10 " +b10 k +17 +1C +1O +1[ +b10000001000100101011110100000000100000010001001010111101000000001000000100010010101111010000000010000001000100101011110100000 % +b10000001000100101011110100000000100000010001001010111101000000001000000100010010101111010000000010000001000100101011110100000 n +b10000001000100101011110100000 1 +b10000001000100101011110100000 f +b10010000000000000000000000000000100100000000000000000000000000001001000000000000000000000000000010010000000000000000000000000000 ' +b10010000000000000000000000000000100100000000000000000000000000001001000000000000000000000000000010010000000000000000000000000000 o +b10010000000000000000000000000000 / +b10010000000000000000000000000000 e +b1111 ! +b1111 l +14 +10 +13 +1- +b10000001000100101011110100000 u +b10010000000000000000000000000000 t +b10000001000100101011110100000 , +b10010000000000000000000000000000 + +#18000 +07 +0C +0O +0[ +0- +#19000 +1* +b10000000 r +b10000001000100101011110100000 ) +b10000001000100101011110100000 q +b10000001000100101011110100000 @ +b10 ( +b10 h +1K +b10000001000100101011110100000 L +b10000001000100101011110100000 X +b10000001000100101011110100000000100000010001001010111101000000001000000100010010101111010000000010000001000100101011110100000 $ +b10000001000100101011110100000000100000010001001010111101000000001000000100010010101111010000000010000001000100101011110100000 j +b10000001000100101011110100000 d +17 +1C +1O +1[ +1- +#20000 +07 +0C +0O +0[ +0- +#21000 +0A +0D +0H +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0K +17 +1C +1O +1[ +1- +#22000 +07 +0C +0O +0[ +0- +#23000 +1A +1D +1H +0= +0I +0U +0a +b10 & +b10 i +b10 " +b10 k +17 +1C +1O +1[ +b0 ! +b0 l +04 +10 +13 +1- +b10010000000000000000000000000000 s +#24000 +07 +0C +0O +0[ +0- +#25000 +1* +b10 ( +b10 h +1K +17 +1C +1O +1[ +1- +#26000 +07 +0C +0O +0[ +0- +#27000 +0A +0D +0H +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0K +17 +1C +1O +1[ +1- +#28000 +07 +0C +0O +0[ +0- +#29000 +b1001000010011010110000010 > +b1001000010011010110000010 J +b1001000010011010110000010 V +b1001000010011010110000010 b +1M +1T +1P +0A +b10000000 r +b10000001000100101011110100000 ) +b10000001000100101011110100000 q +0D +0H +b1001000010011010110000010 9 +b1001000010011010110000010 E +b1001000010011010110000010 Q +b1001000010011010110000010 ] +b10100000000000000000000000000000 6 +b10100000000000000000000000000000 B +b10100000000000000000000000000000 N +b10100000000000000000000000000000 Z +b100 p +1= +1I +1U +1a +b100 & +b100 i +b100 " +b100 k +17 +1C +1O +1[ +b1001000010011010110000010000000010010000100110101100000100000000100100001001101011000001000000001001000010011010110000010 % +b1001000010011010110000010000000010010000100110101100000100000000100100001001101011000001000000001001000010011010110000010 n +b1001000010011010110000010 1 +b1001000010011010110000010 f +b10100000000000000000000000000000101000000000000000000000000000001010000000000000000000000000000010100000000000000000000000000000 ' +b10100000000000000000000000000000101000000000000000000000000000001010000000000000000000000000000010100000000000000000000000000000 o +b10100000000000000000000000000000 / +b10100000000000000000000000000000 e +b1111 ! +b1111 l +14 +10 +13 +1- +b1001000010011010110000010 u +b10100000000000000000000000000000 t +b1001000010011010110000010 , +b10100000000000000000000000000000 + +#30000 +07 +0C +0O +0[ +0- +#31000 +1* +b10000000 r +b1001000010011010110000010 ) +b1001000010011010110000010 q +b1001000010011010110000010 @ +b1001000010011010110000010 L +b100 ( +b100 h +1W +b1001000010011010110000010 X +b1001000010011010110000010000000010010000100110101100000100000000100100001001101011000001000000001001000010011010110000010 $ +b1001000010011010110000010000000010010000100110101100000100000000100100001001101011000001000000001001000010011010110000010 j +b1001000010011010110000010 d +17 +1C +1O +1[ +1- +#32000 +07 +0C +0O +0[ +0- +#33000 +0M +0P +0T +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0W +17 +1C +1O +1[ +1- +#34000 +07 +0C +0O +0[ +0- +#35000 +1M +1P +1T +0= +0I +0U +0a +b100 & +b100 i +b100 " +b100 k +17 +1C +1O +1[ +b0 ! +b0 l +04 +10 +13 +1- +b10100000000000000000000000000000 s +#36000 +07 +0C +0O +0[ +0- +#37000 +1* +b100 ( +b100 h +1W +17 +1C +1O +1[ +1- +#38000 +07 +0C +0O +0[ +0- +#39000 +0M +0P +0T +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0W +17 +1C +1O +1[ +1- +#40000 +07 +0C +0O +0[ +0- +#41000 +b1100011111000001010110011001 > +b1100011111000001010110011001 J +b1100011111000001010110011001 V +b1100011111000001010110011001 b +1Y +1` +1\ +0M +b10000000 r +b1001000010011010110000010 ) +b1001000010011010110000010 q +0P +0T +b1100011111000001010110011001 9 +b1100011111000001010110011001 E +b1100011111000001010110011001 Q +b1100011111000001010110011001 ] +b10110000000000000000000000000000 6 +b10110000000000000000000000000000 B +b10110000000000000000000000000000 N +b10110000000000000000000000000000 Z +b1000 p +1= +1I +1U +1a +b1000 & +b1000 i +b1000 " +b1000 k +17 +1C +1O +1[ +b1100011111000001010110011001000011000111110000010101100110010000110001111100000101011001100100001100011111000001010110011001 % +b1100011111000001010110011001000011000111110000010101100110010000110001111100000101011001100100001100011111000001010110011001 n +b1100011111000001010110011001 1 +b1100011111000001010110011001 f +b10110000000000000000000000000000101100000000000000000000000000001011000000000000000000000000000010110000000000000000000000000000 ' +b10110000000000000000000000000000101100000000000000000000000000001011000000000000000000000000000010110000000000000000000000000000 o +b10110000000000000000000000000000 / +b10110000000000000000000000000000 e +b1111 ! +b1111 l +14 +10 +13 +1- +b1100011111000001010110011001 u +b10110000000000000000000000000000 t +b1100011111000001010110011001 , +b10110000000000000000000000000000 + +#42000 +07 +0C +0O +0[ +0- +#43000 +1* +b10000000 r +b1100011111000001010110011001 ) +b1100011111000001010110011001 q +b1100011111000001010110011001 @ +b1100011111000001010110011001 L +b1100011111000001010110011001 X +b1000 ( +b1000 h +1c +b1100011111000001010110011001000011000111110000010101100110010000110001111100000101011001100100001100011111000001010110011001 $ +b1100011111000001010110011001000011000111110000010101100110010000110001111100000101011001100100001100011111000001010110011001 j +b1100011111000001010110011001 d +17 +1C +1O +1[ +1- +#44000 +07 +0C +0O +0[ +0- +#45000 +0Y +0\ +0` +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0c +17 +1C +1O +1[ +1- +#46000 +07 +0C +0O +0[ +0- +#47000 +1Y +1\ +1` +0= +0I +0U +0a +b1000 & +b1000 i +b1000 " +b1000 k +17 +1C +1O +1[ +b0 ! +b0 l +04 +10 +13 +1- +b10110000000000000000000000000000 s +#48000 +07 +0C +0O +0[ +0- +#49000 +1* +b1000 ( +b1000 h +1c +17 +1C +1O +1[ +1- +#50000 +07 +0C +0O +0[ +0- +#51000 +0Y +0\ +0` +b0 & +b0 i +b0 " +b0 k +00 +03 +0* +b0 ( +b0 h +0c +17 +1C +1O +1[ +1-
diff --git a/verilog/dv/wb/gpio_wb/Makefile b/verilog/dv/wb/gpio_wb/Makefile new file mode 100644 index 0000000..d8d54e4 --- /dev/null +++ b/verilog/dv/wb/gpio_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = gpio_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb/gpio_wb/gpio_wb_tb.v b/verilog/dv/wb/gpio_wb/gpio_wb_tb.v new file mode 100644 index 0000000..8db196c --- /dev/null +++ b/verilog/dv/wb/gpio_wb/gpio_wb_tb.v
@@ -0,0 +1,182 @@ + + +`timescale 1 ns / 1 ps + +`include "gpio_wb.v" + +module gpio_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + reg [15:0] gpio_in_pad; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + gpio_in_pad = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("gpio_wb_tb.vcd"); + $dumpvars(0, gpio_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test GPIO Wishbone Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // GPIO Internal Register Addresses + wire [31:0] gpio_adr = uut.BASE_ADR | uut.GPIO_DATA; + wire [31:0] gpio_oeb_adr = uut.BASE_ADR | uut.GPIO_ENA; + wire [31:0] gpio_pu_adr = uut.BASE_ADR | uut.GPIO_PU; + wire [31:0] gpio_pd_adr = uut.BASE_ADR | uut.GPIO_PD; + + reg [15:0] gpio_data; + reg [15:0] gpio_pu; + reg [15:0] gpio_pd; + reg [15:0] gpio_oeb; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to gpio_data reg + gpio_in_pad = 16'h FFFF; + gpio_data = 16'h A000; + write(gpio_adr, gpio_data); + + #2; + // Read from gpio_data reg + read(gpio_adr); + if (wb_dat_o !== {gpio_data, gpio_in_pad}) begin + $display("Monitor: Error reading from gpio reg"); + $finish; + end + + #2; + // Write to pull-up reg + gpio_pu = 16'h 000f; + write(gpio_pu_adr, gpio_pu); + + #2; + // Read from pull-up reg + read(gpio_pu_adr); + if (wb_dat_o !== {16'd0, gpio_pu}) begin + $display("Monitor: Error reading from gpio pull-up reg"); + $finish; + end + + #2; + // Write to pull-down reg + gpio_pd = 16'h 00f0; + write(gpio_pd_adr, gpio_pd); + + #2; + // Read from pull-down reg + read(gpio_pd_adr); + if (wb_dat_o !== {16'd0, gpio_pd}) begin + $display("Monitor: Error reading from gpio pull-down reg"); + $finish; + end + + #2; + // Write to gpio enable reg + gpio_oeb = 16'h 00ff; + write(gpio_oeb_adr, gpio_oeb); + + #2; + // Read from gpio enable reg + read(gpio_oeb_adr); + if (wb_dat_o !== {16'd0, gpio_oeb}) begin + $display("Monitor: Error reading from gpio output enable reg"); + $finish; + end + + #6; + $display("Monitor: GPIO WB Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + gpio_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + .gpio_in_pad(gpio_in_pad) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/intercon_wb/Makefile b/verilog/dv/wb/intercon_wb/Makefile new file mode 100644 index 0000000..e061e8d --- /dev/null +++ b/verilog/dv/wb/intercon_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = intercon_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb/intercon_wb/intercon_wb_tb.v b/verilog/dv/wb/intercon_wb/intercon_wb_tb.v new file mode 100644 index 0000000..14702f9 --- /dev/null +++ b/verilog/dv/wb/intercon_wb/intercon_wb_tb.v
@@ -0,0 +1,187 @@ + + +`timescale 1 ns / 1 ps + +`include "wb_intercon.v" +`include "dummy_slave.v" + +`define AW 32 +`define DW 32 +`define NS 6 + +`define SLAVE_ADR { \ + {8'h28, {24{1'b0}} }, \ + {8'h23, {24{1'b0}} }, \ + {8'h21, {24{1'b0}} }, \ + {8'h20, {24{1'b0}} }, \ + {8'h10, {24{1'b0}} }, \ + {8'h00, {24{1'b0}} } \ +}\ + +`define ADR_MASK { \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} } \ +}\ + +module intercon_wb_tb; + + localparam SEL = `DW / 8; + + reg wb_clk_i; + reg wb_rst_i; + + // Master Interface + reg wbm_stb_i; + reg wbm_cyc_i; + reg wbm_we_i; + reg [SEL-1:0] wbm_sel_i; + reg [`AW-1:0] wbm_adr_i; + reg [`DW-1:0] wbm_dat_i; + + wire [`DW-1:0] wbm_dat_o; + wire wbm_ack_o; + + // Wishbone Slave Interface + wire [`NS-1:0] wbs_stb_i; + wire [`NS-1:0] wbs_ack_o; + wire [(`NS*`DW)-1:0] wbs_adr_i; + wire [(`NS*`AW)-1:0] wbs_dat_i; + wire [(`NS*`DW)-1:0] wbs_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wbm_adr_i = 0; + wbm_dat_i = 0; + wbm_sel_i = 0; + wbm_we_i = 0; + wbm_cyc_i = 0; + wbm_stb_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("intercon_wb_tb.vcd"); + $dumpvars(0, intercon_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone Interconnect Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [`AW*`NS-1: 0] addr = `SLAVE_ADR; + reg [`DW:0] slave_data; + reg [`AW:0] slave_addr; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // W/R from all slaves + for (i=0; i<`NS; i=i+1) begin + slave_addr = addr[i*`AW +: `AW]; + slave_data = $urandom_range(0, 2**32); + write(slave_addr, slave_data); + #2; + read(slave_addr); + if (wbm_dat_o !== slave_data) begin + $display("%c[1;31m",27); + $display ("Monitor: Reading from slave %0d failed", i); + $display("Monitor: Test Wishbone Interconnect failed"); + $display("%c[0m",27); + $finish; + end + end + $display("Monitor: Test Wishbone Interconnect Success!"); + $finish; + end + + task write; + input [`AW-1:0] addr; + input [`AW-1:0] data; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_sel_i = {SEL{1'b1}}; + wbm_we_i = 1; + wbm_adr_i = addr; + wbm_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wbm_ack_o == 1); + wait(wbm_ack_o == 0); + wbm_cyc_i = 0; + wbm_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [`AW-1:0] addr; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_adr_i = addr; + wbm_we_i = 0; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wbm_ack_o == 1); + wait(wbm_ack_o == 0); + wbm_cyc_i = 0; + wbm_stb_i = 0; + $display("Read Cycle Ended."); + + end + endtask + + wb_intercon #( + .AW(`AW), + .DW(`DW), + .NS(`NS), + .ADR_MASK(`ADR_MASK), + .SLAVE_ADR(`SLAVE_ADR) + ) uut( + // Master Interface + .wbm_adr_i(wbm_adr_i), + .wbm_stb_i(wbm_stb_i), + .wbm_dat_o(wbm_dat_o), + .wbm_ack_o(wbm_ack_o), + + // Slave Interface + .wbs_stb_o(wbs_stb_i), + .wbs_dat_i(wbs_dat_o), + .wbs_ack_i(wbs_ack_o) + ); + + // Instantiate five dummy slaves for testing + dummy_slave dummy_slaves [`NS-1:0]( + .wb_clk_i({`NS{wb_clk_i}}), + .wb_rst_i({`NS{wb_rst_i}}), + .wb_stb_i(wbs_stb_i), + .wb_cyc_i(wbm_cyc_i), + .wb_we_i(wbm_we_i), + .wb_sel_i(wbm_sel_i), + .wb_adr_i(wbm_adr_i), + .wb_dat_i(wbm_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/la_wb/Makefile b/verilog/dv/wb/la_wb/Makefile new file mode 100644 index 0000000..216614f --- /dev/null +++ b/verilog/dv/wb/la_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = la_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb/la_wb/la_wb_tb.v b/verilog/dv/wb/la_wb/la_wb_tb.v new file mode 100644 index 0000000..2c50186 --- /dev/null +++ b/verilog/dv/wb/la_wb/la_wb_tb.v
@@ -0,0 +1,208 @@ +`timescale 1 ns / 1 ps + +`include "la_wb.v" + +module la_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("la_wb_tb.vcd"); + $dumpvars(0, la_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone LA Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // LA Wishbone Internal Register Addresses + wire [31:0] la_data_adr_0 = uut.BASE_ADR | uut.LA_DATA_0; + wire [31:0] la_data_adr_1 = uut.BASE_ADR | uut.LA_DATA_1; + wire [31:0] la_data_adr_2 = uut.BASE_ADR | uut.LA_DATA_2; + wire [31:0] la_data_adr_3 = uut.BASE_ADR | uut.LA_DATA_3; + + wire [31:0] la_ena_adr_0 = uut.BASE_ADR | uut.LA_ENA_0; + wire [31:0] la_ena_adr_1 = uut.BASE_ADR | uut.LA_ENA_1; + wire [31:0] la_ena_adr_2 = uut.BASE_ADR | uut.LA_ENA_2; + wire [31:0] la_ena_adr_3 = uut.BASE_ADR | uut.LA_ENA_3; + + reg [31:0] la_data_0; + reg [31:0] la_data_1; + reg [31:0] la_data_2; + reg [31:0] la_data_3; + + reg [31:0] la_ena_0; + reg [31:0] la_ena_1; + reg [31:0] la_ena_2; + reg [31:0] la_ena_3; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to la data registers + la_data_0 = $urandom_range(0, 2**32); + la_data_1 = $urandom_range(0, 2**32); + la_data_2 = $urandom_range(0, 2**32); + la_data_3 = $urandom_range(0, 2**32); + + write(la_data_adr_0, la_data_0); + write(la_data_adr_1, la_data_1); + write(la_data_adr_2, la_data_2); + write(la_data_adr_3, la_data_3); + + #2; + // Read from la data registers + read(la_data_adr_0); + if (wb_dat_o !== la_data_0) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_1); + if (wb_dat_o !== la_data_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_2); + if (wb_dat_o !== la_data_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_3); + if (wb_dat_o !== la_data_3) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + // Write to la emable registers + la_ena_0 = $urandom_range(0, 2**32); + la_ena_1 = $urandom_range(0, 2**32); + la_ena_2 = $urandom_range(0, 2**32); + la_ena_3 = $urandom_range(0, 2**32); + + write(la_ena_adr_0, la_ena_0); + write(la_ena_adr_1, la_ena_1); + write(la_ena_adr_2, la_ena_2); + write(la_ena_adr_3, la_ena_3); + + #2; + // Read from la data registers + read(la_ena_adr_0); + if (wb_dat_o !== la_ena_0) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_1); + if (wb_dat_o !== la_ena_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_2); + if (wb_dat_o !== la_ena_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_3); + if (wb_dat_o !== la_ena_3) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + #6; + $display("Monitor: Test LA Wishbone Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + la_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/la_wb/la_wb_tb.vcd b/verilog/dv/wb/la_wb/la_wb_tb.vcd new file mode 100644 index 0000000..9a9969d --- /dev/null +++ b/verilog/dv/wb/la_wb/la_wb_tb.vcd
@@ -0,0 +1,635 @@ +$date + Fri Aug 21 14:19:50 2020 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module la_wb_tb $end +$var wire 32 ! la_data_adr_0 [31:0] $end +$var wire 32 " la_data_adr_1 [31:0] $end +$var wire 32 # la_data_adr_2 [31:0] $end +$var wire 32 $ la_data_adr_3 [31:0] $end +$var wire 32 % la_ena_adr_0 [31:0] $end +$var wire 32 & la_ena_adr_1 [31:0] $end +$var wire 32 ' la_ena_adr_2 [31:0] $end +$var wire 32 ( la_ena_adr_3 [31:0] $end +$var wire 32 ) wb_dat_o [31:0] $end +$var wire 1 * wb_ack_o $end +$var reg 32 + la_data_0 [31:0] $end +$var reg 32 , la_data_1 [31:0] $end +$var reg 32 - la_data_2 [31:0] $end +$var reg 32 . la_data_3 [31:0] $end +$var reg 32 / la_ena_0 [31:0] $end +$var reg 32 0 la_ena_1 [31:0] $end +$var reg 32 1 la_ena_2 [31:0] $end +$var reg 32 2 la_ena_3 [31:0] $end +$var reg 32 3 wb_adr_i [31:0] $end +$var reg 1 4 wb_clk_i $end +$var reg 1 5 wb_cyc_i $end +$var reg 32 6 wb_dat_i [31:0] $end +$var reg 1 7 wb_rst_i $end +$var reg 4 8 wb_sel_i [3:0] $end +$var reg 1 9 wb_stb_i $end +$var reg 1 : wb_we_i $end +$scope module uut $end +$var wire 4 ; iomem_we [3:0] $end +$var wire 1 < resetn $end +$var wire 1 = valid $end +$var wire 1 * wb_ack_o $end +$var wire 32 > wb_adr_i [31:0] $end +$var wire 1 4 wb_clk_i $end +$var wire 1 5 wb_cyc_i $end +$var wire 32 ? wb_dat_i [31:0] $end +$var wire 1 7 wb_rst_i $end +$var wire 4 @ wb_sel_i [3:0] $end +$var wire 1 9 wb_stb_i $end +$var wire 1 : wb_we_i $end +$var wire 32 A wb_dat_o [31:0] $end +$var wire 1 B ready $end +$var wire 128 C la_ena [127:0] $end +$var wire 128 D la_data [127:0] $end +$scope module la_ctrl $end +$var wire 1 4 clk $end +$var wire 32 E iomem_addr [31:0] $end +$var wire 1 = iomem_valid $end +$var wire 32 F iomem_wdata [31:0] $end +$var wire 4 G iomem_wstrb [3:0] $end +$var wire 1 < resetn $end +$var wire 4 H la_ena_sel [3:0] $end +$var wire 128 I la_ena [127:0] $end +$var wire 4 J la_data_sel [3:0] $end +$var wire 128 K la_data [127:0] $end +$var reg 32 L iomem_rdata [31:0] $end +$var reg 1 B iomem_ready $end +$var reg 32 M la_data_0 [31:0] $end +$var reg 32 N la_data_1 [31:0] $end +$var reg 32 O la_data_2 [31:0] $end +$var reg 32 P la_data_3 [31:0] $end +$var reg 32 Q la_ena_0 [31:0] $end +$var reg 32 R la_ena_1 [31:0] $end +$var reg 32 S la_ena_2 [31:0] $end +$var reg 32 T la_ena_3 [31:0] $end +$upscope $end +$upscope $end +$scope task read $end +$var reg 33 U addr [32:0] $end +$upscope $end +$scope task write $end +$var reg 33 V addr [32:0] $end +$var reg 33 W data [32:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +bx W +bx V +bx U +bx T +bx S +bx R +bx Q +bx P +bx O +bx N +bx M +bx L +bx K +b1 J +bx I +b0 H +b0 G +b0 F +b0 E +bx D +bx C +xB +bx A +b0 @ +b0 ? +b0 > +0= +0< +b0 ; +0: +09 +b0 8 +17 +b0 6 +05 +04 +b0 3 +bx 2 +bx 1 +bx 0 +bx / +bx . +bx - +bx , +bx + +x* +bx ) +b100010000000000000000000011100 ( +b100010000000000000000000011000 ' +b100010000000000000000000010100 & +b100010000000000000000000010000 % +b100010000000000000000000001100 $ +b100010000000000000000000001000 # +b100010000000000000000000000100 " +b100010000000000000000000000000 ! +$end +#1000 +b0 T +b0 S +b0 R +b0 C +b0 I +b0 Q +b0 P +b0 O +b0 N +b0 D +b0 K +b0 M +14 +#2000 +1< +04 +07 +#3000 +0* +0B +14 +#4000 +04 +b0 W +b100010000000000000000000000000 V +b0 . +b0 - +b0 , +b0 + +#5000 +b1111 ; +b1111 G +1= +b100010000000000000000000000000 3 +b100010000000000000000000000000 > +b100010000000000000000000000000 E +1: +b1111 8 +b1111 @ +15 +19 +14 +#6000 +04 +#7000 +b0 ) +b0 A +b0 L +1* +1B +14 +#8000 +04 +#9000 +0= +b100010000000000000000000000100 V +09 +05 +0* +0B +14 +#10000 +04 +#11000 +b10 J +1= +b100010000000000000000000000100 3 +b100010000000000000000000000100 > +b100010000000000000000000000100 E +15 +19 +14 +#12000 +04 +#13000 +1* +1B +14 +#14000 +04 +#15000 +0= +b100010000000000000000000001000 V +09 +05 +0* +0B +14 +#16000 +04 +#17000 +b100 J +1= +b100010000000000000000000001000 3 +b100010000000000000000000001000 > +b100010000000000000000000001000 E +15 +19 +14 +#18000 +04 +#19000 +1* +1B +14 +#20000 +04 +#21000 +0= +b100010000000000000000000001100 V +09 +05 +0* +0B +14 +#22000 +04 +#23000 +b1000 J +1= +b100010000000000000000000001100 3 +b100010000000000000000000001100 > +b100010000000000000000000001100 E +15 +19 +14 +#24000 +04 +#25000 +1* +1B +14 +#26000 +04 +#27000 +0= +09 +05 +0* +0B +14 +#28000 +04 +#29000 +b1 J +b0 ; +b0 G +1= +b100010000000000000000000000000 3 +b100010000000000000000000000000 > +b100010000000000000000000000000 E +0: +15 +19 +14 +b100010000000000000000000000000 U +#30000 +04 +#31000 +1* +1B +14 +#32000 +04 +#33000 +0= +b100010000000000000000000000100 U +09 +05 +0* +0B +14 +#34000 +04 +#35000 +b10 J +1= +b100010000000000000000000000100 3 +b100010000000000000000000000100 > +b100010000000000000000000000100 E +15 +19 +14 +#36000 +04 +#37000 +1* +1B +14 +#38000 +04 +#39000 +0= +b100010000000000000000000001000 U +09 +05 +0* +0B +14 +#40000 +04 +#41000 +b100 J +1= +b100010000000000000000000001000 3 +b100010000000000000000000001000 > +b100010000000000000000000001000 E +15 +19 +14 +#42000 +04 +#43000 +1* +1B +14 +#44000 +04 +#45000 +0= +b100010000000000000000000001100 U +09 +05 +0* +0B +14 +#46000 +04 +#47000 +b1000 J +1= +b100010000000000000000000001100 3 +b100010000000000000000000001100 > +b100010000000000000000000001100 E +15 +19 +14 +#48000 +04 +#49000 +1* +1B +14 +#50000 +04 +#51000 +0= +b100010000000000000000000010000 V +b0 2 +b0 1 +b0 0 +b0 / +09 +05 +0* +0B +14 +#52000 +04 +#53000 +b0 J +b1 H +b1111 ; +b1111 G +1= +b100010000000000000000000010000 3 +b100010000000000000000000010000 > +b100010000000000000000000010000 E +1: +15 +19 +14 +#54000 +04 +#55000 +1* +1B +14 +#56000 +04 +#57000 +0= +b100010000000000000000000010100 V +09 +05 +0* +0B +14 +#58000 +04 +#59000 +b10 H +1= +b100010000000000000000000010100 3 +b100010000000000000000000010100 > +b100010000000000000000000010100 E +15 +19 +14 +#60000 +04 +#61000 +1* +1B +14 +#62000 +04 +#63000 +0= +b100010000000000000000000011000 V +09 +05 +0* +0B +14 +#64000 +04 +#65000 +b100 H +1= +b100010000000000000000000011000 3 +b100010000000000000000000011000 > +b100010000000000000000000011000 E +15 +19 +14 +#66000 +04 +#67000 +1* +1B +14 +#68000 +04 +#69000 +0= +b100010000000000000000000011100 V +09 +05 +0* +0B +14 +#70000 +04 +#71000 +b1000 H +1= +b100010000000000000000000011100 3 +b100010000000000000000000011100 > +b100010000000000000000000011100 E +15 +19 +14 +#72000 +04 +#73000 +1* +1B +14 +#74000 +04 +#75000 +0= +09 +05 +0* +0B +14 +#76000 +04 +#77000 +b1 H +b0 ; +b0 G +1= +b100010000000000000000000010000 3 +b100010000000000000000000010000 > +b100010000000000000000000010000 E +0: +15 +19 +14 +b100010000000000000000000010000 U +#78000 +04 +#79000 +1* +1B +14 +#80000 +04 +#81000 +0= +b100010000000000000000000010100 U +09 +05 +0* +0B +14 +#82000 +04 +#83000 +b10 H +1= +b100010000000000000000000010100 3 +b100010000000000000000000010100 > +b100010000000000000000000010100 E +15 +19 +14 +#84000 +04 +#85000 +1* +1B +14 +#86000 +04 +#87000 +0= +b100010000000000000000000011000 U +09 +05 +0* +0B +14 +#88000 +04 +#89000 +b100 H +1= +b100010000000000000000000011000 3 +b100010000000000000000000011000 > +b100010000000000000000000011000 E +15 +19 +14 +#90000 +04 +#91000 +1* +1B +14 +#92000 +04 +#93000 +0= +b100010000000000000000000011100 U +09 +05 +0* +0B +14 +#94000 +04 +#95000 +b1000 H +1= +b100010000000000000000000011100 3 +b100010000000000000000000011100 > +b100010000000000000000000011100 E +15 +19 +14 +#96000 +04 +#97000 +1* +1B +14 +#98000 +04 +#99000 +0= +09 +05 +0* +0B +14 +#100000 +04 +#101000 +14 +#102000 +04 +#103000 +14 +#104000 +04 +#105000 +14
diff --git a/verilog/dv/wb/la_wb/ldo_wb_tb.vcd b/verilog/dv/wb/la_wb/ldo_wb_tb.vcd new file mode 100644 index 0000000..a0e252e --- /dev/null +++ b/verilog/dv/wb/la_wb/ldo_wb_tb.vcd
@@ -0,0 +1,635 @@ +$date + Thu Aug 20 00:22:06 2020 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module ldo_wb_tb $end +$var wire 32 ! ldo_data_adr_0 [31:0] $end +$var wire 32 " ldo_data_adr_1 [31:0] $end +$var wire 32 # ldo_data_adr_2 [31:0] $end +$var wire 32 $ ldo_data_adr_3 [31:0] $end +$var wire 32 % ldo_ena_adr_0 [31:0] $end +$var wire 32 & ldo_ena_adr_1 [31:0] $end +$var wire 32 ' ldo_ena_adr_2 [31:0] $end +$var wire 32 ( ldo_ena_adr_3 [31:0] $end +$var wire 32 ) wb_dat_o [31:0] $end +$var wire 1 * wb_ack_o $end +$var reg 32 + ldo_data_0 [31:0] $end +$var reg 32 , ldo_data_1 [31:0] $end +$var reg 32 - ldo_data_2 [31:0] $end +$var reg 32 . ldo_data_3 [31:0] $end +$var reg 32 / ldo_ena_0 [31:0] $end +$var reg 32 0 ldo_ena_1 [31:0] $end +$var reg 32 1 ldo_ena_2 [31:0] $end +$var reg 32 2 ldo_ena_3 [31:0] $end +$var reg 32 3 wb_adr_i [31:0] $end +$var reg 1 4 wb_clk_i $end +$var reg 1 5 wb_cyc_i $end +$var reg 32 6 wb_dat_i [31:0] $end +$var reg 1 7 wb_rst_i $end +$var reg 4 8 wb_sel_i [3:0] $end +$var reg 1 9 wb_stb_i $end +$var reg 1 : wb_we_i $end +$scope module uut $end +$var wire 4 ; iomem_we [3:0] $end +$var wire 1 < resetn $end +$var wire 1 = valid $end +$var wire 1 * wb_ack_o $end +$var wire 32 > wb_adr_i [31:0] $end +$var wire 1 4 wb_clk_i $end +$var wire 1 5 wb_cyc_i $end +$var wire 32 ? wb_dat_i [31:0] $end +$var wire 1 7 wb_rst_i $end +$var wire 4 @ wb_sel_i [3:0] $end +$var wire 1 9 wb_stb_i $end +$var wire 1 : wb_we_i $end +$var wire 32 A wb_dat_o [31:0] $end +$var wire 1 B ready $end +$var wire 128 C ldo_ena [127:0] $end +$var wire 128 D ldo_data [127:0] $end +$scope module ldo_ctrl $end +$var wire 1 4 clk $end +$var wire 32 E iomem_addr [31:0] $end +$var wire 1 = iomem_valid $end +$var wire 32 F iomem_wdata [31:0] $end +$var wire 4 G iomem_wstrb [3:0] $end +$var wire 1 < resetn $end +$var wire 4 H ldo_ena_sel [3:0] $end +$var wire 128 I ldo_ena [127:0] $end +$var wire 4 J ldo_data_sel [3:0] $end +$var wire 128 K ldo_data [127:0] $end +$var reg 32 L iomem_rdata [31:0] $end +$var reg 1 B iomem_ready $end +$var reg 32 M ldo_data_0 [31:0] $end +$var reg 32 N ldo_data_1 [31:0] $end +$var reg 32 O ldo_data_2 [31:0] $end +$var reg 32 P ldo_data_3 [31:0] $end +$var reg 32 Q ldo_ena_0 [31:0] $end +$var reg 32 R ldo_ena_1 [31:0] $end +$var reg 32 S ldo_ena_2 [31:0] $end +$var reg 32 T ldo_ena_3 [31:0] $end +$upscope $end +$upscope $end +$scope task read $end +$var reg 33 U addr [32:0] $end +$upscope $end +$scope task write $end +$var reg 33 V addr [32:0] $end +$var reg 33 W data [32:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +bx W +bx V +bx U +bx T +bx S +bx R +bx Q +bx P +bx O +bx N +bx M +bx L +bx K +b1 J +bx I +b0 H +b0 G +b0 F +b0 E +bx D +bx C +xB +bx A +b0 @ +b0 ? +b0 > +0= +0< +b0 ; +0: +09 +b0 8 +17 +b0 6 +05 +04 +b0 3 +bx 2 +bx 1 +bx 0 +bx / +bx . +bx - +bx , +bx + +x* +bx ) +b100010000000000000000000011100 ( +b100010000000000000000000011000 ' +b100010000000000000000000010100 & +b100010000000000000000000010000 % +b100010000000000000000000001100 $ +b100010000000000000000000001000 # +b100010000000000000000000000100 " +b100010000000000000000000000000 ! +$end +#1000 +b0 T +b0 S +b0 R +b0 C +b0 I +b0 Q +b0 P +b0 O +b0 N +b0 D +b0 K +b0 M +14 +#2000 +1< +04 +07 +#3000 +0* +0B +14 +#4000 +04 +b0 W +b100010000000000000000000000000 V +b0 . +b0 - +b0 , +b0 + +#5000 +b1111 ; +b1111 G +1= +b100010000000000000000000000000 3 +b100010000000000000000000000000 > +b100010000000000000000000000000 E +1: +b1111 8 +b1111 @ +15 +19 +14 +#6000 +04 +#7000 +b0 ) +b0 A +b0 L +1* +1B +14 +#8000 +04 +#9000 +0= +b100010000000000000000000000100 V +09 +05 +0* +0B +14 +#10000 +04 +#11000 +b10 J +1= +b100010000000000000000000000100 3 +b100010000000000000000000000100 > +b100010000000000000000000000100 E +15 +19 +14 +#12000 +04 +#13000 +1* +1B +14 +#14000 +04 +#15000 +0= +b100010000000000000000000001000 V +09 +05 +0* +0B +14 +#16000 +04 +#17000 +b100 J +1= +b100010000000000000000000001000 3 +b100010000000000000000000001000 > +b100010000000000000000000001000 E +15 +19 +14 +#18000 +04 +#19000 +1* +1B +14 +#20000 +04 +#21000 +0= +b100010000000000000000000001100 V +09 +05 +0* +0B +14 +#22000 +04 +#23000 +b1000 J +1= +b100010000000000000000000001100 3 +b100010000000000000000000001100 > +b100010000000000000000000001100 E +15 +19 +14 +#24000 +04 +#25000 +1* +1B +14 +#26000 +04 +#27000 +0= +09 +05 +0* +0B +14 +#28000 +04 +#29000 +b1 J +b0 ; +b0 G +1= +b100010000000000000000000000000 3 +b100010000000000000000000000000 > +b100010000000000000000000000000 E +0: +15 +19 +14 +b100010000000000000000000000000 U +#30000 +04 +#31000 +1* +1B +14 +#32000 +04 +#33000 +0= +b100010000000000000000000000100 U +09 +05 +0* +0B +14 +#34000 +04 +#35000 +b10 J +1= +b100010000000000000000000000100 3 +b100010000000000000000000000100 > +b100010000000000000000000000100 E +15 +19 +14 +#36000 +04 +#37000 +1* +1B +14 +#38000 +04 +#39000 +0= +b100010000000000000000000001000 U +09 +05 +0* +0B +14 +#40000 +04 +#41000 +b100 J +1= +b100010000000000000000000001000 3 +b100010000000000000000000001000 > +b100010000000000000000000001000 E +15 +19 +14 +#42000 +04 +#43000 +1* +1B +14 +#44000 +04 +#45000 +0= +b100010000000000000000000001100 U +09 +05 +0* +0B +14 +#46000 +04 +#47000 +b1000 J +1= +b100010000000000000000000001100 3 +b100010000000000000000000001100 > +b100010000000000000000000001100 E +15 +19 +14 +#48000 +04 +#49000 +1* +1B +14 +#50000 +04 +#51000 +0= +b100010000000000000000000010000 V +b0 2 +b0 1 +b0 0 +b0 / +09 +05 +0* +0B +14 +#52000 +04 +#53000 +b0 J +b1 H +b1111 ; +b1111 G +1= +b100010000000000000000000010000 3 +b100010000000000000000000010000 > +b100010000000000000000000010000 E +1: +15 +19 +14 +#54000 +04 +#55000 +1* +1B +14 +#56000 +04 +#57000 +0= +b100010000000000000000000010100 V +09 +05 +0* +0B +14 +#58000 +04 +#59000 +b10 H +1= +b100010000000000000000000010100 3 +b100010000000000000000000010100 > +b100010000000000000000000010100 E +15 +19 +14 +#60000 +04 +#61000 +1* +1B +14 +#62000 +04 +#63000 +0= +b100010000000000000000000011000 V +09 +05 +0* +0B +14 +#64000 +04 +#65000 +b100 H +1= +b100010000000000000000000011000 3 +b100010000000000000000000011000 > +b100010000000000000000000011000 E +15 +19 +14 +#66000 +04 +#67000 +1* +1B +14 +#68000 +04 +#69000 +0= +b100010000000000000000000011100 V +09 +05 +0* +0B +14 +#70000 +04 +#71000 +b1000 H +1= +b100010000000000000000000011100 3 +b100010000000000000000000011100 > +b100010000000000000000000011100 E +15 +19 +14 +#72000 +04 +#73000 +1* +1B +14 +#74000 +04 +#75000 +0= +09 +05 +0* +0B +14 +#76000 +04 +#77000 +b1 H +b0 ; +b0 G +1= +b100010000000000000000000010000 3 +b100010000000000000000000010000 > +b100010000000000000000000010000 E +0: +15 +19 +14 +b100010000000000000000000010000 U +#78000 +04 +#79000 +1* +1B +14 +#80000 +04 +#81000 +0= +b100010000000000000000000010100 U +09 +05 +0* +0B +14 +#82000 +04 +#83000 +b10 H +1= +b100010000000000000000000010100 3 +b100010000000000000000000010100 > +b100010000000000000000000010100 E +15 +19 +14 +#84000 +04 +#85000 +1* +1B +14 +#86000 +04 +#87000 +0= +b100010000000000000000000011000 U +09 +05 +0* +0B +14 +#88000 +04 +#89000 +b100 H +1= +b100010000000000000000000011000 3 +b100010000000000000000000011000 > +b100010000000000000000000011000 E +15 +19 +14 +#90000 +04 +#91000 +1* +1B +14 +#92000 +04 +#93000 +0= +b100010000000000000000000011100 U +09 +05 +0* +0B +14 +#94000 +04 +#95000 +b1000 H +1= +b100010000000000000000000011100 3 +b100010000000000000000000011100 > +b100010000000000000000000011100 E +15 +19 +14 +#96000 +04 +#97000 +1* +1B +14 +#98000 +04 +#99000 +0= +09 +05 +0* +0B +14 +#100000 +04 +#101000 +14 +#102000 +04 +#103000 +14 +#104000 +04 +#105000 +14
diff --git a/verilog/dv/wb/mem_wb/Makefile b/verilog/dv/wb/mem_wb/Makefile new file mode 100644 index 0000000..82b2235 --- /dev/null +++ b/verilog/dv/wb/mem_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = mem_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb/mem_wb/mem_wb_tb.v b/verilog/dv/wb/mem_wb/mem_wb_tb.v new file mode 100644 index 0000000..eb45e22 --- /dev/null +++ b/verilog/dv/wb/mem_wb/mem_wb_tb.v
@@ -0,0 +1,143 @@ + + +`timescale 1 ns / 1 ps + +`define USE_OPENRAM + +`include "sram_1rw1r_32_256_8_sky130.v" +`include "mem_wb.v" + +module mem_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + reg [3:0] wb_sel_i; + reg wb_we_i; + reg wb_cyc_i; + reg wb_stb_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + + wb_stb_i = 0; // master select-signal for the slave + wb_we_i = 0; // R = 0 , W = 1 + wb_cyc_i = 0; // master is transferring + wb_adr_i = 0; // input addr 32-bits + wb_dat_i = 0; // input data 32-bits + wb_sel_i = 0; // where data is available on data_i 4-bits + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("mem_wb_tb.vcd"); + $dumpvars(0, mem_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone Memory Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [31:0] ref_data [255: 0]; + reg [31: 0] read_data; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Randomly Write to memory array + for ( i = 0; i < 1; i = i + 1) begin + ref_data[i] = $urandom_range(0, 2**32); + write(i, ref_data[i]); + #2; + end + + #6; + for ( i = 0; i < 1; i = i + 1) begin + read(i); + if (wb_dat_o !== ref_data[i]) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", ref_data[i], wb_dat_o); + $display("Monitor: Wishbone Memory Failed"); + $display("%c[0m",27); + $finish; + end + #2; + end + #6; + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + mem_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_cyc_i(wb_cyc_i), + .wb_stb_i(wb_stb_i), + + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/spi_sysctrl_wb/Makefile b/verilog/dv/wb/spi_sysctrl_wb/Makefile new file mode 100644 index 0000000..55b9235 --- /dev/null +++ b/verilog/dv/wb/spi_sysctrl_wb/Makefile
@@ -0,0 +1,18 @@ +.SUFFIXES: + +PATTERN = spi_sysctrl_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.v b/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.v new file mode 100644 index 0000000..0275a2c --- /dev/null +++ b/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.v
@@ -0,0 +1,226 @@ + + +`timescale 1 ns / 1 ps + +`include "spi_sysctrl.v" +`include "striVe_spi.v" + +module spi_sysctrl_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + wire [7:0] spi_ro_config; // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + wire [4:0] spi_ro_pll_div; + wire [2:0] spi_ro_pll_sel; + wire spi_ro_xtal_ena; + wire spi_ro_reg_ena; + wire [25:0] spi_ro_pll_trim; + wire spi_ro_pll_dco_ena; + wire [11:0] spi_ro_mfgr_id; + wire [7:0] spi_ro_prod_id; + wire [3:0] spi_ro_mask_rev; + wire spi_ro_pll_bypass; + + // HKSPI + reg RSTB; + reg SCK; + reg SDI; + reg CSB; + reg trap; + reg [3:0] mask_rev_in; + + wire SDO; + wire sdo_enb; + wire xtal_ena; + wire reg_ena; + wire pll_dco_ena; + wire [25:0] pll_trim; + wire [2:0] pll_sel; + wire [4:0] pll_div; + wire pll_bypass; + wire irq; + wire reset; + wire RST; + wire [11:0] mfgr_id; + wire [7:0] prod_id; + wire [3:0] mask_rev; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + CSB = 1; + SCK = 0; + SDI = 0; + RSTB = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + // System Control Default Register Addresses (Read-only reg) + wire [31:0] spi_cfg = uut.BASE_ADR | uut.SPI_CFG; // unused & reserved ? + wire [31:0] spi_ena = uut.BASE_ADR | uut.SPI_ENA; + wire [31:0] spi_pll_cfg = uut.BASE_ADR | uut.SPI_PLL_CFG; + wire [31:0] spi_mfgr_id = uut.BASE_ADR | uut.SPI_MFGR_ID; + wire [31:0] spi_prod_id = uut.BASE_ADR | uut.SPI_PROD_ID; + wire [31:0] spi_mask_rev = uut.BASE_ADR | uut.SPI_MASK_REV; + wire [31:0] spi_pll_bypass = uut.BASE_ADR | uut.SPI_PLL_BYPASS; + + initial begin + $dumpfile("spi_sysctrl_wb_tb.vcd"); + $dumpvars(0, spi_sysctrl_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test SPI System Control Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + initial begin + // Reset Operation + wb_rst_i = 1; + RSTB = 0; // active low reset + #2; + wb_rst_i = 0; + RSTB = 1; + #2; + + // Read mask_rev register + mask_rev_in = 4'hF; + read(spi_mask_rev); + if (wb_dat_o !== {28'd0, mask_rev_in}) begin + $display("Error reading mask_rev reg"); + $finish; + end + + // Read manufacture id register + read(spi_mfgr_id); + if (wb_dat_o !== {20'd0, 12'h456}) begin + $display("Error reading manufacture id reg"); + $finish; + end + + // Read product id register + read(spi_prod_id); + if (wb_dat_o !== {24'd0, 8'h05}) begin + $display("Error reading product id reg"); + $finish; + end + + // Read PLL-Bypass register + read(spi_pll_bypass); + if (wb_dat_o !== {31'd0, 1'b1}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + + // Read PLL-Configuration register + read(spi_pll_cfg); + if (wb_dat_o !== {5'd0, spi_ro_pll_trim, spi_ro_pll_dco_ena}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + + // Read SPI Enables register + read(spi_ena); + if (wb_dat_o !== {22'd0, spi_ro_pll_div, spi_ro_pll_sel, spi_ro_xtal_ena, spi_ro_reg_ena}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + $display("Success!"); + $finish; + end + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Monitor: Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Read Cycle Ended."); + end + endtask + + spi_sysctrl_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + + .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + .spi_ro_pll_div(spi_ro_pll_div), + .spi_ro_pll_sel(spi_ro_pll_sel), + .spi_ro_xtal_ena(spi_ro_xtal_ena), + .spi_ro_reg_ena(spi_ro_reg_ena), + + .spi_ro_pll_trim(spi_ro_pll_trim), + .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena), + + .spi_ro_mfgr_id(spi_ro_mfgr_id), + .spi_ro_prod_id(spi_ro_prod_id), + .spi_ro_mask_rev(spi_ro_mask_rev), + .pll_bypass(spi_ro_pll_bypass) + ); + + striVe_spi hkspi ( + .RSTB(RSTB), + .SCK(SCK), + .SDI(SDI), + .CSB(CSB), + + .SDO(SDO), + .sdo_enb(SDO_enb), + .xtal_ena(spi_ro_xtal_ena), + .reg_ena(spi_ro_reg_ena), + .pll_dco_ena(spi_ro_pll_dco_ena), + .pll_sel(spi_ro_pll_sel), + .pll_div(spi_ro_pll_div), + .pll_trim(spi_ro_pll_trim), + .pll_bypass(spi_ro_pll_bypass), + .irq(irq_spi), + .RST(por), + .reset(ext_reset), + .trap(trap), + .mfgr_id(spi_ro_mfgr_id), + .prod_id(spi_ro_prod_id), + .mask_rev_in(mask_rev_in), + .mask_rev(spi_ro_mask_rev) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.vcd b/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.vcd new file mode 100644 index 0000000..3abe514 --- /dev/null +++ b/verilog/dv/wb/spi_sysctrl_wb/spi_sysctrl_wb_tb.vcd
@@ -0,0 +1,460 @@ +$date + Fri Aug 21 14:21:00 2020 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module spi_sysctrl_wb_tb $end +$var wire 32 ! spi_cfg [31:0] $end +$var wire 32 " spi_ena [31:0] $end +$var wire 32 # spi_mask_rev [31:0] $end +$var wire 32 $ spi_mfgr_id [31:0] $end +$var wire 32 % spi_pll_bypass [31:0] $end +$var wire 32 & spi_pll_cfg [31:0] $end +$var wire 32 ' spi_prod_id [31:0] $end +$var wire 8 ( spi_ro_config [7:0] $end +$var wire 12 ) spi_ro_mfgr_id [11:0] $end +$var wire 8 * spi_ro_prod_id [7:0] $end +$var wire 32 + wb_dat_o [31:0] $end +$var wire 1 , wb_ack_o $end +$var wire 1 - spi_ro_xtal_ena $end +$var wire 1 . spi_ro_reg_ena $end +$var wire 26 / spi_ro_pll_trim [25:0] $end +$var wire 3 0 spi_ro_pll_sel [2:0] $end +$var wire 5 1 spi_ro_pll_div [4:0] $end +$var wire 1 2 spi_ro_pll_dco_ena $end +$var wire 1 3 spi_ro_pll_bypass $end +$var wire 4 4 spi_ro_mask_rev [3:0] $end +$var wire 1 5 por $end +$var wire 1 6 irq_spi $end +$var wire 1 7 ext_reset $end +$var wire 1 8 SDO_enb $end +$var wire 1 9 SDO $end +$var reg 1 : CSB $end +$var reg 1 ; RSTB $end +$var reg 1 < SCK $end +$var reg 1 = SDI $end +$var reg 4 > mask_rev_in [3:0] $end +$var reg 1 ? trap $end +$var reg 32 @ wb_adr_i [31:0] $end +$var reg 1 A wb_clk_i $end +$var reg 1 B wb_cyc_i $end +$var reg 32 C wb_dat_i [31:0] $end +$var reg 1 D wb_rst_i $end +$var reg 4 E wb_sel_i [3:0] $end +$var reg 1 F wb_stb_i $end +$var reg 1 G wb_we_i $end +$scope module hkspi $end +$var wire 1 : CSB $end +$var wire 1 5 RST $end +$var wire 1 ; RSTB $end +$var wire 1 < SCK $end +$var wire 1 = SDI $end +$var wire 4 H mask_rev [3:0] $end +$var wire 4 I mask_rev_in [3:0] $end +$var wire 12 J mfgr_id [11:0] $end +$var wire 8 K prod_id [7:0] $end +$var wire 1 ? trap $end +$var wire 1 L wrstb $end +$var wire 1 8 sdo_enb $end +$var wire 1 M rdstb $end +$var wire 8 N odata [7:0] $end +$var wire 8 O idata [7:0] $end +$var wire 8 P iaddr [7:0] $end +$var wire 1 9 SDO $end +$var reg 1 6 irq $end +$var reg 1 3 pll_bypass $end +$var reg 1 2 pll_dco_ena $end +$var reg 5 Q pll_div [4:0] $end +$var reg 3 R pll_sel [2:0] $end +$var reg 26 S pll_trim [25:0] $end +$var reg 1 . reg_ena $end +$var reg 1 7 reset $end +$var reg 1 - xtal_ena $end +$scope module U1 $end +$var wire 1 : CSB $end +$var wire 1 < SCK $end +$var wire 1 = SDI $end +$var wire 8 T idata [7:0] $end +$var wire 8 U odata [7:0] $end +$var wire 8 V oaddr [7:0] $end +$var wire 1 9 SDO $end +$var reg 8 W addr [7:0] $end +$var reg 3 X count [2:0] $end +$var reg 3 Y fixed [2:0] $end +$var reg 8 Z ldata [7:0] $end +$var reg 7 [ predata [6:0] $end +$var reg 1 M rdstb $end +$var reg 1 \ readmode $end +$var reg 1 8 sdoenb $end +$var reg 2 ] state [1:0] $end +$var reg 1 ^ writemode $end +$var reg 1 L wrstb $end +$upscope $end +$upscope $end +$scope module uut $end +$var wire 4 _ iomem_we [3:0] $end +$var wire 1 3 pll_bypass $end +$var wire 1 ` resetn $end +$var wire 8 a spi_ro_config [7:0] $end +$var wire 4 b spi_ro_mask_rev [3:0] $end +$var wire 12 c spi_ro_mfgr_id [11:0] $end +$var wire 1 2 spi_ro_pll_dco_ena $end +$var wire 5 d spi_ro_pll_div [4:0] $end +$var wire 3 e spi_ro_pll_sel [2:0] $end +$var wire 26 f spi_ro_pll_trim [25:0] $end +$var wire 8 g spi_ro_prod_id [7:0] $end +$var wire 1 . spi_ro_reg_ena $end +$var wire 1 - spi_ro_xtal_ena $end +$var wire 1 h valid $end +$var wire 1 , wb_ack_o $end +$var wire 32 i wb_adr_i [31:0] $end +$var wire 1 A wb_clk_i $end +$var wire 1 B wb_cyc_i $end +$var wire 32 j wb_dat_i [31:0] $end +$var wire 1 D wb_rst_i $end +$var wire 4 k wb_sel_i [3:0] $end +$var wire 1 F wb_stb_i $end +$var wire 1 G wb_we_i $end +$var wire 32 l wb_dat_o [31:0] $end +$var wire 1 m ready $end +$scope module spi_sysctrl $end +$var wire 1 A clk $end +$var wire 32 n iomem_addr [31:0] $end +$var wire 1 h iomem_valid $end +$var wire 32 o iomem_wdata [31:0] $end +$var wire 4 p iomem_wstrb [3:0] $end +$var wire 1 3 pll_bypass $end +$var wire 1 ` resetn $end +$var wire 8 q spi_ro_config [7:0] $end +$var wire 4 r spi_ro_mask_rev [3:0] $end +$var wire 12 s spi_ro_mfgr_id [11:0] $end +$var wire 1 2 spi_ro_pll_dco_ena $end +$var wire 5 t spi_ro_pll_div [4:0] $end +$var wire 3 u spi_ro_pll_sel [2:0] $end +$var wire 26 v spi_ro_pll_trim [25:0] $end +$var wire 8 w spi_ro_prod_id [7:0] $end +$var wire 1 . spi_ro_reg_ena $end +$var wire 1 - spi_ro_xtal_ena $end +$var wire 1 x spi_prod_sel $end +$var wire 1 y spi_mfgr_sel $end +$var wire 1 z spi_maskrev_sel $end +$var wire 1 { spi_ena_sel $end +$var wire 1 | spi_cfg_sel $end +$var wire 1 } pll_cfg_sel $end +$var wire 1 ~ pll_bypass_sel $end +$var reg 32 !" iomem_rdata [31:0] $end +$var reg 1 m iomem_ready $end +$upscope $end +$upscope $end +$scope task read $end +$var reg 33 "" addr [32:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +bx "" +bx !" +0~ +0} +1| +0{ +0z +0y +0x +b101 w +b11111111111110111111111111 v +b0 u +b100 t +b10001010110 s +bx r +bz q +b0 p +b0 o +b0 n +xm +bx l +b0 k +b0 j +b0 i +0h +b101 g +b11111111111110111111111111 f +b0 e +b100 d +b10001010110 c +bx b +bz a +0` +b0 _ +0^ +b0 ] +0\ +b0 [ +b0 Z +b0 Y +b0 X +b0 W +b0 V +b0 U +b0 T +b11111111111110111111111111 S +b0 R +b100 Q +b0 P +b0 O +b0 N +0M +0L +b101 K +b10001010110 J +bx I +bx H +0G +0F +b0 E +1D +b0 C +0B +0A +b0 @ +x? +bx > +0= +0< +0; +1: +09 +18 +07 +06 +15 +bx 4 +13 +12 +b100 1 +b0 0 +b11111111111110111111111111 / +1. +1- +x, +bx + +b101 * +b10001010110 ) +bz ( +b101110000000000000000000010000 ' +b101110000000000000000000001000 & +b101110000000000000000000011000 % +b101110000000000000000000001100 $ +b101110000000000000000000010100 # +b101110000000000000000000000100 " +b101110000000000000000000000000 ! +$end +#1000 +0, +0m +1A +#2000 +05 +1` +0A +1; +0D +#3000 +1A +#4000 +0A +b101110000000000000000000010100 "" +b1111 4 +b1111 H +b1111 b +b1111 r +b1111 > +b1111 I +#5000 +0| +1z +1h +b101110000000000000000000010100 @ +b101110000000000000000000010100 i +b101110000000000000000000010100 n +1B +1F +1A +#6000 +0A +#7000 +b1111 + +b1111 l +b1111 !" +1, +1m +1A +#8000 +0A +#9000 +0h +b101110000000000000000000001100 "" +0F +0B +0, +0m +1A +#10000 +0A +#11000 +1y +0z +1h +b101110000000000000000000001100 @ +b101110000000000000000000001100 i +b101110000000000000000000001100 n +1B +1F +1A +#12000 +0A +#13000 +b10001010110 + +b10001010110 l +b10001010110 !" +1, +1m +1A +#14000 +0A +#15000 +0h +b101110000000000000000000010000 "" +0F +0B +0, +0m +1A +#16000 +0A +#17000 +0y +1x +1h +b101110000000000000000000010000 @ +b101110000000000000000000010000 i +b101110000000000000000000010000 n +1B +1F +1A +#18000 +0A +#19000 +b101 + +b101 l +b101 !" +1, +1m +1A +#20000 +0A +#21000 +0h +b101110000000000000000000011000 "" +0F +0B +0, +0m +1A +#22000 +0A +#23000 +0x +1~ +1h +b101110000000000000000000011000 @ +b101110000000000000000000011000 i +b101110000000000000000000011000 n +1B +1F +1A +#24000 +0A +#25000 +b1 + +b1 l +b1 !" +1, +1m +1A +#26000 +0A +#27000 +0h +b101110000000000000000000001000 "" +0F +0B +0, +0m +1A +#28000 +0A +#29000 +1} +0~ +1h +b101110000000000000000000001000 @ +b101110000000000000000000001000 i +b101110000000000000000000001000 n +1B +1F +1A +#30000 +0A +#31000 +b111111111111101111111111111 + +b111111111111101111111111111 l +b111111111111101111111111111 !" +1, +1m +1A +#32000 +0A +#33000 +0h +b101110000000000000000000000100 "" +0F +0B +0, +0m +1A +#34000 +0A +#35000 +1{ +0} +1h +b101110000000000000000000000100 @ +b101110000000000000000000000100 i +b101110000000000000000000000100 n +1B +1F +1A +#36000 +0A +#37000 +b10000011 + +b10000011 l +b10000011 !" +1, +1m +1A +#38000 +0A +#39000 +0h +0F +0B +0, +0m +1A
diff --git a/verilog/dv/wb/spimemio_wb/Makefile b/verilog/dv/wb/spimemio_wb/Makefile new file mode 100644 index 0000000..075241d --- /dev/null +++ b/verilog/dv/wb/spimemio_wb/Makefile
@@ -0,0 +1,18 @@ +.SUFFIXES: + +PATTERN = spimemio_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../ -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb/spimemio_wb/flash.hex b/verilog/dv/wb/spimemio_wb/flash.hex new file mode 100644 index 0000000..23bd76d --- /dev/null +++ b/verilog/dv/wb/spimemio_wb/flash.hex
@@ -0,0 +1,6 @@ +@10000000 +a1 +b1 +c1 +d1 +f1 \ No newline at end of file
diff --git a/verilog/dv/wb/spimemio_wb/spimemio_wb_tb.v b/verilog/dv/wb/spimemio_wb/spimemio_wb_tb.v new file mode 100644 index 0000000..b75e6fc --- /dev/null +++ b/verilog/dv/wb/spimemio_wb/spimemio_wb_tb.v
@@ -0,0 +1,217 @@ + + +`timescale 1 ns / 1 ps + +`define FLASH_BASE 32'h 1000_000 + +`include "spimemio.v" +// `include "spiflash.v" + +module spimemio_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_flash_stb_i; + reg wb_cfg_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + + wire wb_flash_ack_o; + wire wb_cfg_ack_o; + wire [31:0] wb_flash_dat_o; + wire [31:0] wb_cfg_dat_o; + + wire flash_csb; + wire flash_clk; + + wire flash_io0_oeb; + wire flash_io1_oeb; + wire flash_io2_oeb; + wire flash_io3_oeb; + + wire flash_io0_di = 1'b 1; + wire flash_io1_di = 1'b 1; + wire flash_io2_di = 1'b 1; + wire flash_io3_di = 1'b 1; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_flash_stb_i = 0; + wb_cfg_stb_i = 0; + wb_cyc_i = 0; + wb_we_i = 0; + wb_sel_i = 0; + wb_adr_i = 0; + wb_dat_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + spimemio_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_flash_stb_i(wb_flash_stb_i), + .wb_cfg_stb_i(wb_cfg_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_we_i(wb_we_i), + .wb_sel_i(wb_sel_i), + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_flash_ack_o(wb_flash_ack_o), + .wb_cfg_ack_o(wb_cfg_ack_o), + .wb_flash_dat_o(wb_flash_dat_o), + .wb_cfg_dat_o(wb_cfg_dat_o), + + .flash_clk(flash_clk), + .flash_csb(flash_csb), + + .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_di(flash_io0_di), + .flash_io1_di(flash_io1_di), + .flash_io2_di(flash_io2_di), + .flash_io3_di(flash_io3_di) + ); + + initial begin + $dumpfile("spimemio_wb_tb.vcd"); + $dumpvars(0, spimemio_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test spimmemio Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + wire [31:0] cfgreg_data; + assign cfgreg_data = { + 1'b 1, + 8'b 0, + 3'b 111, + 4'b 1010, + 4'b 0, // make sure is it tied to zero in the module itself + {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb}, + 2'b 0, + flash_csb, + flash_clk, + {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di} + }; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Read from flash + for (i = `FLASH_BASE; i < `FLASH_BASE + 100 ; i = i + 4) begin + read(i, 1, 0); + if (wb_flash_dat_o !== 32'hFFFF_FFFF) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", 32'hFFFF_FFFF, wb_flash_dat_o); + $display("Monitor: Wishbone spimemio Failed"); + $display("%c[0m",27); + $finish; + end + #2; + end + + #6; + // Write to Configuration register + write(cfgreg_data, 0); + #2; + read(0, 0, 1); + if (wb_cfg_dat_o !== cfgreg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", cfgreg_data, wb_cfg_dat_o); + $display("Monitor: Wishbone spimemio Failed"); + $display("%c[0m",27); + $finish; + end + + $display("Success!"); + $finish; + end + + task write; + input [32:0] data; + input [31:0] addr; + begin + @(posedge wb_clk_i) begin + wb_cfg_stb_i = 1'b 1; + wb_flash_stb_i = 1'b 0; + wb_cyc_i = 1'b 1; + wb_sel_i = 4'b 1111; // complete word + wb_we_i = 1'b 1; // write enable + wb_adr_i = addr; + wb_dat_i = data; + end + + wait_ack(); + end + endtask + + task read; + input [32:0] addr; + input flash_stb; + input cfg_stb; + begin + wb_flash_stb_i = flash_stb; + wb_cfg_stb_i = cfg_stb; + + wb_cyc_i = 1'b 1; + wb_adr_i = addr; + wb_dat_i = 24; + wb_sel_i = 4'b 1111; // complete word + wb_we_i = 1'b 0; // read + $display("Initiated Read transaction..."); + wait_ack(); + end + endtask + + task wait_ack; + // Wait for an ACK + if (wb_cfg_stb_i == 1) begin + @(posedge wb_cfg_ack_o) begin + #2; // To end the transaction on the falling edge of ack + wb_cyc_i = 1'b 0; + wb_cfg_stb_i = 1'b 0; + $display("Monitor: Received an ACK from slave"); + end + end + else begin + @(posedge wb_flash_ack_o) begin + #2; // To end the transaction on the falling edge of ack + wb_cyc_i = 1'b 0; + wb_flash_stb_i = 1'b 0; + $display("Monitor: Received an ACK from slave"); + end + end + endtask + + // spiflash #( + // .FILENAME("flash.hex") + // ) spiflash ( + // .csb(flash_csb), + // .clk(flash_clk), + // .io0(flash_io0), + // .io1(flash_io1), + // .io2(flash_io2), + // .io3(flash_io3) + // ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb/sysctrl_wb/Makefile b/verilog/dv/wb/sysctrl_wb/Makefile new file mode 100644 index 0000000..e1b0978 --- /dev/null +++ b/verilog/dv/wb/sysctrl_wb/Makefile
@@ -0,0 +1,18 @@ +.SUFFIXES: + +PATTERN = sysctrl_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.v b/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.v new file mode 100644 index 0000000..e0ec433 --- /dev/null +++ b/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.v
@@ -0,0 +1,222 @@ + +`timescale 1 ns / 1 ps + +`include "sysctrl.v" + +module sysctrl_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + reg overtemp; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("sysctrl_wb_tb.vcd"); + $dumpvars(0, sysctrl_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test System Control Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // System Control Default Register Addresses + wire [31:0] osc_ena_adr = uut.BASE_ADR | uut.OSC_ENA; + wire [31:0] osc_out_adr = uut.BASE_ADR | uut.OSC_OUT; + wire [31:0] xtal_out_adr = uut.BASE_ADR | uut.XTAL_OUT; + wire [31:0] pll_out_adr = uut.BASE_ADR | uut.PLL_OUT; + wire [31:0] trap_out_adr = uut.BASE_ADR | uut.TRAP_OUT; + wire [31:0] irq7_src_adr = uut.BASE_ADR | uut.IRQ7_SRC; + wire [31:0] irq8_src_adr = uut.BASE_ADR | uut.IRQ8_SRC; + wire [31:0] overtemp_adr = uut.BASE_ADR | uut.OVERTEMP_DATA; + wire [31:0] overtemp_ena_adr = uut.BASE_ADR | uut.OVERTEMP_ENA; + wire [31:0] ovetemp_out_adr = uut.BASE_ADR | uut.OVERTEMP_OUT; + + reg rcosc_ena; + reg [1:0] rcosc_output_dest; + reg [1:0] xtal_output_dest; + reg [1:0] pll_output_dest; + reg [1:0] trap_output_dest; + reg [1:0] irq_7_inputsrc; + reg [1:0] irq_8_inputsrc; + reg overtemp_ena; + reg [1:0] overtemp_dest; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + overtemp = 1'b1; + rcosc_ena = 1'b1; + rcosc_output_dest = 2'b10; + xtal_output_dest = 2'b01; + pll_output_dest = 2'b11; + trap_output_dest = 2'b10; + irq_7_inputsrc = 2'b01; + irq_8_inputsrc = 2'b11; + overtemp_ena = 1'b1; + overtemp_dest = 1'b1; + + // Write to System Control Registers (except overtemp; read-only) + write(osc_ena_adr, rcosc_ena); + write(osc_out_adr, rcosc_output_dest); + write(xtal_out_adr, xtal_output_dest); + write(pll_out_adr, pll_output_dest); + write(trap_out_adr, trap_output_dest); + write(irq7_src_adr, irq_7_inputsrc); + write(irq8_src_adr, irq_8_inputsrc); + write(overtemp_ena_adr, overtemp_ena); + write(ovetemp_out_adr, overtemp_dest); + + #2; + // Read System Control Registers + read(overtemp_adr); + if (wb_dat_o !== overtemp) begin + $display("Error reading from overtemp reg"); + $finish; + end + + read(osc_ena_adr); + if (wb_dat_o !== rcosc_ena) begin + $display("Error reading oscillator enable register."); + $finish; + end + + read(osc_out_adr); + if (wb_dat_o !== rcosc_output_dest) begin + $display("Error reading oscillator output destination register."); + $finish; + end + + read(xtal_out_adr); + if (wb_dat_o !== xtal_output_dest) begin + $display("Error reading XTAL output destination register."); + $finish; + end + + read(pll_out_adr); + if (wb_dat_o !== pll_output_dest) begin + $display("Error reading PLL output destination register."); + $finish; + end + + read(trap_out_adr); + if (wb_dat_o !== trap_output_dest) begin + $display("Error reading trap output destination register."); + $finish; + end + + read(irq7_src_adr); + if (wb_dat_o !== irq_7_inputsrc) begin + $display("Error reading IRQ7 input source register."); + $finish; + end + + read(irq8_src_adr); + if (wb_dat_o !== irq_8_inputsrc) begin + $display("Error reading IRQ7 input source register."); + $finish; + end + + read(overtemp_ena_adr); + if (wb_dat_o !== overtemp_ena) begin + $display("Error reading over-temperature enable register."); + $finish; + end + + read(ovetemp_out_adr); + if (wb_dat_o !== overtemp_dest) begin + $display("Error reading over-temperature output destination register."); + $finish; + end + + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Monitor: Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Monitor: Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Read Cycle Ended."); + end + endtask + + sysctrl_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + .overtemp(overtemp) + ); + +endmodule
diff --git a/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.vcd b/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.vcd new file mode 100644 index 0000000..31cad7c --- /dev/null +++ b/verilog/dv/wb/sysctrl_wb/sysctrl_wb_tb.vcd
@@ -0,0 +1,828 @@ +$date + Fri Aug 21 14:21:19 2020 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module sysctrl_wb_tb $end +$var wire 32 ! irq7_src_adr [31:0] $end +$var wire 32 " irq8_src_adr [31:0] $end +$var wire 32 # osc_ena_adr [31:0] $end +$var wire 32 $ osc_out_adr [31:0] $end +$var wire 32 % overtemp_adr [31:0] $end +$var wire 32 & overtemp_ena_adr [31:0] $end +$var wire 32 ' ovetemp_out_adr [31:0] $end +$var wire 32 ( pll_out_adr [31:0] $end +$var wire 32 ) trap_out_adr [31:0] $end +$var wire 32 * xtal_out_adr [31:0] $end +$var wire 32 + wb_dat_o [31:0] $end +$var wire 1 , wb_ack_o $end +$var reg 2 - irq_7_inputsrc [1:0] $end +$var reg 2 . irq_8_inputsrc [1:0] $end +$var reg 1 / overtemp $end +$var reg 2 0 overtemp_dest [1:0] $end +$var reg 1 1 overtemp_ena $end +$var reg 2 2 pll_output_dest [1:0] $end +$var reg 1 3 rcosc_ena $end +$var reg 2 4 rcosc_output_dest [1:0] $end +$var reg 2 5 trap_output_dest [1:0] $end +$var reg 32 6 wb_adr_i [31:0] $end +$var reg 1 7 wb_clk_i $end +$var reg 1 8 wb_cyc_i $end +$var reg 32 9 wb_dat_i [31:0] $end +$var reg 1 : wb_rst_i $end +$var reg 4 ; wb_sel_i [3:0] $end +$var reg 1 < wb_stb_i $end +$var reg 1 = wb_we_i $end +$var reg 2 > xtal_output_dest [1:0] $end +$scope module uut $end +$var wire 4 ? iomem_we [3:0] $end +$var wire 1 / overtemp $end +$var wire 1 @ resetn $end +$var wire 1 A valid $end +$var wire 1 , wb_ack_o $end +$var wire 32 B wb_adr_i [31:0] $end +$var wire 1 7 wb_clk_i $end +$var wire 1 8 wb_cyc_i $end +$var wire 32 C wb_dat_i [31:0] $end +$var wire 1 : wb_rst_i $end +$var wire 4 D wb_sel_i [3:0] $end +$var wire 1 < wb_stb_i $end +$var wire 1 = wb_we_i $end +$var wire 2 E xtal_output_dest [1:0] $end +$var wire 32 F wb_dat_o [31:0] $end +$var wire 2 G trap_output_dest [1:0] $end +$var wire 1 H ready $end +$var wire 2 I rcosc_output_dest [1:0] $end +$var wire 1 J rcosc_ena $end +$var wire 2 K pll_output_dest [1:0] $end +$var wire 1 L overtemp_ena $end +$var wire 2 M overtemp_dest [1:0] $end +$var wire 2 N irq_8_inputsrc [1:0] $end +$var wire 2 O irq_7_inputsrc [1:0] $end +$scope module sysctrl $end +$var wire 1 7 clk $end +$var wire 32 P iomem_addr [31:0] $end +$var wire 1 A iomem_valid $end +$var wire 32 Q iomem_wdata [31:0] $end +$var wire 4 R iomem_wstrb [3:0] $end +$var wire 1 / overtemp $end +$var wire 1 @ resetn $end +$var wire 1 S xtal_out_sel $end +$var wire 1 T trap_out_sel $end +$var wire 1 U pll_out_sel $end +$var wire 1 V overtemp_sel $end +$var wire 1 W overtemp_ena_sel $end +$var wire 1 X overtemp_dest_sel $end +$var wire 1 Y osc_out_sel $end +$var wire 1 Z osc_ena_sel $end +$var wire 1 [ irq8_sel $end +$var wire 1 \ irq7_sel $end +$var reg 32 ] iomem_rdata [31:0] $end +$var reg 1 H iomem_ready $end +$var reg 2 ^ irq_7_inputsrc [1:0] $end +$var reg 2 _ irq_8_inputsrc [1:0] $end +$var reg 2 ` overtemp_dest [1:0] $end +$var reg 1 L overtemp_ena $end +$var reg 2 a pll_output_dest [1:0] $end +$var reg 1 J rcosc_ena $end +$var reg 2 b rcosc_output_dest [1:0] $end +$var reg 2 c trap_output_dest [1:0] $end +$var reg 2 d xtal_output_dest [1:0] $end +$upscope $end +$upscope $end +$scope task read $end +$var reg 33 e addr [32:0] $end +$upscope $end +$scope task write $end +$var reg 33 f addr [32:0] $end +$var reg 33 g data [32:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +bx g +bx f +bx e +bx d +bx c +bx b +bx a +bx ` +bx _ +bx ^ +bx ] +0\ +0[ +1Z +0Y +0X +0W +0V +0U +0T +0S +b0 R +b0 Q +b0 P +bx O +bx N +bx M +xL +bx K +xJ +bx I +xH +bx G +bx F +bx E +b0 D +b0 C +b0 B +0A +0@ +b0 ? +bx > +0= +0< +b0 ; +1: +b0 9 +08 +07 +b0 6 +bx 5 +bx 4 +x3 +bx 2 +x1 +bx 0 +x/ +bx . +bx - +x, +bx + +b101111000000000000000000001000 * +b101111000000000000000000010000 ) +b101111000000000000000000001100 ( +b101111000000000000000000100100 ' +b101111000000000000000000011100 & +b101111000000000000000000100000 % +b101111000000000000000000000100 $ +b101111000000000000000000000000 # +b101111000000000000000000011000 " +b101111000000000000000000010100 ! +$end +#1000 +0L +b0 M +b0 ` +b0 N +b0 _ +b0 O +b0 ^ +b0 G +b0 c +b0 E +b0 d +b0 K +b0 a +b0 I +b0 b +0J +17 +#2000 +1@ +07 +0: +#3000 +0, +0H +17 +#4000 +07 +b1 g +b101111000000000000000000000000 f +b1 0 +11 +b11 . +b1 - +b10 5 +b11 2 +b1 > +b10 4 +13 +1/ +#5000 +b1111 ? +b1111 R +1A +b1 9 +b1 C +b1 Q +b101111000000000000000000000000 6 +b101111000000000000000000000000 B +b101111000000000000000000000000 P +1= +b1111 ; +b1111 D +18 +1< +17 +#6000 +07 +#7000 +1J +b0 + +b0 F +b0 ] +1, +1H +17 +#8000 +07 +#9000 +0A +b10 g +b101111000000000000000000000100 f +0< +08 +0, +0H +17 +#10000 +07 +#11000 +0Z +1Y +1A +b10 9 +b10 C +b10 Q +b101111000000000000000000000100 6 +b101111000000000000000000000100 B +b101111000000000000000000000100 P +18 +1< +17 +#12000 +07 +#13000 +b10 I +b10 b +1, +1H +17 +#14000 +07 +#15000 +0A +b1 g +b101111000000000000000000001000 f +0< +08 +0, +0H +17 +#16000 +07 +#17000 +0Y +1S +1A +b1 9 +b1 C +b1 Q +b101111000000000000000000001000 6 +b101111000000000000000000001000 B +b101111000000000000000000001000 P +18 +1< +17 +#18000 +07 +#19000 +b1 E +b1 d +1, +1H +17 +#20000 +07 +#21000 +0A +b11 g +b101111000000000000000000001100 f +0< +08 +0, +0H +17 +#22000 +07 +#23000 +1U +0S +1A +b11 9 +b11 C +b11 Q +b101111000000000000000000001100 6 +b101111000000000000000000001100 B +b101111000000000000000000001100 P +18 +1< +17 +#24000 +07 +#25000 +b11 K +b11 a +1, +1H +17 +#26000 +07 +#27000 +0A +b10 g +b101111000000000000000000010000 f +0< +08 +0, +0H +17 +#28000 +07 +#29000 +0U +1T +1A +b10 9 +b10 C +b10 Q +b101111000000000000000000010000 6 +b101111000000000000000000010000 B +b101111000000000000000000010000 P +18 +1< +17 +#30000 +07 +#31000 +b10 G +b10 c +1, +1H +17 +#32000 +07 +#33000 +0A +b1 g +b101111000000000000000000010100 f +0< +08 +0, +0H +17 +#34000 +07 +#35000 +0T +1\ +1A +b1 9 +b1 C +b1 Q +b101111000000000000000000010100 6 +b101111000000000000000000010100 B +b101111000000000000000000010100 P +18 +1< +17 +#36000 +07 +#37000 +b1 O +b1 ^ +1, +1H +17 +#38000 +07 +#39000 +0A +b11 g +b101111000000000000000000011000 f +0< +08 +0, +0H +17 +#40000 +07 +#41000 +0\ +1[ +1A +b11 9 +b11 C +b11 Q +b101111000000000000000000011000 6 +b101111000000000000000000011000 B +b101111000000000000000000011000 P +18 +1< +17 +#42000 +07 +#43000 +b11 N +b11 _ +1, +1H +17 +#44000 +07 +#45000 +0A +b1 g +b101111000000000000000000011100 f +0< +08 +0, +0H +17 +#46000 +07 +#47000 +0[ +1W +1A +b1 9 +b1 C +b1 Q +b101111000000000000000000011100 6 +b101111000000000000000000011100 B +b101111000000000000000000011100 P +18 +1< +17 +#48000 +07 +#49000 +1L +1, +1H +17 +#50000 +07 +#51000 +0A +b101111000000000000000000100100 f +0< +08 +0, +0H +17 +#52000 +07 +#53000 +0W +1X +1A +b101111000000000000000000100100 6 +b101111000000000000000000100100 B +b101111000000000000000000100100 P +18 +1< +17 +#54000 +07 +#55000 +b1 M +b1 ` +1, +1H +17 +#56000 +07 +#57000 +0A +0< +08 +0, +0H +17 +#58000 +07 +#59000 +1V +0X +b0 ? +b0 R +1A +b101111000000000000000000100000 6 +b101111000000000000000000100000 B +b101111000000000000000000100000 P +0= +18 +1< +17 +b101111000000000000000000100000 e +#60000 +07 +#61000 +b1 + +b1 F +b1 ] +1, +1H +17 +#62000 +07 +#63000 +0A +b101111000000000000000000000000 e +0< +08 +0, +0H +17 +#64000 +07 +#65000 +1Z +0V +1A +b101111000000000000000000000000 6 +b101111000000000000000000000000 B +b101111000000000000000000000000 P +18 +1< +17 +#66000 +07 +#67000 +1, +1H +17 +#68000 +07 +#69000 +0A +b101111000000000000000000000100 e +0< +08 +0, +0H +17 +#70000 +07 +#71000 +0Z +1Y +1A +b101111000000000000000000000100 6 +b101111000000000000000000000100 B +b101111000000000000000000000100 P +18 +1< +17 +#72000 +07 +#73000 +b10 + +b10 F +b10 ] +1, +1H +17 +#74000 +07 +#75000 +0A +b101111000000000000000000001000 e +0< +08 +0, +0H +17 +#76000 +07 +#77000 +0Y +1S +1A +b101111000000000000000000001000 6 +b101111000000000000000000001000 B +b101111000000000000000000001000 P +18 +1< +17 +#78000 +07 +#79000 +b1 + +b1 F +b1 ] +1, +1H +17 +#80000 +07 +#81000 +0A +b101111000000000000000000001100 e +0< +08 +0, +0H +17 +#82000 +07 +#83000 +1U +0S +1A +b101111000000000000000000001100 6 +b101111000000000000000000001100 B +b101111000000000000000000001100 P +18 +1< +17 +#84000 +07 +#85000 +b11 + +b11 F +b11 ] +1, +1H +17 +#86000 +07 +#87000 +0A +b101111000000000000000000010000 e +0< +08 +0, +0H +17 +#88000 +07 +#89000 +0U +1T +1A +b101111000000000000000000010000 6 +b101111000000000000000000010000 B +b101111000000000000000000010000 P +18 +1< +17 +#90000 +07 +#91000 +b10 + +b10 F +b10 ] +1, +1H +17 +#92000 +07 +#93000 +0A +b101111000000000000000000010100 e +0< +08 +0, +0H +17 +#94000 +07 +#95000 +0T +1\ +1A +b101111000000000000000000010100 6 +b101111000000000000000000010100 B +b101111000000000000000000010100 P +18 +1< +17 +#96000 +07 +#97000 +b1 + +b1 F +b1 ] +1, +1H +17 +#98000 +07 +#99000 +0A +b101111000000000000000000011000 e +0< +08 +0, +0H +17 +#100000 +07 +#101000 +0\ +1[ +1A +b101111000000000000000000011000 6 +b101111000000000000000000011000 B +b101111000000000000000000011000 P +18 +1< +17 +#102000 +07 +#103000 +b11 + +b11 F +b11 ] +1, +1H +17 +#104000 +07 +#105000 +0A +b101111000000000000000000011100 e +0< +08 +0, +0H +17 +#106000 +07 +#107000 +0[ +1W +1A +b101111000000000000000000011100 6 +b101111000000000000000000011100 B +b101111000000000000000000011100 P +18 +1< +17 +#108000 +07 +#109000 +b1 + +b1 F +b1 ] +1, +1H +17 +#110000 +07 +#111000 +0A +b101111000000000000000000100100 e +0< +08 +0, +0H +17 +#112000 +07 +#113000 +0W +1X +1A +b101111000000000000000000100100 6 +b101111000000000000000000100100 B +b101111000000000000000000100100 P +18 +1< +17 +#114000 +07 +#115000 +1, +1H +17 +#116000 +07 +#117000 +0A +0< +08 +0, +0H +17
diff --git a/verilog/dv/wb/uart_wb/Makefile b/verilog/dv/wb/uart_wb/Makefile new file mode 100644 index 0000000..a37bd82 --- /dev/null +++ b/verilog/dv/wb/uart_wb/Makefile
@@ -0,0 +1,17 @@ +.SUFFIXES: + +PATTERN = uart_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb/uart_wb/uart_wb_tb.v b/verilog/dv/wb/uart_wb/uart_wb_tb.v new file mode 100644 index 0000000..6063060 --- /dev/null +++ b/verilog/dv/wb/uart_wb/uart_wb_tb.v
@@ -0,0 +1,149 @@ + + +`timescale 1 ns / 1 ps + +`include "simpleuart.v" + +module uart_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_we_i = 0; + wb_cyc_i = 0; + wb_adr_i = 0; + wb_dat_i = 0; + wb_sel_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("uart_wb_tb.vcd"); + $dumpvars(0, uart_wb_tb); + repeat (500) begin + repeat (10000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display("Monitor: Timeout, Test UART Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + wire [31:0] div_reg_addr = uut.BASE_ADR | uut.CLK_DIV; + wire [31:0] div_reg_data = 32'h FFFF_FFFF; + + wire [31:0] dat_reg_addr = uut.BASE_ADR | uut.DATA; + wire [31:0] dat_reg_data = 32'h FFFF_FFFF; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to div register + write(div_reg_addr, div_reg_data); + #2; + read(div_reg_addr); + if (wb_dat_o !== div_reg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", div_reg_data, wb_dat_o); + $display("Monitor: Wishbone UART Failed"); + $display("%c[0m",27); + $finish; + end + #6; + + // Write Operation: writes to data register + write(dat_reg_addr, dat_reg_data); + #2; + read(dat_reg_addr); + if (wb_dat_o !== dat_reg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", dat_reg_data, wb_dat_o); + $display("Monitor: Wishbone UART Failed"); + $display("%c[0m",27); + $finish; + end + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + #2; + wb_we_i = 0; + // Wait for an ACK + wait(wb_ack_o == 1); + #2; + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + #2; + // wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + simpleuart_wb uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + .ser_tx(tbuart_rx), + .ser_rx(ser_rx) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/ip/arbiter.v b/verilog/ip/arbiter.v new file mode 100644 index 0000000..f599173 --- /dev/null +++ b/verilog/ip/arbiter.v
@@ -0,0 +1,135 @@ +module wb_arbiter #( + parameter AW = 32, + parameter DW = 32, + parameter NM = 2 +)( + + input wb_clk_i, + input wb_rst_i, + + // Masters Interface + input [NM-1:0] wbm_stb_i, + input [NM-1:0] wbm_cyc_i, + input [NM-1:0] wbm_we_i, + input [NM*(DW/8)-1:0] wbm_sel_i, + input [NM*DW-1:0] wbm_dat_i, + input [NM*AW-1:0] wbm_adr_i, + + output [NM-1:0] wbm_ack_o, + output [NM-1:0] wbm_err_o, + output [NM*DW-1:0] wbm_dat_o, + + // Slave Interface + input wbs_ack_i, + input wbs_err_i, + input [DW-1:0] wbs_dat_i, + output reg wbs_stb_o, + output reg wbs_cyc_o, + output wbs_we_o, + output reg [(DW/8)-1:0] wbs_sel_o, + output reg [AW-1:0] wbs_adr_o, + output reg [DW-1:0] wbs_dat_o +); + +localparam SEL = DW / 8; + +// Current elected master (one hot) +reg [NM-1:0] cur_master; +reg capture_req; + +wire [NM-1:0] master_sel; +wire [NM-1:0] requests; +wire any_req; +wire any_acks; + +assign requests = wbm_cyc_i & wbm_stb_i; +assign any_req = |requests; +assign any_ack = |{wbs_ack_i, wbs_err_i}; + +genvar iM; +generate + assign master_sel[0] = requests[0]; + for (iM=1; iM<NM; iM=iM+1) begin + assign master_sel[iM] = requests[iM] & (~master_sel[iM-1]); + end +endgenerate + +// Current-elected master +always @(posedge wb_clk_i) + if(wb_rst_i) begin + cur_master <= {NM{1'b0}}; + end else if (capture_req) begin + cur_master <= master_sel; + end + +// Finite State Machine +localparam IDLE = 1'b0; +localparam BUSY = 1'b1; + +reg state = IDLE; +reg next_state; + +always @(*) +begin: FSM_COMB +case (state) + IDLE: if (any_req) begin + wbs_stb_o = 1'b1; + wbs_cyc_o = 1'b1; + capture_req = 1'b1; + next_state = BUSY; + end else begin + wbs_stb_o = 1'b0; + wbs_cyc_o = 1'b0; + capture_req = 1'b0; + next_state = IDLE; + end + BUSY: begin + if (any_ack & !any_req) begin + next_state = IDLE; + end if (any_ack & any_req) begin + capture_req = 1'b1; + end + end + default: next_state = IDLE; +endcase +end + +always @(posedge wb_clk_i) + if (wb_rst_i) + state <= IDLE; + else + state <= next_state; + +// Masters Output Assignment +assign wbm_dat_o = {NM{wbs_dat_i}}; +assign wbm_ack_o = {NM{wbs_ack_i}} & cur_master; +assign wbm_err_o = {NM{wbs_err_i}} & cur_master; + +// Multiplexed signal to the slave + +assign wbs_we_o = |(cur_master & wbm_we_i); + +integer k; +always @(*) begin + wbs_sel_o = {SEL{1'b0}}; + for (k=0; k<(NM*SEL); k=k+1) + wbs_sel_o[k%SEL] = wbs_sel_o[k%SEL] | (cur_master[k/SEL] & wbm_sel_i[k]); +end + +integer l; +always @(*) begin + wbs_adr_o = {AW{1'b0}}; + for (l=0; l<(NM*AW); l=l+1) + wbs_adr_o[l%AW] = wbs_adr_o[l%AW] | (cur_master[l/AW] & wbm_adr_i[l]); +end + +integer o; +always @(*) begin + wbs_dat_o = {DW{1'b0}}; + for (o=0; o<(NM*DW); o=o+1) + wbs_dat_o[o%DW] = wbs_dat_o[o%DW] | (cur_master[o/DW] & wbm_dat_i[o]); +end + + +endmodule +
diff --git a/verilog/ip/crossbar.v b/verilog/ip/crossbar.v new file mode 100644 index 0000000..ee07d5e --- /dev/null +++ b/verilog/ip/crossbar.v
@@ -0,0 +1,172 @@ + +`include "distributor.v" +`include "arbiter.v" + +module wb_xbar #( + parameter NM = 2, + parameter NS = 4, + parameter AW = 32, + parameter DW = 32 +) ( + + input wb_clk_i, + input wb_rst_i, + + // Masters interface + input [NM-1:0] wbm_cyc_i, + input [NM-1:0] wbm_stb_i, + input [NM-1:0] wbm_we_i, + input [(NM*(DW/8))-1:0] wbm_sel_i, + input [(NM*AW)-1:0] wbm_adr_i, + input [(NM*DW)-1:0] wbm_dat_i, + output [NM-1:0] wbm_ack_o, + output [NM-1:0] wbm_err_o, + output [(NM*DW)-1:0] wbm_dat_o, + + // Slaves interfaces + input [NS-1:0] wbs_ack_i, + input [(NS*DW)-1:0] wbs_dat_i, + output [NS-1:0] wbs_cyc_o, + output [NS-1:0] wbs_stb_o, + output [NS-1:0] wbs_we_o, + output [(NS*(DW/8))-1:0] wbs_sel_o, + output [(NS*AW)-1:0] wbs_adr_o, + output [(NS*DW)-1:0] wbs_dat_o +); + parameter ADR_MASK = { + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}} + }; + + parameter SLAVE_ADR = { + {8'hB0, {24{1'b0}}}, + {8'hA0, {24{1'b0}}}, + {8'h90, {24{1'b0}}}, + {8'h80, {24{1'b0}}} + }; + + localparam SEL = DW / 8; + + wire [(NM*NS)-1:0] distributor_cyc_o; + wire [(NM*NS)-1:0] distributor_stb_o; + wire [(NM*NS)-1:0] distributor_we_o; + wire [(NM*NS*SEL)-1:0] distributor_sel_o; + wire [(NM*NS*AW)-1:0] distributor_adr_o; + wire [(NM*NS*DW)-1:0] distributor_dat_o; + wire [(NM*NS)-1:0] distributor_ack_i; + wire [(NM*NS)-1:0] distributor_err_i; + wire [(NM*NS)-1:0] distributor_rty_i; + wire [(NM*NS*DW)-1:0] distributor_dat_i; + + //Arbiter busses: + wire [(NM*NS)-1:0] arbiter_cyc_i; + wire [(NM*NS)-1:0] arbiter_stb_i; + wire [(NM*NS)-1:0] arbiter_we_i; + wire [(NM*NS*SEL)-1:0] arbiter_sel_i; + wire [(NM*NS*AW)-1:0] arbiter_adr_i; + wire [(NM*NS*DW)-1:0] arbiter_dat_i; + wire [(NM*NS)-1:0] arbiter_ack_o; + wire [(NM*NS)-1:0] arbiter_err_o; + wire [(NM*NS*DW)-1:0] arbiter_dat_o; + + //Instantiate distributors + generate + genvar i; + for (i=0; i<NM; i=i+1) + begin + distributor #( + .NS(NS), + .AW(AW), + .DW(DW), + .SLAVE_ADR(SLAVE_ADR), + .ADR_MASK(ADR_MASK) + ) distributor ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wbm_cyc_i(wbm_cyc_i[i]), + .wbm_stb_i(wbm_stb_i[i]), + .wbm_we_i(wbm_we_i[i]), + .wbm_sel_i(wbm_sel_i[(SEL*(i+1))-1:(SEL*i)]), + .wbm_adr_i(wbm_adr_i[(AW*(i+1))-1:(AW*i)]), + .wbm_dat_i(wbm_dat_i[(DW*(i+1))-1:(DW*i)]), + .wbm_ack_o(wbm_ack_o[i]), + .wbm_dat_o(wbm_dat_o[(DW*(i+1))-1:(DW*i)]), + + // Slave interfaces + .wbs_cyc_o (distributor_cyc_o[(NS*(i+1))-1:NS*i]), + .wbs_stb_o (distributor_stb_o[(NS*(i+1))-1:NS*i]), + .wbs_we_o (distributor_we_o [(NS*(i+1))-1:NS*i]), + .wbs_sel_o (distributor_sel_o[(NS*SEL*(i+1))-1:NS*SEL*i]), + .wbs_adr_o (distributor_adr_o[(NS*AW*(i+1))-1:NS*AW*i]), + .wbs_dat_o (distributor_dat_o[(NS*DW*(i+1))-1:NS*DW*i]), + .wbs_ack_i (distributor_ack_i[(NS*(i+1))-1:NS*i]), + .wbs_dat_i (distributor_dat_i[(NS*DW*(i+1))-1:NS*DW*i]) + ); + end + endgenerate + + //Instantiate arbiters + generate + genvar j; + for (j=0; j<NS; j=j+1) + begin + wb_arbiter #( + .NM(NM), + .AW(AW), + .DW(DW) + ) arbiter ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + // Masters Interface + .wbm_cyc_i (arbiter_cyc_i[(NM*(j+1))-1:NM*j]), + .wbm_stb_i (arbiter_stb_i[(NM*(j+1))-1:NM*j]), + .wbm_we_i (arbiter_we_i [(NM*(j+1))-1:NM*j]), + .wbm_sel_i (arbiter_sel_i[(NM*SEL*(j+1))-1:NM*SEL*j]), + .wbm_adr_i (arbiter_adr_i[(NM*AW*(j+1))-1:NM*AW*j]), + .wbm_dat_i (arbiter_dat_i[(NM*DW*(j+1))-1:NM*DW*j]), + .wbm_ack_o (arbiter_ack_o[(NM*(j+1))-1:NM*j]), + .wbm_dat_o (arbiter_dat_o[(NM*DW*(j+1))-1:NM*DW*j]), + + // Slave interfaces + .wbs_cyc_o (wbs_cyc_o[j]), + .wbs_stb_o (wbs_stb_o[j]), + .wbs_we_o (wbs_we_o[j]), + .wbs_sel_o (wbs_sel_o[(SEL*(j+1))-1:(SEL*j)]), + .wbs_adr_o (wbs_adr_o[(AW*(j+1))-1:(AW*j)]), + .wbs_dat_o (wbs_dat_o[(DW*(j+1))-1:(DW*j)]), + .wbs_ack_i (wbs_ack_i[j]), + .wbs_dat_i (wbs_dat_i[(DW*(j+1))-1:(DW*j)]) + ); + end + endgenerate + + //Crossbar connections + generate + genvar k, l, m, indx; + for (k=0; k<NM; k=k+1) + for (l=0; l<NS; l=l+1) + begin + assign arbiter_cyc_i[(NM*l)+k] = distributor_cyc_o[(NS*k)+l]; + assign arbiter_stb_i[(NM*l)+k] = distributor_stb_o[(NS*k)+l]; + assign arbiter_we_i [(NM*l)+k] = distributor_we_o [(NS*k)+l]; + + assign arbiter_sel_i[(((NM*l)+k)*SEL)+(SEL-1):((NM*l)+k)*SEL] = + distributor_sel_o[(((NS*k)+l)*SEL)+(SEL-1):((NS*k)+l)*SEL]; + + assign arbiter_adr_i[(((NM*l)+k)*AW)+(AW-1) : ((NM*l)+k)*AW] = + distributor_adr_o[(((NS*k)+l)*AW)+(AW-1) : ((NS*k)+l)*AW]; + + assign arbiter_dat_i[(((NM*l)+k)*AW)+(AW-1) : ((NM*l)+k)*AW] = + distributor_dat_o[(((NS*k)+l)*AW)+(AW-1) : ((NS*k)+l)*AW]; + + assign distributor_dat_i[(((NS*k)+l)*DW)+(DW-1) : ((NS*k)+l)*DW] = + arbiter_dat_o[(((NM*l)+k)*DW)+(DW-1) : ((NM*l)+k)*DW]; + + assign distributor_ack_i[(NS*k)+l] = arbiter_ack_o[(NM*l)+k]; + end + endgenerate + +endmodule \ No newline at end of file
diff --git a/verilog/ip/distributor.v b/verilog/ip/distributor.v new file mode 100644 index 0000000..78aa374 --- /dev/null +++ b/verilog/ip/distributor.v
@@ -0,0 +1,77 @@ +module distributor #( + parameter AW = 32, + parameter DW = 32, + parameter NS = 4 +) ( + input wb_clk_i, + input wb_rst_i, + + // Master Interface + input wbm_cyc_i, + input wbm_stb_i, + input wbm_we_i, + input [(DW/8)-1:0] wbm_sel_i, + input [AW-1:0] wbm_adr_i, + input [DW-1:0] wbm_dat_i, + output wbm_ack_o, + output reg [DW-1:0] wbm_dat_o, + + // Slave interfaces + input [NS-1:0] wbs_ack_i, + input [(NS*DW)-1:0] wbs_dat_i, + + output [NS-1:0] wbs_cyc_o, + output [NS-1:0] wbs_stb_o, + output [NS-1:0] wbs_we_o, + output [(NS*(DW/8))-1:0] wbs_sel_o, + output [(NS*AW)-1:0] wbs_adr_o, + output [(NS*DW)-1:0] wbs_dat_o + +); + +parameter ADR_MASK = { + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}}, + {8'hFF, {24{1'b0}}} +}; + +parameter SLAVE_ADR = { + {8'hB0, {24{1'b0}}}, + {8'hA0, {24{1'b0}}}, + {8'h90, {24{1'b0}}}, + {8'h80, {24{1'b0}}} +}; + +wire [NS-1:0] slave_sel; + +// Decode Addresseses, then accordingly assign the slave signals +genvar iS; +generate + for (iS = 0; iS < NS; iS = iS + 1) begin + assign slave_sel[iS] = ((wbm_adr_i & ADR_MASK[(iS+1)*AW-1:iS*AW]) == SLAVE_ADR[(iS+1)*AW-1:iS*AW]); + end +endgenerate + +// Plain signal propagation to all target busses +assign wbs_we_o = {NS{wbm_we_i}}; //write enables +assign wbs_sel_o = {NS{wbm_sel_i}}; //write data selects +assign wbs_adr_o = {NS{wbm_adr_i}}; //address busses +assign wbs_dat_o = {NS{wbm_dat_i}}; //write data busses + +// Masked signal propagation to all target busses +assign wbs_cyc_o = slave_sel & {NS{wbm_cyc_i}}; // bus cycle indicators +assign wbs_stb_o = slave_sel & {NS{wbm_cyc_i}}; // access requests + +// Multiplexed signal propagation to the initiator bus +assign wbm_ack_o = |{slave_sel & wbs_ack_i}; + +integer i; +always @* + begin + wbm_dat_o = {DW{1'b0}}; + for (i=0; i<(DW*NS); i=i+1) + wbm_dat_o[i%DW] = wbm_dat_o[i%DW] | (slave_sel[i/DW] & wbs_dat_i[i]); + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v deleted file mode 100644 index bbe24ce..0000000 --- a/verilog/rtl/caravel.v +++ /dev/null
@@ -1,919 +0,0 @@ -/*------------------------------------------------------*/ -/* caravel, a standard container for user projects on */ -/* the Google/SkyWater/efabless shuttle runs for the */ -/* SkyWater sky130 130nm process. */ -/* */ -/* Copyright 2020 efabless, Inc. */ -/* Written by Tim Edwards, August 2020 */ -/* This file is open source hardware released under the */ -/* Apache 2.0 license. See file LICENSE. */ -/* */ -/*------------------------------------------------------*/ - -`timescale 1 ns / 1 ps - -/* Always define USE_PG_PIN (used by SkyWater cells) */ -/* But do not define SC_USE_PG_PIN */ -`define USE_PG_PIN - -/* Must define functional for now because otherwise the timing delays */ -/* are assumed, but they have been stripped out because some are not */ -/* parsed by iverilog. */ - -`define functional - -// Define GL to use the gate-level netlists -//`define GL - -// PDK IP - -// I/O padframe cells - -// Local IP -`include "striVe.v" - -//`define TOP_ROUTING - -`ifndef TOP_ROUTING - `define ABUTMENT_PINS \ - .amuxbus_a(analog_a),\ - .amuxbus_b(analog_b),\ - .vssa(vss),\ - .vdda(vdd3v3),\ - .vswitch(vdd3v3),\ - .vddio_q(vddio_q),\ - .vcchib(vdd1v8),\ - .vddio(vdd3v3),\ - .vccd(vdd1v8),\ - .vssio(vss),\ - .vssd(vss),\ - .vssio_q(vssio_q), -`else - `define ABUTMENT_PINS -`endif - -module caravel (vdd3v3, vdd1v8, vss, gpio, cclk, ser_rx, ser_tx, irq, - RSTB, SDO, SDI, CSB, SCK, - flash_csb, flash_clk, flash_io0, flash_io1, flash_io2, flash_io3); - inout vdd3v3; - inout vdd1v8; - inout vss; - inout [15:0] gpio; - input cclk; // CMOS clock input - input ser_rx; - output ser_tx; - input irq; - input RSTB; // NOTE: Replaces analog_out pin from raven chip - output SDO; - input SDI; - input CSB; - input SCK; - output flash_csb; - output flash_clk; - output flash_io0; - output flash_io1; - output flash_io2; - output flash_io3; - - wire [15:0] gpio_out_core; - wire [15:0] gpio_in_core; - wire [15:0] gpio_mode0_core; - wire [15:0] gpio_mode1_core; - wire [15:0] gpio_outenb_core; - wire [15:0] gpio_inenb_core; - - wire analog_a, analog_b; /* Placeholders for analog signals */ - - wire porb_h; - wire porb_l; - wire por_h; - wire por; - wire SCK_core; - wire SDI_core; - wire CSB_core; - wire SDO_core; - wire SDO_enb; - wire spi_ro_reg_ena_core; - wire spi_ro_pll_dco_ena_core; - wire [2:0] spi_ro_pll_sel_core; - wire [4:0] spi_ro_pll_div_core; - wire [25:0] spi_ro_pll_trim_core; - wire irq_spi_core; - wire ext_reset_core; - wire trap_core; - wire [11:0] spi_ro_mfgr_id_core; - wire [7:0] spi_ro_prod_id_core; - wire [3:0] spi_ro_mask_rev_core; - - // Instantiate power cells for VDD3V3 domain (8 total; 4 high clamps and - // 4 low clamps) - s8iom0_vdda_hvc_pad vdd3v3hclamp [1:0] ( - `ABUTMENT_PINS - .drn_hvc(), - .src_bdy_hvc() - ); - - s8iom0_vddio_hvc_pad vddiohclamp [1:0] ( - `ABUTMENT_PINS - .drn_hvc(), - .src_bdy_hvc() - ); - - - s8iom0_vdda_lvc_pad vdd3v3lclamp [3:0] ( - `ABUTMENT_PINS - .bdy2_b2b(), - .drn_lvc1(), - .drn_lvc2(), - .src_bdy_lvc1(), - .src_bdy_lvc2() - ); - - // Instantiate the core voltage supply (since it is not generated on-chip) - // (1.8V) (4 total, 2 high and 2 low clamps) - - s8iom0_vccd_hvc_pad vdd1v8hclamp [1:0] ( - `ABUTMENT_PINS - .drn_hvc(), - .src_bdy_hvc() - ); - - s8iom0_vccd_lvc_pad vdd1v8lclamp [1:0] ( - `ABUTMENT_PINS - .bdy2_b2b(), - .drn_lvc1(), - .drn_lvc2(), - .src_bdy_lvc1(), - .src_bdy_lvc2() - ); - - // Instantiate ground cells (7 total, 4 high clamps and 3 low clamps) - - s8iom0_vssa_hvc_pad vsshclamp [3:0] ( - `ABUTMENT_PINS - .drn_hvc(), - .src_bdy_hvc() - ); - - s8iom0_vssa_lvc_pad vssalclamp ( - `ABUTMENT_PINS - .bdy2_b2b(), - .drn_lvc1(), - .drn_lvc2(), - .src_bdy_lvc1(), - .src_bdy_lvc2() - ); - - s8iom0_vssd_lvc_pad vssdlclamp ( - `ABUTMENT_PINS - .bdy2_b2b(), - .drn_lvc1(), - .drn_lvc2(), - .src_bdy_lvc1(), - .src_bdy_lvc2() - ); - - s8iom0_vssio_lvc_pad vssiolclamp ( - `ABUTMENT_PINS - .bdy2_b2b(), - .drn_lvc1(), - .drn_lvc2(), - .src_bdy_lvc1(), - .src_bdy_lvc2() - ); - - - - // Instantiate GPIO v2 cell. These are used for both digital and analog - // functions, configured appropriately. - // - // GPIO pin description: - // - // general: signals with _h suffix are in the vddio (3.3V) domain. All - // other signals are in 1.8V domains (vccd or vcchib) - - // out = Signal from core to pad (digital, 1.8V domain) - // oe_n = Output buffer enable (sense inverted) - // hld_h_n = Hold signals during deep sleep (sense inverted) - // enable_h = Power-on-reset (inverted) - // enable_inp_h = Defines state of input buffer output when disabled. - // Connect via loopback to tie_hi_esd or tie_lo_esd. - // enable_vdda_h = Power-on-reset (inverted) to analog section - // enable_vswitch_h = set to 0 if not using vswitch - // enable_vddio = set to 1 if vddio is up during deep sleep - // inp_dis = Disable input buffer - // ib_mode_sel = Input buffer mode select, 0 for 3.3V external signals, 1 for - // 1.8V external signals - // vtrip_se = Input buffer trip select, 0 for CMOS level, 1 for TTL level - // slow = 0 for fast slew, 1 for slow slew - // hld_ovr = override for pads that need to be enabled during deep sleep - // analog_en = enable analog functions - // analog_sel = select analog channel a or b - // analog_pol = analog select polarity - // dm = digital mode (3 bits) 000 = analog 001 = input only, 110 = output only - // vddio = Main 3.3V supply - // vddio_q = Quiet 3.3V supply - // vdda = Analog 3.3V supply - // vccd = Digital 1.8V supply - // vswitch = High-voltage supply for analog switches - // vcchib = Digital 1.8V supply live during deep sleep mode - // vssa = Analog ground - // vssd = Digital ground - // vssio_q = Quiet main ground - // vssio = Main ground - // pad = Signal on pad - // pad_a_noesd_h = Direct core connection to pad - // pad_a_esd_0_h = Core connection to pad through 150 ohms (primary) - // pad_a_esd_1_h = Core connection to pad through 150 ohms (secondary) - // amuxbus_a = Analog bus A - // amuxbus_b = Analog bus B - // in = Signal from pad to core (digital, 1.8V domain) - // in_h = Signal from pad to core (3.3V domain) - // tie_hi_esd = 3.3V output for loopback to enable_inp_h - // tie_lo_esd = ground output for loopback to enable_inp_h - - // 37 instances: 16 general purpose digital, 2 for the crystal oscillator, - // 4 for the ADC, 1 for the analog out, 2 for the comparator inputs, - // one for the IRQ input, one for the xclk input, 6 for the SPI flash - // signals, and 4 for the housekeeping SPI signals. - - // NOTE: To pass a vector to array dm in an array of instances gpio_pad, - // the array needs to be rearranged. Reconstruct the needed 48-bit vector - // (3 bit signal * 16 instances). - // - // Also note: Preferable to use a generate block, but that is incompatible - // with the current version of padframe_generator. . . - - wire [47:0] dm_all; - - assign dm_all = {gpio_mode1_core[15], gpio_mode1_core[15], gpio_mode0_core[15], - gpio_mode1_core[14], gpio_mode1_core[14], gpio_mode0_core[14], - gpio_mode1_core[13], gpio_mode1_core[13], gpio_mode0_core[13], - gpio_mode1_core[12], gpio_mode1_core[12], gpio_mode0_core[12], - gpio_mode1_core[11], gpio_mode1_core[11], gpio_mode0_core[11], - gpio_mode1_core[10], gpio_mode1_core[10], gpio_mode0_core[10], - gpio_mode1_core[9], gpio_mode1_core[9], gpio_mode0_core[9], - gpio_mode1_core[8], gpio_mode1_core[8], gpio_mode0_core[8], - gpio_mode1_core[7], gpio_mode1_core[7], gpio_mode0_core[7], - gpio_mode1_core[6], gpio_mode1_core[6], gpio_mode0_core[6], - gpio_mode1_core[5], gpio_mode1_core[5], gpio_mode0_core[5], - gpio_mode1_core[4], gpio_mode1_core[4], gpio_mode0_core[4], - gpio_mode1_core[3], gpio_mode1_core[3], gpio_mode0_core[3], - gpio_mode1_core[2], gpio_mode1_core[2], gpio_mode0_core[2], - gpio_mode1_core[1], gpio_mode1_core[1], gpio_mode0_core[1], - gpio_mode1_core[0], gpio_mode1_core[0], gpio_mode0_core[0]}; - - // GPIO pads (user space) - s8iom0_gpiov2_pad gpio_pad [31:0] ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(gpio), -`endif - .out(gpio_out_core), // Signal from core to pad - .oe_n(gpio_outenb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold signals during deep sleep (sense inverted) - .enable_h(porb_h), // Post-reset enable - .enable_inp_h(loopb0), // Input buffer state when disabled - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(gpio_inenb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm(dm_all), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(gpio_in_core), // Signal from pad to core - .in_h(), // VDDA domain signal (unused) - .tie_hi_esd(), - .tie_lo_esd(loopb0) - ); - - s8iom0_gpiov2_pad cclk_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(cclk), -`endif - .out(), // Signal from core to pad - .oe_n(vdd1v8), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb1), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(por), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vss, vss, vdd1v8}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(cclk_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb1) - ); - - // NOTE: The analog_out pad from the raven chip has been replaced by - // the digital reset input RSTB on striVe due to the lack of an on-board - // power-on-reset circuit. The XRES pad is used for providing a glitch- - // free reset. - - s8iom0s8_top_xres4v2 RSTB_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(RSTB), -`endif - .tie_weak_hi_h(xresloop), // Loop-back connection to pad through pad_a_esd_h - .tie_hi_esd(), - .tie_lo_esd(), - .pad_a_esd_h(xresloop), - .xres_h_n(porb_h), - .disable_pullup_h(vss), // 0 = enable pull-up on reset pad - .enable_h(vdd), // Power-on-reset to the power-on-reset input?? - .en_vddio_sig_h(vss), // No idea. - .inp_sel_h(vss), // 1 = use filt_in_h else filter the pad input - .filt_in_h(vss), // Alternate input for glitch filter - .pullup_h(vss), // Pullup connection for alternate filter input - .enable_vddio(vdd1v8) - ); - - s8iom0_gpiov2_pad irq_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(irq), -`endif - .out(vss), // Signal from core to pad - .oe_n(vdd1v8), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb10), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(por), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vss, vss, vdd1v8}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(irq_pin_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb10) - ); - - s8iom0_gpiov2_pad SDO_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(SDO), -`endif - .out(SDO_core), // Signal from core to pad - .oe_n(SDO_enb), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb11), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(vdd1v8), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb11) - ); - - s8iom0_gpiov2_pad SDI_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(SDI), -`endif - .out(vss), // Signal from core to pad - .oe_n(vdd1v8), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb12), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(por), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vss, vss, vdd1v8}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(SDI_core), // Signal from pad to core - .in_h(SDI_core_h), - .tie_hi_esd(), - .tie_lo_esd() - ); - - s8iom0_gpiov2_pad CSB_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(CSB), -`endif - .out(vss), // Signal from core to pad - .oe_n(vdd1v8), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb13), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(por), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vss, vss, vdd1v8}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(CSB_core), // Signal from pad to core - .in_h(CSB_core_h), - .tie_hi_esd(), - .tie_lo_esd(loopb13) - ); - - s8iom0_gpiov2_pad SCK_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(SCK), -`endif - .out(vss), // Signal from core to pad - .oe_n(vdd1v8), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb14), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(por), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vss, vss, vdd1v8}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(SCK_core), // Signal from pad to core - .in_h(SCK_core_h), // Signal in vdda domain (3.3V) - .tie_hi_esd(), - .tie_lo_esd(loopb14) - ); - - s8iom0_gpiov2_pad flash_csb_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_csb), -`endif - .out(flash_csb_core), // Signal from core to pad - .oe_n(flash_csb_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb16), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_csb_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd() - ); - - s8iom0_gpiov2_pad flash_clk_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_clk), -`endif - .out(flash_clk_core), // Signal from core to pad - .oe_n(flash_clk_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb17), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_clk_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd() - ); - - s8iom0_gpiov2_pad flash_io0_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_io0), -`endif - .out(flash_io0_do_core), // Signal from core to pad - .oe_n(flash_io0_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb18), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_io0_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(flash_io0_di_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb18) - ); - - s8iom0_gpiov2_pad flash_io1_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_io1), -`endif - .out(flash_io1_do_core), // Signal from core to pad - .oe_n(flash_io1_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb19), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_io1_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(flash_io1_di_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb19) - ); - - s8iom0_gpiov2_pad flash_io2_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_io2), -`endif - .out(flash_io2_do_core), // Signal from core to pad - .oe_n(flash_io2_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb20), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_io2_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({flash_io2_ieb_core, flash_io2_ieb_core, flash_io2_oeb_core}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(flash_io2_di_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb20) - ); - - s8iom0_gpiov2_pad flash_io3_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(flash_io3), -`endif - .out(flash_io3_do_core), // Signal from core to pad - .oe_n(flash_io3_oeb_core), // Output enable (sense inverted) - .hld_h_n(vdd), // Hold - .enable_h(porb_h), // Enable - .enable_inp_h(loopb21), // Enable input buffer - .enable_vdda_h(porb_h), // - .enable_vswitch_h(vss), // - .enable_vddio(vdd1v8), // - .inp_dis(flash_io3_ieb_core), // Disable input buffer - .ib_mode_sel(vss), // - .vtrip_sel(vss), // - .slow(vss), // - .hld_ovr(vss), // - .analog_en(vss), // - .analog_sel(vss), // - .analog_pol(vss), // - .dm({flash_io3_ieb_core, flash_io3_ieb_core, flash_io3_oeb_core}), // (3 bits) Mode control - .pad_a_noesd_h(), // Direct pad connection - .pad_a_esd_0_h(), // Pad connection through 150 ohms - .pad_a_esd_1_h(), // Pad connection through 150 ohms - .in(flash_io3_di_core), // Signal from pad to core - .in_h(), - .tie_hi_esd(), - .tie_lo_esd(loopb21) - ); - - // Instantiate GPIO overvoltage (I2C) compliant cell - // (Use this for ser_rx and ser_tx; no reason other than testing - // the use of the cell.) (Might be worth adding in the I2C IP from - // ravenna just to test on a proper I2C channel.) - - s8iom0s8_top_gpio_ovtv2 ser_rx_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(ser_rx), -`endif - .out(vss), - .oe_n(vdd1v8), - .hld_h_n(vdd), - .enable_h(porb_h), - .enable_inp_h(loopb22), - .enable_vdda_h(porb_h), - .enable_vddio(vdd1v8), - .enable_vswitch_h(vss), - .inp_dis(por), - .vtrip_sel(vss), - .hys_trim(vdd1v8), - .slow(vss), - .slew_ctl({vss, vss}), // 2 bits - .hld_ovr(vss), - .analog_en(vss), - .analog_sel(vss), - .analog_pol(vss), - .dm({vss, vss, vdd1v8}), // 3 bits - .ib_mode_sel({vss, vss}), // 2 bits - .vinref(vdd1v8), - .pad_a_noesd_h(), - .pad_a_esd_0_h(), - .pad_a_esd_1_h(), - .in(ser_rx_core), - .in_h(), - .tie_hi_esd(), - .tie_lo_esd() - ); - - s8iom0s8_top_gpio_ovtv2 ser_tx_pad ( - `ABUTMENT_PINS -`ifndef TOP_ROUTING - .pad(ser_tx), -`endif - .out(ser_tx_core), - .oe_n(vss), - .hld_h_n(vdd), - .enable_h(porb_h), - .enable_inp_h(loopb23), - .enable_vdda_h(porb_h), - .enable_vddio(vdd1v8), - .enable_vswitch_h(vss), - .inp_dis(vdd1v8), - .vtrip_sel(vss), - .hys_trim(vdd1v8), - .slow(vss), - .slew_ctl({vss, vss}), // 2 bits - .hld_ovr(vss), - .analog_en(vss), - .analog_sel(vss), - .analog_pol(vss), - .dm({vdd1v8, vdd1v8, vss}), // 3 bits - .ib_mode_sel({vss, vss}), // 2 bits - .vinref(vdd1v8), - .pad_a_noesd_h(), - .pad_a_esd_0_h(), - .pad_a_esd_1_h(), - .in(), - .in_h(), - .tie_hi_esd(), - .tie_lo_esd() - ); - - // Corner cells - `ifndef TOP_ROUTING - s8iom0_corner_pad corner [3:0] ( - .vssio(vss), - .vddio(vdd), - .vddio_q(vddio_q), - .vssio_q(vssio_q), - .amuxbus_a(analog_a), - .amuxbus_b(analog_b), - .vssd(vss), - .vssa(vss), - .vswitch(vdd), - .vdda(vdd), - .vccd(vdd1v8), - .vcchib(vdd1v8) - //`ABUTMENT_PINS - ); -`endif - // SoC core - - wire striVe_clk, striVe_rstn; - - striVe_clkrst clkrst( -`ifdef LVS - .vdd1v8(vdd1v8), - .vss(vss), -`endif - .ext_clk_sel(ext_clk_sel_core), - .ext_clk(ext_clk_core), - .pll_clk(pll_clk_core), - .reset(por), - .ext_reset(ext_reset_core), - .clk(striVe_clk), - .resetn(striVe_rstn) -); - - striVe_soc core ( -`ifdef LVS - .vdd1v8(vdd1v8), - .vss(vss), -`endif - - .pll_clk(pll_clk_core), - .clk(striVe_clk), - .resetn(striVe_rstn), - .gpio_out_pad(gpio_out_core), - .gpio_in_pad(gpio_in_core), - .gpio_mode0_pad(gpio_mode0_core), - .gpio_mode1_pad(gpio_mode1_core), - .gpio_outenb_pad(gpio_outenb_core), - .gpio_inenb_pad(gpio_inenb_core), - .spi_sck(SCK_core), - .spi_ro_config(spi_ro_config_core), - .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena_core), - .spi_ro_pll_div(spi_ro_pll_div_core), - .spi_ro_pll_sel(spi_ro_pll_sel_core), - .spi_ro_pll_trim(spi_ro_pll_trim_core), - .spi_ro_mfgr_id(spi_ro_mfgr_id_core), - .spi_ro_prod_id(spi_ro_prod_id_core), - .spi_ro_mask_rev(spi_ro_mask_rev_core), - .ser_tx(ser_tx_core), - .ser_rx(ser_rx_core), - .irq_pin(irq_pin_core), - .irq_spi(irq_spi_core), - .trap(trap_core), - .flash_csb(flash_csb_core), - .flash_clk(flash_clk_core), - .flash_csb_oeb(flash_csb_oeb_core), - .flash_clk_oeb(flash_clk_oeb_core), - .flash_io0_oeb(flash_io0_oeb_core), - .flash_io1_oeb(flash_io1_oeb_core), - .flash_io2_oeb(flash_io2_oeb_core), - .flash_io3_oeb(flash_io3_oeb_core), - .flash_csb_ieb(flash_csb_ieb_core), - .flash_clk_ieb(flash_clk_ieb_core), - .flash_io0_ieb(flash_io0_ieb_core), - .flash_io1_ieb(flash_io1_ieb_core), - .flash_io2_ieb(flash_io2_ieb_core), - .flash_io3_ieb(flash_io3_ieb_core), - .flash_io0_do(flash_io0_do_core), - .flash_io1_do(flash_io1_do_core), - .flash_io2_do(flash_io2_do_core), - .flash_io3_do(flash_io3_do_core), - .flash_io0_di(flash_io0_di_core), - .flash_io1_di(flash_io1_di_core), - .flash_io2_di(flash_io2_di_core), - .flash_io3_di(flash_io3_di_core) - ); - - // For the mask revision input, use an array of digital constant logic cells - wire [3:0] mask_rev_h; - wire [3:0] no_connect; - - sky130_fd_sc_hvl__conb_1 mask_rev_value [3:0] ( -`ifdef LVS - .vpwr(vdd3v3), - .vpb(vdd3v3), - .vnb(vss), - .vgnd(vss), -`endif - .HI({no_connect[3:1], mask_rev[0]}), - .LO({mask_rev[3:1], no_connect[0]}) - ); - - // Housekeeping SPI at 3.3V. - - striVe_spi housekeeping ( -`ifdef LVS - .vdd(vdd3v3), - .vss(vss), -`endif - .RSTB(porb_h), - .SCK(SCK_core_h), - .SDI(SDI_core_h), - .CSB(CSB_core_h), - .SDO(SDO_core_h), - .sdo_enb(SDO_enb_h), - .reg_ena(spi_ro_reg_ena_core_h), - .pll_dco_ena(spi_ro_pll_dco_ena_core_h), - .pll_sel(spi_ro_pll_sel_core_h), - .pll_div(spi_ro_pll_div_core_h), - .pll_trim(spi_ro_pll_trim_core_h), - .irq(irq_spi_core_h), - .RST(por_h), - .reset(ext_reset_core_h), - .trap(trap_core_h), - .mfgr_id(spi_ro_mfgr_id_core_h), - .prod_id(spi_ro_prod_id_core_h), - .mask_rev_in(mask_rev_h), - .mask_rev(spi_ro_mask_rev_core_h) - ); - - // Level shifters from the HVL library - - // On-board digital PLL - - digital_pll pll ( -`ifdef LVS - .vdd(vdd1v8), - .vss(vss), -`endif - .reset(por), - .osc(cclk_core), - .clockc(pll_clk_core), - .clockp({pll_clk_core0, pll_clk_core90}), - .clockd({pll_clk2, pll_clk4, pll_clk8, pll_clk16}), - .div(spi_ro_pll_div_core), - .sel(spi_ro_pll_sel_core), - .dco(spi_ro_pll_dco_ena_core), - .ext_trim(spi_ro_pll_trim_core) - ); - -endmodule
diff --git a/verilog/rtl/digital_pll.v b/verilog/rtl/digital_pll.v index fe564cb..d7dc839 100644 --- a/verilog/rtl/digital_pll.v +++ b/verilog/rtl/digital_pll.v
@@ -4,7 +4,17 @@ `include "digital_pll_controller.v" `include "ring_osc2x13.v" -module digital_pll(reset, extclk_sel, osc, clockc, clockp, clockd, div, sel, dco, ext_trim); +module digital_pll( +`ifdef LVS + vdd, + vss, +`endif + reset, extclk_sel, osc, clockc, clockp, clockd, div, sel, dco, ext_trim); + +`ifdef LVS + input vdd; + input vss; +`endif input reset; // Sense positive reset input extclk_sel; // External clock select (acts as 2nd reset) @@ -32,66 +42,66 @@ assign creset = (dco == 1'b0) ? ireset : 1'b1; ring_osc2x13 ringosc ( - .reset(ireset), - .trim(itrim), - .clockp(clockp) + .reset(ireset), + .trim(itrim), + .clockp(clockp) ); digital_pll_controller pll_control ( - .reset(creset), - .clock(clockp[0]), - .osc(osc), - .div(div), - .trim(otrim) + .reset(creset), + .clock(clockp[0]), + .osc(osc), + .div(div), + .trim(otrim) ); // Select core clock output assign clockc = (sel == 3'b000) ? clockp[0] : - (sel == 3'b001) ? clockd[0] : - (sel == 3'b010) ? clockd[1] : - (sel == 3'b011) ? clockd[2] : - clockd[3]; + (sel == 3'b001) ? clockd[0] : + (sel == 3'b010) ? clockd[1] : + (sel == 3'b011) ? clockd[2] : + clockd[3]; // Derive negative-sense reset from the input positive-sense reset - sky130_fd_sc_hd__inv_4 irb ( - .A(reset), - .Y(resetb) + scs8hd_inv_4 irb ( + .A(reset), + .Y(resetb) ); // Create divided down clocks. The inverted output only comes // with digital standard cells with inverted resets, so the // reset has to be inverted as well. - sky130_fd_sc_hd__dfrbp_1 idiv2 ( - .CLK(clockp[1]), - .D(clockd[0]), - .Q(nint[0]), - .QN(clockd[0]), - .RESETB(resetb) + scs8hd_dfrbp_1 idiv2 ( + .CLK(clockp[1]), + .D(clockd[0]), + .Q(nint[0]), + .QN(clockd[0]), + .RESETB(resetb) ); - sky130_fd_sc_hd__dfrbp_1 idiv4 ( - .CLK(clockd[0]), - .D(clockd[1]), - .Q(nint[1]), - .QN(clockd[1]), - .RESETB(resetb) + scs8hd_dfrbp_1 idiv4 ( + .CLK(clockd[0]), + .D(clockd[1]), + .Q(nint[1]), + .QN(clockd[1]), + .RESETB(resetb) ); - sky130_fd_sc_hd__dfrbp_1 idiv8 ( - .CLK(clockd[1]), - .D(clockd[2]), - .Q(nint[2]), - .QN(clockd[2]), - .RESETB(resetb) + scs8hd_dfrbp_1 idiv8 ( + .CLK(clockd[1]), + .D(clockd[2]), + .Q(nint[2]), + .QN(clockd[2]), + .RESETB(resetb) ); - sky130_fd_sc_hd__dfrbp_1 idiv16 ( - .CLK(clockd[2]), - .D(clockd[3]), - .Q(nint[3]), - .QN(clockd[3]), - .RESETB(resetb) + scs8hd_dfrbp_1 idiv16 ( + .CLK(clockd[2]), + .D(clockd[3]), + .Q(nint[3]), + .QN(clockd[3]), + .RESETB(resetb) ); endmodule
diff --git a/verilog/rtl/digital_pll_controller.v b/verilog/rtl/digital_pll_controller.v index b88cc33..ddc553d 100644 --- a/verilog/rtl/digital_pll_controller.v +++ b/verilog/rtl/digital_pll_controller.v
@@ -54,62 +54,62 @@ assign tint = tval[6:2]; // |<--second-->|<-- first-->| assign trim = (tint == 5'd0) ? 26'b0000000000000_0000000000000 : - (tint == 5'd1) ? 26'b0000000000000_0000000000001 : - (tint == 5'd2) ? 26'b0000000000000_0000001000001 : - (tint == 5'd3) ? 26'b0000000000000_0010001000001 : - (tint == 5'd4) ? 26'b0000000000000_0010001001001 : - (tint == 5'd5) ? 26'b0000000000000_0010101001001 : - (tint == 5'd6) ? 26'b0000000000000_1010101001001 : - (tint == 5'd7) ? 26'b0000000000000_1010101101001 : - (tint == 5'd8) ? 26'b0000000000000_1010101101101 : - (tint == 5'd9) ? 26'b0000000000000_1011101101101 : - (tint == 5'd10) ? 26'b0000000000000_1011101111101 : - (tint == 5'd11) ? 26'b0000000000000_1111101111101 : - (tint == 5'd12) ? 26'b0000000000000_1111101111111 : - (tint == 5'd13) ? 26'b0000000000000_1111111111111 : - (tint == 5'd14) ? 26'b0000000000001_1111111111111 : - (tint == 5'd15) ? 26'b0000001000001_1111111111111 : - (tint == 5'd16) ? 26'b0010001000001_1111111111111 : - (tint == 5'd17) ? 26'b0010001001001_1111111111111 : - (tint == 5'd18) ? 26'b0010101001001_1111111111111 : - (tint == 5'd19) ? 26'b1010101001001_1111111111111 : - (tint == 5'd20) ? 26'b1010101101001_1111111111111 : - (tint == 5'd21) ? 26'b1010101101101_1111111111111 : - (tint == 5'd22) ? 26'b1011101101101_1111111111111 : - (tint == 5'd23) ? 26'b1011101111101_1111111111111 : - (tint == 5'd24) ? 26'b1111101111101_1111111111111 : - (tint == 5'd25) ? 26'b1111101111111_1111111111111 : - 26'b1111111111111_1111111111111; + (tint == 5'd1) ? 26'b0000000000000_0000000000001 : + (tint == 5'd2) ? 26'b0000000000000_0000001000001 : + (tint == 5'd3) ? 26'b0000000000000_0010001000001 : + (tint == 5'd4) ? 26'b0000000000000_0010001001001 : + (tint == 5'd5) ? 26'b0000000000000_0010101001001 : + (tint == 5'd6) ? 26'b0000000000000_1010101001001 : + (tint == 5'd7) ? 26'b0000000000000_1010101101001 : + (tint == 5'd8) ? 26'b0000000000000_1010101101101 : + (tint == 5'd9) ? 26'b0000000000000_1011101101101 : + (tint == 5'd10) ? 26'b0000000000000_1011101111101 : + (tint == 5'd11) ? 26'b0000000000000_1111101111101 : + (tint == 5'd12) ? 26'b0000000000000_1111101111111 : + (tint == 5'd13) ? 26'b0000000000000_1111111111111 : + (tint == 5'd14) ? 26'b0000000000001_1111111111111 : + (tint == 5'd15) ? 26'b0000001000001_1111111111111 : + (tint == 5'd16) ? 26'b0010001000001_1111111111111 : + (tint == 5'd17) ? 26'b0010001001001_1111111111111 : + (tint == 5'd18) ? 26'b0010101001001_1111111111111 : + (tint == 5'd19) ? 26'b1010101001001_1111111111111 : + (tint == 5'd20) ? 26'b1010101101001_1111111111111 : + (tint == 5'd21) ? 26'b1010101101101_1111111111111 : + (tint == 5'd22) ? 26'b1011101101101_1111111111111 : + (tint == 5'd23) ? 26'b1011101111101_1111111111111 : + (tint == 5'd24) ? 26'b1111101111101_1111111111111 : + (tint == 5'd25) ? 26'b1111101111111_1111111111111 : + 26'b1111111111111_1111111111111; always @(posedge clock or posedge reset) begin - if (reset == 1'b1) begin - tval <= 7'd0; // Note: trim[0] must be zero for startup to work. - oscbuf <= 3'd0; - prep <= 3'd0; - count0 <= 5'd0; - count1 <= 5'd0; + if (reset == 1'b1) begin + tval <= 7'd0; // Note: trim[0] must be zero for startup to work. + oscbuf <= 3'd0; + prep <= 3'd0; + count0 <= 5'd0; + count1 <= 5'd0; - end else begin - oscbuf <= {oscbuf[1:0], osc}; + end else begin + oscbuf <= {oscbuf[1:0], osc}; - if (oscbuf[2] != oscbuf[1]) begin - count1 <= count0; - count0 <= 5'b00001; - prep <= {prep[1:0], 1'b1}; + if (oscbuf[2] != oscbuf[1]) begin + count1 <= count0; + count0 <= 5'b00001; + prep <= {prep[1:0], 1'b1}; - if (prep == 3'b111) begin - if (sum > div) begin - tval <= tval + 1; - end else if (sum < div) begin - tval <= tval - 1; - end - end - end else begin - if (count0 != 5'b11111) begin - count0 <= count0 + 1; - end - end - end + if (prep == 3'b111) begin + if (sum > div) begin + tval <= tval + 1; + end else if (sum < div) begin + tval <= tval - 1; + end + end + end else begin + if (count0 != 5'b11111) begin + count0 <= count0 + 1; + end + end + end end endmodule // digital_pll_controller
diff --git a/verilog/rtl/gpio_wb.v b/verilog/rtl/gpio_wb.v new file mode 100644 index 0000000..5f014ce --- /dev/null +++ b/verilog/rtl/gpio_wb.v
@@ -0,0 +1,147 @@ +module gpio_wb # ( + parameter BASE_ADR = 32'h 2100_0000, + parameter GPIO_DATA = 8'h 00, + parameter GPIO_ENA = 8'h 04, + parameter GPIO_PU = 8'h 08, + parameter GPIO_PD = 8'h 0c +) ( + input wb_clk_i, + input wb_rst_i, + + input [31:0] wb_dat_i, + input [31:0] wb_adr_i, + input [3:0] wb_sel_i, + input wb_cyc_i, + input wb_stb_i, + input wb_we_i, + + output [31:0] wb_dat_o, + output wb_ack_o, + + input [15:0] gpio_in_pad, + output [15:0] gpio, + output [15:0] gpio_oeb, + output [15:0] gpio_pu, + output [15:0] gpio_pd +); + + wire resetn; + wire valid; + wire ready; + wire [3:0] iomem_we; + + assign resetn = ~wb_rst_i; + assign valid = wb_stb_i && wb_cyc_i; + + assign iomem_we = wb_sel_i & {4{wb_we_i}}; + assign wb_ack_o = ready; + + gpio #( + .BASE_ADR(BASE_ADR), + .GPIO_DATA(GPIO_DATA), + .GPIO_ENA(GPIO_ENA), + .GPIO_PD(GPIO_PD), + .GPIO_PU(GPIO_PU) + ) gpio_ctrl ( + .clk(wb_clk_i), + .resetn(resetn), + + .gpio_in_pad(gpio_in_pad), + + .iomem_addr(wb_adr_i), + .iomem_valid(valid), + .iomem_wstrb(iomem_we), + .iomem_wdata(wb_dat_i), + .iomem_rdata(wb_dat_o), + .iomem_ready(ready), + + .gpio(gpio), + .gpio_oeb(gpio_oeb), + .gpio_pu(gpio_pu), + .gpio_pd(gpio_pd) + ); + +endmodule + +module gpio #( + parameter BASE_ADR = 32'h 2100_0000, + parameter GPIO_DATA = 8'h 00, + parameter GPIO_ENA = 8'h 04, + parameter GPIO_PU = 8'h 08, + parameter GPIO_PD = 8'h 0c +) ( + input clk, + input resetn, + + input [15:0] gpio_in_pad, + + input [31:0] iomem_addr, + input iomem_valid, + input [3:0] iomem_wstrb, + input [31:0] iomem_wdata, + output reg [31:0] iomem_rdata, + output reg iomem_ready, + + output [15:0] gpio, + output [15:0] gpio_oeb, + output [15:0] gpio_pu, + output [15:0] gpio_pd +); + + reg [15:0] gpio; // GPIO output data + reg [15:0] gpio_pu; // GPIO pull-up enable + reg [15:0] gpio_pd; // GPIO pull-down enable + reg [15:0] gpio_oeb; // GPIO output enable (sense negative) + + wire gpio_sel; + wire gpio_oeb_sel; + wire gpio_pu_sel; + wire gpio_pd_sel; + + assign gpio_sel = (iomem_addr[7:0] == GPIO_DATA); + assign gpio_oeb_sel = (iomem_addr[7:0] == GPIO_ENA); + assign gpio_pu_sel = (iomem_addr[7:0] == GPIO_PU); + assign gpio_pd_sel = (iomem_addr[7:0] == GPIO_PD); + + always @(posedge clk) begin + if (!resetn) begin + gpio <= 0; + gpio_oeb <= 16'hffff; + gpio_pu <= 0; + gpio_pd <= 0; + end else begin + iomem_ready <= 0; + if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin + iomem_ready <= 1'b 1; + + if (gpio_sel) begin + iomem_rdata <= {gpio, gpio_in_pad}; + + if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8]; + + end else if (gpio_oeb_sel) begin + iomem_rdata <= {16'd0, gpio_oeb}; + + if (iomem_wstrb[0]) gpio_oeb[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) gpio_oeb[15: 8] <= iomem_wdata[15: 8]; + + end else if (gpio_pu_sel) begin + iomem_rdata <= {16'd0, gpio_pu}; + + if (iomem_wstrb[0]) gpio_pu[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) gpio_pu[15: 8] <= iomem_wdata[15: 8]; + + end else if (gpio_pd_sel) begin + iomem_rdata <= {16'd0, gpio_pd}; + + if (iomem_wstrb[0]) gpio_pd[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) gpio_pd[15: 8] <= iomem_wdata[15: 8]; + + end + + end + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/harness.v b/verilog/rtl/harness.v new file mode 100644 index 0000000..b8403e1 --- /dev/null +++ b/verilog/rtl/harness.v
@@ -0,0 +1,1303 @@ +/*----------------------------------------------------------*/ +/* striVe, a raven/ravenna-like architecture in SkyWater s8 */ +/* */ +/* 1st edition, test of SkyWater s8 process */ +/* This version is missing all analog functionality, */ +/* including crystal oscillator, voltage regulator, and PLL */ +/* For simplicity, the pad arrangement of Raven has been */ +/* retained, even though many pads have no internal */ +/* connection. */ +/* */ +/* Copyright 2020 efabless, Inc. */ +/* Written by Tim Edwards, December 2019 */ +/* This file is open source hardware released under the */ +/* Apache 2.0 license. See file LICENSE. */ +/* */ +/*----------------------------------------------------------*/ + +`timescale 1 ns / 1 ps + +`define USE_OPENRAM +`define USE_PG_PIN +`define functional + +`ifdef SYNTH_OPENLANE + `include "../stubs/scs8hd_conb_1.v" + `include "../stubs/s8iom0s8.v" + `include "../stubs/power_pads_lib.v" +`else + + `ifndef LVS + `include "/ef/tech/SW/EFS8A/libs.ref/verilog/s8iom0s8/s8iom0s8.v" + `include "/ef/tech/SW/EFS8A/libs.ref/verilog/s8iom0s8/power_pads_lib.v" + `include "/ef/tech/SW/EFS8A/libs.ref/verilog/scs8hd/scs8hd.v" + + `include "lvlshiftdown.v" + `include "mgmt_soc.v" + `include "striVe_spi.v" + `include "digital_pll.v" + `include "striVe_clkrst.v" + `include "../ip/crossbar.v" + `include "../dv/dummy_slave.v" + + `endif +`endif + +`ifdef USE_OPENRAM + `include "sram_1rw1r_32_256_8_sky130.v" +`endif + +//`define TOP_ROUTING +`ifndef TOP_ROUTING + `define ABUTMENT_PINS \ + .amuxbus_a(analog_a),\ + .amuxbus_b(analog_b),\ + .vssa(vss),\ + .vdda(vdd),\ + .vswitch(vdd),\ + .vddio_q(vddio_q),\ + .vcchib(vdd1v8),\ + .vddio(vdd),\ + .vccd(vdd1v8),\ + .vssio(vss),\ + .vssd(vss),\ + .vssio_q(vssio_q), +`else + `define ABUTMENT_PINS +`endif + +// Crossbar Slaves +`ifndef SLAVE_ADR + `define SLAVE_ADR { \ + {8'hB0, {24{1'b0}}},\ + {8'hA0, {24{1'b0}}},\ + {8'h90, {24{1'b0}}},\ + {8'h80, {24{1'b0}}}\ + }\ +`endif + +`ifndef ADR_MASK + `define ADR_MASK { \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}}, \ + {8'hFF, {24{1'b0}}} \ + }\ +`endif + +`define NM 2 // Crossbar switch number of masters +`define NS 4 // Crossbar switch number of slaves +`define DW 32 +`define AW 32 + +module harness (vdd, vdd1v8, vss, gpio, xi, xo, adc0_in, adc1_in, adc_high, adc_low, + comp_inn, comp_inp, RSTB, ser_rx, ser_tx, irq, SDO, SDI, CSB, SCK, + xclk, flash_csb, flash_clk, flash_io0, flash_io1, flash_io2, flash_io3); + + inout vdd; + inout vdd1v8; + inout vss; + inout [15:0] gpio; + input xi; // CMOS clock input, not a crystal + output xo; // divide-by-16 clock output + input adc0_in; + input adc1_in; + input adc_high; + input adc_low; + input comp_inn; + input comp_inp; + input RSTB; // NOTE: Replaces analog_out pin from raven chip + input ser_rx; + output ser_tx; + input irq; + output SDO; + input SDI; + input CSB; + input SCK; + input xclk; + output flash_csb; + output flash_clk; + output flash_io0; + output flash_io1; + output flash_io2; + output flash_io3; + + wire [15:0] gpio_out_core; + wire [15:0] gpio_in_core; + wire [15:0] gpio_mode0_core; + wire [15:0] gpio_mode1_core; + wire [15:0] gpio_outenb_core; + wire [15:0] gpio_inenb_core; + + wire analog_a, analog_b; /* Placeholders for analog signals */ + + wire porb_h; + wire porb_l; + wire por_h; + wire por; + wire SCK_core; + wire SDI_core; + wire CSB_core; + wire SDO_core; + wire SDO_enb; + wire spi_ro_xtal_ena_core; + wire spi_ro_reg_ena_core; + wire spi_ro_pll_dco_ena_core; + wire [2:0] spi_ro_pll_sel_core; + wire [4:0] spi_ro_pll_div_core; + wire [25:0] spi_ro_pll_trim_core; + wire ext_clk_sel_core; + wire irq_spi_core; + wire ext_reset_core; + wire trap_core; + wire [11:0] spi_ro_mfgr_id_core; + wire [7:0] spi_ro_prod_id_core; + wire [3:0] spi_ro_mask_rev_core; + + // Instantiate power cells for VDD3V3 domain (8 total; 4 high clamps and + // 4 low clamps) + s8iom0_vdda_hvc_pad vdd3v3hclamp [1:0] ( + `ABUTMENT_PINS + .drn_hvc(), + .src_bdy_hvc() + ); + + s8iom0_vddio_hvc_pad vddiohclamp [1:0] ( + `ABUTMENT_PINS + .drn_hvc(), + .src_bdy_hvc() + ); + + + s8iom0_vdda_lvc_pad vdd3v3lclamp [3:0] ( + `ABUTMENT_PINS + .bdy2_b2b(), + .drn_lvc1(), + .drn_lvc2(), + .src_bdy_lvc1(), + .src_bdy_lvc2() + ); + + // Instantiate the core voltage supply (since it is not generated on-chip) + // (1.8V) (4 total, 2 high and 2 low clamps) + + s8iom0_vccd_hvc_pad vdd1v8hclamp [1:0] ( + `ABUTMENT_PINS + .drn_hvc(), + .src_bdy_hvc() + ); + + s8iom0_vccd_lvc_pad vdd1v8lclamp [1:0] ( + `ABUTMENT_PINS + .bdy2_b2b(), + .drn_lvc1(), + .drn_lvc2(), + .src_bdy_lvc1(), + .src_bdy_lvc2() + ); + + // Instantiate ground cells (7 total, 4 high clamps and 3 low clamps) + + s8iom0_vssa_hvc_pad vsshclamp [3:0] ( + `ABUTMENT_PINS + .drn_hvc(), + .src_bdy_hvc() + ); + + s8iom0_vssa_lvc_pad vssalclamp ( + `ABUTMENT_PINS + .bdy2_b2b(), + .drn_lvc1(), + .drn_lvc2(), + .src_bdy_lvc1(), + .src_bdy_lvc2() + ); + + s8iom0_vssd_lvc_pad vssdlclamp ( + `ABUTMENT_PINS + .bdy2_b2b(), + .drn_lvc1(), + .drn_lvc2(), + .src_bdy_lvc1(), + .src_bdy_lvc2() + ); + + s8iom0_vssio_lvc_pad vssiolclamp ( + `ABUTMENT_PINS + .bdy2_b2b(), + .drn_lvc1(), + .drn_lvc2(), + .src_bdy_lvc1(), + .src_bdy_lvc2() + ); + + wire [47:0] dm_all; + + assign dm_all = {gpio_mode1_core[15], gpio_mode1_core[15], gpio_mode0_core[15], + gpio_mode1_core[14], gpio_mode1_core[14], gpio_mode0_core[14], + gpio_mode1_core[13], gpio_mode1_core[13], gpio_mode0_core[13], + gpio_mode1_core[12], gpio_mode1_core[12], gpio_mode0_core[12], + gpio_mode1_core[11], gpio_mode1_core[11], gpio_mode0_core[11], + gpio_mode1_core[10], gpio_mode1_core[10], gpio_mode0_core[10], + gpio_mode1_core[9], gpio_mode1_core[9], gpio_mode0_core[9], + gpio_mode1_core[8], gpio_mode1_core[8], gpio_mode0_core[8], + gpio_mode1_core[7], gpio_mode1_core[7], gpio_mode0_core[7], + gpio_mode1_core[6], gpio_mode1_core[6], gpio_mode0_core[6], + gpio_mode1_core[5], gpio_mode1_core[5], gpio_mode0_core[5], + gpio_mode1_core[4], gpio_mode1_core[4], gpio_mode0_core[4], + gpio_mode1_core[3], gpio_mode1_core[3], gpio_mode0_core[3], + gpio_mode1_core[2], gpio_mode1_core[2], gpio_mode0_core[2], + gpio_mode1_core[1], gpio_mode1_core[1], gpio_mode0_core[1], + gpio_mode1_core[0], gpio_mode1_core[0], gpio_mode0_core[0]}; + + // GPIO pads + s8iom0_gpiov2_pad gpio_pad [15:0] ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(gpio), +`endif + .out(gpio_out_core), // Signal from core to pad + .oe_n(gpio_outenb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold signals during deep sleep (sense inverted) + .enable_h(porb_h), // Post-reset enable + .enable_inp_h(loopb0), // Input buffer state when disabled + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(gpio_inenb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm(dm_all), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(gpio_in_core), // Signal from pad to core + .in_h(), // VDDA domain signal (unused) + .tie_hi_esd(), + .tie_lo_esd(loopb0) + ); + + s8iom0_gpiov2_pad xi_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(xi), +`endif + .out(), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb1), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(xi_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb1) + ); + + s8iom0_gpiov2_pad xo_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(xo), +`endif + .out(pll_clk16), // Signal from core to pad + .oe_n(vss), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb2), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb2) + ); + + s8iom0_gpiov2_pad adc0_in_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(adc0_in), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb3), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad adc1_in_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(adc1_in), +`endif + .pad_a_noesd_h(), // Direct pad connection + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb4), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad adc_high_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(adc_high), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb5), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vdd1v8), // + .analog_pol(vdd1v8), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad adc_low_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(adc_low), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb6), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad comp_inn_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(comp_inn), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb7), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad comp_inp_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(comp_inp), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb8), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vdd1v8), // + .analog_sel(vdd1v8), // + .analog_pol(vss), // + .dm({vss, vss, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + // NOTE: The analog_out pad from the raven chip has been replaced by + // the digital reset input RSTB on striVe due to the lack of an on-board + // power-on-reset circuit. The XRES pad is used for providing a glitch- + // free reset. + + s8iom0s8_top_xres4v2 RSTB_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(RSTB), +`endif + .tie_weak_hi_h(xresloop), // Loop-back connection to pad through pad_a_esd_h + .tie_hi_esd(), + .tie_lo_esd(), + .pad_a_esd_h(xresloop), + .xres_h_n(porb_h), + .disable_pullup_h(vss), // 0 = enable pull-up on reset pad + .enable_h(vdd), // Power-on-reset to the power-on-reset input?? + .en_vddio_sig_h(vss), // No idea. + .inp_sel_h(vss), // 1 = use filt_in_h else filter the pad input + .filt_in_h(vss), // Alternate input for glitch filter + .pullup_h(vss), // Pullup connection for alternate filter input + .enable_vddio(vdd1v8) + ); + + s8iom0_gpiov2_pad irq_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(irq), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb10), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(irq_pin_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb10) + ); + + s8iom0_gpiov2_pad SDO_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(SDO), +`endif + .out(SDO_core), // Signal from core to pad + .oe_n(SDO_enb), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb11), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(vdd1v8), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb11) + ); + + s8iom0_gpiov2_pad SDI_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(SDI), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb12), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(SDI_core), // Signal from pad to core + .in_h(SDI_core_h), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad CSB_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(CSB), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb13), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(CSB_core), // Signal from pad to core + .in_h(CSB_core_h), + .tie_hi_esd(), + .tie_lo_esd(loopb13) + ); + + s8iom0_gpiov2_pad SCK_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(SCK), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb14), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(SCK_core), // Signal from pad to core + .in_h(SCK_core_h), // Signal in vdda domain (3.3V) + .tie_hi_esd(), + .tie_lo_esd(loopb14) + ); + + s8iom0_gpiov2_pad xclk_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(xclk), +`endif + .out(vss), // Signal from core to pad + .oe_n(vdd1v8), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb15), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(por), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vss, vss, vdd1v8}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(ext_clk_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb15) + ); + + // assign flash_csb = (input) ? + s8iom0_gpiov2_pad flash_csb_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_csb), +`endif + .out(flash_csb_core), // Signal from core to pad + .oe_n(flash_csb_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb16), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_csb_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad flash_clk_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_clk), +`endif + .out(flash_clk_core), // Signal from core to pad + .oe_n(flash_clk_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb17), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_clk_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({vdd1v8, vdd1v8, vss}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0_gpiov2_pad flash_io0_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_io0), +`endif + .out(flash_io0_do_core), // Signal from core to pad + .oe_n(flash_io0_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb18), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_io0_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(flash_io0_di_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb18) + ); + + s8iom0_gpiov2_pad flash_io1_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_io1), +`endif + .out(flash_io1_do_core), // Signal from core to pad + .oe_n(flash_io1_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb19), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_io1_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(flash_io1_di_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb19) + ); + + s8iom0_gpiov2_pad flash_io2_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_io2), +`endif + .out(flash_io2_do_core), // Signal from core to pad + .oe_n(flash_io2_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb20), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_io2_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({flash_io2_ieb_core, flash_io2_ieb_core, flash_io2_oeb_core}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(flash_io2_di_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb20) + ); + + s8iom0_gpiov2_pad flash_io3_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(flash_io3), +`endif + .out(flash_io3_do_core), // Signal from core to pad + .oe_n(flash_io3_oeb_core), // Output enable (sense inverted) + .hld_h_n(vdd), // Hold + .enable_h(porb_h), // Enable + .enable_inp_h(loopb21), // Enable input buffer + .enable_vdda_h(porb_h), // + .enable_vswitch_h(vss), // + .enable_vddio(vdd1v8), // + .inp_dis(flash_io3_ieb_core), // Disable input buffer + .ib_mode_sel(vss), // + .vtrip_sel(vss), // + .slow(vss), // + .hld_ovr(vss), // + .analog_en(vss), // + .analog_sel(vss), // + .analog_pol(vss), // + .dm({flash_io3_ieb_core, flash_io3_ieb_core, flash_io3_oeb_core}), // (3 bits) Mode control + .pad_a_noesd_h(), // Direct pad connection + .pad_a_esd_0_h(), // Pad connection through 150 ohms + .pad_a_esd_1_h(), // Pad connection through 150 ohms + .in(flash_io3_di_core), // Signal from pad to core + .in_h(), + .tie_hi_esd(), + .tie_lo_esd(loopb21) + ); + + // Instantiate GPIO overvoltage (I2C) compliant cell + // (Use this for ser_rx and ser_tx; no reason other than testing + // the use of the cell.) (Might be worth adding in the I2C IP from + // ravenna just to test on a proper I2C channel.) + + s8iom0s8_top_gpio_ovtv2 ser_rx_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(ser_rx), +`endif + .out(vss), + .oe_n(vdd1v8), + .hld_h_n(vdd), + .enable_h(porb_h), + .enable_inp_h(loopb22), + .enable_vdda_h(porb_h), + .enable_vddio(vdd1v8), + .enable_vswitch_h(vss), + .inp_dis(por), + .vtrip_sel(vss), + .hys_trim(vdd1v8), + .slow(vss), + .slew_ctl({vss, vss}), // 2 bits + .hld_ovr(vss), + .analog_en(vss), + .analog_sel(vss), + .analog_pol(vss), + .dm({vss, vss, vdd1v8}), // 3 bits + .ib_mode_sel({vss, vss}), // 2 bits + .vinref(vdd1v8), + .pad_a_noesd_h(), + .pad_a_esd_0_h(), + .pad_a_esd_1_h(), + .in(ser_rx_core), + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + s8iom0s8_top_gpio_ovtv2 ser_tx_pad ( + `ABUTMENT_PINS +`ifndef TOP_ROUTING + .pad(ser_tx), +`endif + .out(ser_tx_core), + .oe_n(vss), + .hld_h_n(vdd), + .enable_h(porb_h), + .enable_inp_h(loopb23), + .enable_vdda_h(porb_h), + .enable_vddio(vdd1v8), + .enable_vswitch_h(vss), + .inp_dis(vdd1v8), + .vtrip_sel(vss), + .hys_trim(vdd1v8), + .slow(vss), + .slew_ctl({vss, vss}), // 2 bits + .hld_ovr(vss), + .analog_en(vss), + .analog_sel(vss), + .analog_pol(vss), + .dm({vdd1v8, vdd1v8, vss}), // 3 bits + .ib_mode_sel({vss, vss}), // 2 bits + .vinref(vdd1v8), + .pad_a_noesd_h(), + .pad_a_esd_0_h(), + .pad_a_esd_1_h(), + .in(), + .in_h(), + .tie_hi_esd(), + .tie_lo_esd() + ); + + // Corner cells (These are overlay cells; it is not clear what is normally + // supposed to go under them.) + `ifndef TOP_ROUTING + s8iom0_corner_pad corner [3:0] ( + .vssio(vss), + .vddio(vdd), + .vddio_q(vddio_q), + .vssio_q(vssio_q), + .amuxbus_a(analog_a), + .amuxbus_b(analog_b), + .vssd(vss), + .vssa(vss), + .vswitch(vdd), + .vdda(vdd), + .vccd(vdd1v8), + .vcchib(vdd1v8) + //`ABUTMENT_PINS + ); +`endif + + // SoC core + wire [9:0] adc0_data_core; + wire [1:0] adc0_inputsrc_core; + wire [9:0] adc1_data_core; + wire [1:0] adc1_inputsrc_core; + wire [9:0] dac_value_core; + wire [1:0] comp_ninputsrc_core; + wire [1:0] comp_pinputsrc_core; + wire [7:0] spi_ro_config_core; + + wire xbar_cyc_o_core; + wire xbar_stb_o_core; + wire xbar_we_o_core; + wire [3:0] xbar_sel_o_core; + wire [31:0] xbar_adr_o_core; + wire [31:0] xbar_dat_o_core; + wire xbar_ack_i_core; + wire [31:0] xbar_dat_i_core; + + wire striVe_clk, striVe_rstn; + + striVe_clkrst clkrst( + `ifdef LVS + .vdd1v8(vdd1v8), + .vss(vss), + `endif + .ext_clk_sel(ext_clk_sel_core), + .ext_clk(ext_clk_core), + .pll_clk(pll_clk_core), + .reset(por), + .ext_reset(ext_reset_core), + .clk(striVe_clk), + .resetn(striVe_rstn) + ); + + mgmt_soc core ( + `ifdef LVS + .vdd1v8(vdd1v8), + .vss(vss), + `endif + .pll_clk(pll_clk_core), + .ext_clk(ext_clk_core), + .ext_clk_sel(ext_clk_sel_core), + .clk(striVe_clk), + .resetn(striVe_rstn), + .gpio_out_pad(gpio_out_core), + .gpio_in_pad(gpio_in_core), + .gpio_mode0_pad(gpio_mode0_core), + .gpio_mode1_pad(gpio_mode1_core), + .gpio_outenb_pad(gpio_outenb_core), + .gpio_inenb_pad(gpio_inenb_core), + .adc0_ena(adc0_ena_core), + .adc0_convert(adc0_convert_core), + .adc0_data(adc0_data_core), + .adc0_done(adc0_done_core), + .adc0_clk(adc0_clk_core), + .adc0_inputsrc(adc0_inputsrc_core), + .adc1_ena(adc1_ena_core), + .adc1_convert(adc1_convert_core), + .adc1_clk(adc1_clk_core), + .adc1_inputsrc(adc1_inputsrc_core), + .adc1_data(adc1_data_core), + .adc1_done(adc1_done_core), + .xtal_in(xtal_in_core), + .comp_in(comp_in_core), + .spi_sck(SCK_core), + .spi_ro_config(spi_ro_config_core), + .spi_ro_xtal_ena(spi_ro_xtal_ena_core), + .spi_ro_reg_ena(spi_ro_reg_ena_core), + .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena_core), + .spi_ro_pll_div(spi_ro_pll_div_core), + .spi_ro_pll_sel(spi_ro_pll_sel_core), + .spi_ro_pll_trim(spi_ro_pll_trim_core), + .spi_ro_mfgr_id(spi_ro_mfgr_id_core), + .spi_ro_prod_id(spi_ro_prod_id_core), + .spi_ro_mask_rev(spi_ro_mask_rev_core), + .ser_tx(ser_tx_core), + .ser_rx(ser_rx_core), + .irq_pin(irq_pin_core), + .irq_spi(irq_spi_core), + .trap(trap_core), + .flash_csb(flash_csb_core), + .flash_clk(flash_clk_core), + .flash_csb_oeb(flash_csb_oeb_core), + .flash_clk_oeb(flash_clk_oeb_core), + .flash_io0_oeb(flash_io0_oeb_core), + .flash_io1_oeb(flash_io1_oeb_core), + .flash_io2_oeb(flash_io2_oeb_core), + .flash_io3_oeb(flash_io3_oeb_core), + .flash_csb_ieb(flash_csb_ieb_core), + .flash_clk_ieb(flash_clk_ieb_core), + .flash_io0_ieb(flash_io0_ieb_core), + .flash_io1_ieb(flash_io1_ieb_core), + .flash_io2_ieb(flash_io2_ieb_core), + .flash_io3_ieb(flash_io3_ieb_core), + .flash_io0_do(flash_io0_do_core), + .flash_io1_do(flash_io1_do_core), + .flash_io2_do(flash_io2_do_core), + .flash_io3_do(flash_io3_do_core), + .flash_io0_di(flash_io0_di_core), + .flash_io1_di(flash_io1_di_core), + .flash_io2_di(flash_io2_di_core), + .flash_io3_di(flash_io3_di_core), + .xbar_cyc_o(xbar_cyc_o_core), + .xbar_stb_o(xbar_stb_o_core), + .xbar_we_o (xbar_we_o_core), + .xbar_sel_o(xbar_sel_o_core), + .xbar_adr_o(xbar_adr_o_core), + .xbar_dat_o(xbar_dat_o_core), + .xbar_ack_i(xbar_ack_i_core), + .xbar_dat_i(xbar_dat_i_core) + ); + + // Mega-Project + wire mega_cyc_o; + wire mega_stb_o; + wire mega_we_o; + wire [3:0] mega_sel_o; + wire [31:0] mega_adr_o; + wire [31:0] mega_dat_o; + wire mega_ack_i; + wire [31:0] mega_dat_i; + + // Masters interface + wire [`NM-1:0] wbm_cyc_i; + wire [`NM-1:0] wbm_stb_i; + wire [`NM-1:0] wbm_we_i; + wire [(`NM*(`DW/8))-1:0] wbm_sel_i; + wire [(`NM*`AW)-1:0] wbm_adr_i; + wire [(`NM*`DW)-1:0] wbm_dat_i; + + wire [`NM-1:0] wbm_ack_o; + wire [(`NM*`DW)-1:0] wbm_dat_o; + + // Slaves interfaces + wire [`NS-1:0] wbs_ack_o; + wire [(`NS*`DW)-1:0] wbs_dat_i; + wire [`NS-1:0] wbs_cyc_o; + wire [`NS-1:0] wbs_stb_o; + wire [`NS-1:0] wbs_we_o; + wire [(`NS*(`DW/8))-1:0] wbs_sel_o; + wire [(`NS*`AW)-1:0] wbs_adr_o; + wire [(`NS*`DW)-1:0] wbs_dat_o; + + assign wbm_cyc_i = {mega_cyc_o, xbar_cyc_o_core}; + assign wbm_stb_i = {mega_stb_o, xbar_stb_o_core}; + assign wbm_we_i = {mega_we_o , xbar_we_o_core}; + assign wbm_sel_i = {mega_sel_o, xbar_sel_o_core}; + assign wbm_adr_i = {mega_adr_o, xbar_adr_o_core}; + assign wbm_dat_i = {mega_dat_o, xbar_dat_o_core}; + + assign xbar_ack_i_core = wbm_ack_o[0]; + assign mega_ack_i = wbm_ack_o[1]; + assign xbar_dat_i_core = wbm_dat_o[`DW-1:0]; + assign mega_dat_i = wbm_dat_o[`DW*2-1:`DW]; + + // Instantiate four dummy slaves for testing (TO-BE-REMOVED) + dummy_slave dummy_slaves [`NS-1:0]( + .wb_clk_i({`NS{striVe_clk}}), + .wb_rst_i({`NS{~striVe_rstn}}), + .wb_stb_i(wbs_stb_o), + .wb_cyc_i(wbs_cyc_o), + .wb_we_i(wbs_we_o), + .wb_sel_i(wbs_sel_o), + .wb_adr_i(wbs_adr_o), + .wb_dat_i(wbs_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + // Crossbar Switch + wb_xbar #( + .NM(`NM), + .NS(`NS), + .AW(`AW), + .DW(`DW), + .SLAVE_ADR(`SLAVE_ADR), + .ADR_MASK(`ADR_MASK) + ) + wb_xbar( + .wb_clk_i(striVe_clk), + .wb_rst_i(~striVe_rstn), + + // Masters interface + .wbm_cyc_i(wbm_cyc_i), + .wbm_stb_i(wbm_stb_i), + .wbm_we_i (wbm_we_i), + .wbm_sel_i(wbm_sel_i), + .wbm_adr_i(wbm_adr_i), + .wbm_dat_i(wbm_dat_i), + .wbm_ack_o(wbm_ack_o), + .wbm_dat_o(wbm_dat_o), + + // Slaves interfaces + .wbs_ack_i(wbs_ack_o), + .wbs_dat_i(wbs_dat_o), + .wbs_cyc_o(wbs_cyc_o), + .wbs_stb_o(wbs_stb_o), + .wbs_we_o (wbs_we_o), + .wbs_sel_o(wbs_sel_o), + .wbs_adr_o(wbs_adr_o), + .wbs_dat_o(wbs_dat_i) + ); + + // For the mask revision input, use an array of digital constant logic cells + wire [3:0] mask_rev; + wire [3:0] no_connect; + scs8hd_conb_1 mask_rev_value [3:0] ( + `ifdef LVS + .vpwr(vdd1v8), + .vpb(vdd1v8), + .vnb(vss), + .vgnd(vss), + `endif + .HI({no_connect[3:1], mask_rev[0]}), + .LO({mask_rev[3:1], no_connect[0]}) + ); + + // Housekeeping SPI at 1.8V. + + striVe_spi housekeeping ( + `ifdef LVS + .vdd(vdd1v8), + .vss(vss), + `endif + .RSTB(porb_l), + .SCK(SCK_core), + .SDI(SDI_core), + .CSB(CSB_core), + .SDO(SDO_core), + .sdo_enb(SDO_enb), + + .xtal_ena(spi_ro_xtal_ena_core), + .reg_ena(spi_ro_reg_ena_core), + .pll_dco_ena(spi_ro_pll_dco_ena_core), + .pll_sel(spi_ro_pll_sel_core), + .pll_div(spi_ro_pll_div_core), + .pll_trim(spi_ro_pll_trim_core), + .pll_bypass(ext_clk_sel_core), + .irq(irq_spi_core), + .RST(por), + .reset(ext_reset_core), + .trap(trap_core), + .mfgr_id(spi_ro_mfgr_id_core), + .prod_id(spi_ro_prod_id_core), + .mask_rev_in(mask_rev), + .mask_rev(spi_ro_mask_rev_core) + ); + + lvlshiftdown porb_level_shift ( + `ifdef LVS + .vpwr(vdd1v8), + .vpb(vdd1v8), + .vnb(vss), + .vgnd(vss), + `endif + .A(porb_h), + .X(porb_l) + ); + + // On-board experimental digital PLL + // Use xi_core, assumed to be a CMOS digital clock signal. xo_core + // is used as an output and set from pll_clk16. + + digital_pll pll ( + `ifdef LVS + .vdd(vdd1v8), + .vss(vss), + `endif + .reset(por), + .extclk_sel(ext_clk_sel_core), + .osc(xi_core), + .clockc(pll_clk_core), + .clockp({pll_clk_core0, pll_clk_core90}), + .clockd({pll_clk2, pll_clk4, pll_clk8, pll_clk16}), + .div(spi_ro_pll_div_core), + .sel(spi_ro_pll_sel_core), + .dco(spi_ro_pll_dco_ena_core), + .ext_trim(spi_ro_pll_trim_core) + ); + +endmodule
diff --git a/verilog/rtl/la_wb.v b/verilog/rtl/la_wb.v new file mode 100644 index 0000000..fd713a4 --- /dev/null +++ b/verilog/rtl/la_wb.v
@@ -0,0 +1,201 @@ +module la_wb # ( + parameter BASE_ADR = 32'h 2200_0000, + parameter LA_DATA_0 = 8'h00, + parameter LA_DATA_1 = 8'h04, + parameter LA_DATA_2 = 8'h08, + parameter LA_DATA_3 = 8'h0c, + parameter LA_ENA_0 = 8'h10, + parameter LA_ENA_1 = 8'h14, + parameter LA_ENA_2 = 8'h18, + parameter LA_ENA_3 = 8'h1c +) ( + input wb_clk_i, + input wb_rst_i, + + input [31:0] wb_dat_i, + input [31:0] wb_adr_i, + input [3:0] wb_sel_i, + input wb_cyc_i, + input wb_stb_i, + input wb_we_i, + + output [31:0] wb_dat_o, + output wb_ack_o, + + output [127:0] la_data, + output [127:0] la_ena +); + + wire resetn; + wire valid; + wire ready; + wire [3:0] iomem_we; + + assign resetn = ~wb_rst_i; + assign valid = wb_stb_i && wb_cyc_i; + + assign iomem_we = wb_sel_i & {4{wb_we_i}}; + assign wb_ack_o = ready; + + la #( + .BASE_ADR(BASE_ADR), + .LA_DATA_0(LA_DATA_0), + .LA_DATA_1(LA_DATA_1), + .LA_DATA_2(LA_DATA_2), + .LA_DATA_3(LA_DATA_3), + .LA_ENA_0(LA_ENA_0), + .LA_ENA_1(LA_ENA_1), + .LA_ENA_2(LA_ENA_2), + .LA_ENA_3(LA_ENA_3) + ) la_ctrl ( + .clk(wb_clk_i), + .resetn(resetn), + .iomem_addr(wb_adr_i), + .iomem_valid(valid), + .iomem_wstrb(iomem_we), + .iomem_wdata(wb_dat_i), + .iomem_rdata(wb_dat_o), + .iomem_ready(ready), + .la_data(la_data), + .la_ena(la_ena) + ); + +endmodule + +module la #( + parameter BASE_ADR = 32'h 2200_0000, + parameter LA_DATA_0 = 8'h00, + parameter LA_DATA_1 = 8'h04, + parameter LA_DATA_2 = 8'h08, + parameter LA_DATA_3 = 8'h0c, + parameter LA_ENA_0 = 8'h10, + parameter LA_ENA_1 = 8'h14, + parameter LA_ENA_2 = 8'h18, + parameter LA_ENA_3 = 8'h1c +) ( + input clk, + input resetn, + + input [31:0] iomem_addr, + input iomem_valid, + input [3:0] iomem_wstrb, + input [31:0] iomem_wdata, + + output reg [31:0] iomem_rdata, + output reg iomem_ready, + + output [127:0] la_data, + output [127:0] la_ena +); + + reg [31:0] la_data_0; + reg [31:0] la_data_1; + reg [31:0] la_data_2; + reg [31:0] la_data_3; + + reg [31:0] la_ena_0; + reg [31:0] la_ena_1; + reg [31:0] la_ena_2; + reg [31:0] la_ena_3; + + wire [3:0] la_data_sel; + wire [3:0] la_ena_sel; + + assign la_data = {la_data_3, la_data_2, la_data_1, la_data_0}; + assign la_ena = {la_ena_3, la_ena_2, la_ena_1, la_ena_0}; + + assign la_data_sel = { + (iomem_addr[7:0] == LA_DATA_3), + (iomem_addr[7:0] == LA_DATA_2), + (iomem_addr[7:0] == LA_DATA_1), + (iomem_addr[7:0] == LA_DATA_0) + }; + + assign la_ena_sel = { + (iomem_addr[7:0] == LA_ENA_3), + (iomem_addr[7:0] == LA_ENA_2), + (iomem_addr[7:0] == LA_ENA_1), + (iomem_addr[7:0] == LA_ENA_0) + }; + + + always @(posedge clk) begin + if (!resetn) begin + la_data_0 <= 0; + la_data_1 <= 0; + la_data_2 <= 0; + la_data_3 <= 0; + la_ena_0 <= 0; + la_ena_1 <= 0; + la_ena_2 <= 0; + la_ena_3 <= 0; + end else begin + iomem_ready <= 0; + if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin + iomem_ready <= 1'b 1; + + if (la_data_sel[0]) begin + iomem_rdata <= la_data_0; + + if (iomem_wstrb[0]) la_data_0[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_data_0[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_data_0[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_data_0[31:24] <= iomem_wdata[31:24]; + + end else if (la_data_sel[1]) begin + iomem_rdata <= la_data_1; + + if (iomem_wstrb[0]) la_data_1[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_data_1[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_data_1[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_data_1[31:24] <= iomem_wdata[31:24]; + + end else if (la_data_sel[2]) begin + iomem_rdata <= la_data_2; + + if (iomem_wstrb[0]) la_data_2[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_data_2[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_data_2[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_data_2[31:24] <= iomem_wdata[31:24]; + + end else if (la_data_sel[3]) begin + iomem_rdata <= la_data_3; + + if (iomem_wstrb[0]) la_data_3[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_data_3[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_data_3[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_data_3[31:24] <= iomem_wdata[31:24]; + end else if (la_ena_sel[0]) begin + iomem_rdata <= la_ena_0; + + if (iomem_wstrb[0]) la_ena_0[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_ena_0[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_ena_0[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_ena_0[31:24] <= iomem_wdata[31:24]; + end else if (la_ena_sel[1]) begin + iomem_rdata <= la_ena_1; + + if (iomem_wstrb[0]) la_ena_1[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_ena_1[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_ena_1[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_ena_1[31:24] <= iomem_wdata[31:24]; + end else if (la_ena_sel[2]) begin + iomem_rdata <= la_ena_2; + + if (iomem_wstrb[0]) la_ena_2[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_ena_2[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_ena_2[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_ena_2[31:24] <= iomem_wdata[31:24]; + end else if (la_ena_sel[3]) begin + iomem_rdata <= la_ena_3; + + if (iomem_wstrb[0]) la_ena_3[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) la_ena_3[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) la_ena_3[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) la_ena_3[31:24] <= iomem_wdata[31:24]; + end + end + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/lvlshiftdown.v b/verilog/rtl/lvlshiftdown.v new file mode 100644 index 0000000..a647cf6 --- /dev/null +++ b/verilog/rtl/lvlshiftdown.v
@@ -0,0 +1,30 @@ +/* Level shifter (simplified model, as buffer only) */ + +module lvlshiftdown ( +`ifdef LVS + vpwr, vpb, vnb, vgnd, +`endif + A, + X + ); + + +`ifdef LVS + input vpwr; + input vpb; + input vnb; + input vgnd; +`endif + +input A; +output X; + +`ifdef LVS + wire vpwr, vpb, vnb, vgnd; +`endif + +wire A, X; + +assign X = A; + +endmodule // lvlshiftdown
diff --git a/verilog/rtl/mem_wb.v b/verilog/rtl/mem_wb.v new file mode 100644 index 0000000..e0b6599 --- /dev/null +++ b/verilog/rtl/mem_wb.v
@@ -0,0 +1,106 @@ +module mem_wb # ( + parameter integer MEM_WORDS = 256 +) ( + input wb_clk_i, + input wb_rst_i, + + input [31:0] wb_adr_i, + input [31:0] wb_dat_i, + input [3:0] wb_sel_i, + input wb_we_i, + input wb_cyc_i, + input wb_stb_i, + + output wb_ack_o, + output [31:0] wb_dat_o + +); + wire valid; + wire ram_wen; + wire [3:0] wen; // write enable + + assign valid = wb_cyc_i & wb_stb_i; + assign ram_wen = wb_we_i && valid; + + assign wen = wb_sel_i & {4{ram_wen}} ; + +`ifndef USE_OPENRAM + assign wb_ack_o = valid; +`else + + /* + Ack Generation + - write transaction: asserted upon receiving adr_i & dat_i + - read transaction : asserted one clock cycle after receiving the adr_i & dat_i + */ + + reg [2:0] wb_ack_read; + + assign wb_ack_o = wb_we_i ? valid : &wb_ack_read; + + always @(posedge wb_clk_i) begin + if (wb_rst_i == 1'b 1) begin + wb_ack_read <= 3'b 00; + end else begin + wb_ack_read <= {3{valid}} & {1'b1, wb_ack_read[2:1]}; + end + end + +`endif + + soc_mem mem( + .clk(wb_clk_i), + .ena(valid), + .wen(wen), + .addr(wb_adr_i[23:2]), + .wdata(wb_dat_i), + .rdata(wb_dat_o) + ); + +endmodule + +module soc_mem +`ifndef USE_OPENRAM +#( + parameter integer WORDS = 256 +) +`endif + ( + input clk, + input ena, + input [3:0] wen, + input [21:0] addr, + input [31:0] wdata, + output[31:0] rdata +); + +`ifndef USE_OPENRAM + reg [31:0] rdata; + reg [31:0] mem [0:WORDS-1]; + + always @(posedge clk) begin + if (ena == 1'b1) begin + rdata <= mem[addr]; + if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0]; + if (wen[1]) mem[addr][15: 8] <= wdata[15: 8]; + if (wen[2]) mem[addr][23:16] <= wdata[23:16]; + if (wen[3]) mem[addr][31:24] <= wdata[31:24]; + end + end +`else + + /* Using Port 0 Only - Size: 1KB, 256x32 bits */ + //sram_1rw1r_32_256_8_scn4m_subm + sram_1rw1r_32_256_8_sky130 SRAM( + .clk0(clk), + .csb0(~ena), + .web0(~|wen), + .wmask0(wen), + .addr0(addr[7:0]), + .din0(wdata), + .dout0(rdata) + ); + +`endif + +endmodule
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v new file mode 100644 index 0000000..007ca0f --- /dev/null +++ b/verilog/rtl/mgmt_soc.v
@@ -0,0 +1,876 @@ +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Revision 1, July 2019: Added signals to drive flash_clk and flash_csb + * output enable (inverted), tied to reset so that the flash is completely + * isolated from the processor when the processor is in reset. + * + * Also: Made ram_wenb a 4-bit bus so that the memory access can be made + * byte-wide for byte-wide instructions. + */ + +`ifdef PICORV32_V +`error "openstriVe_soc.v must be read before picorv32.v!" +`endif + +`define PICORV32_REGS openstriVe_soc_regs + +`include "picorv32.v" +`include "spimemio.v" +`include "simpleuart.v" +`include "wb_intercon.v" +`include "mem_wb.v" +`include "gpio_wb.v" +`include "spi_sysctrl.v" +`include "sysctrl.v" +`include "la_wb.v" + +module mgmt_soc ( +`ifdef LVS + inout vdd1v8, /* 1.8V domain */ + inout vss, +`endif + input pll_clk, + input ext_clk, + input ext_clk_sel, + + input clk, + input resetn, + + // Memory mapped I/O signals + output [15:0] gpio_out_pad, // Connect to out on gpio pad + input [15:0] gpio_in_pad, // Connect to in on gpio pad + output [15:0] gpio_mode0_pad, // Connect to dm[0] on gpio pad + output [15:0] gpio_mode1_pad, // Connect to dm[2] on gpio pad + output [15:0] gpio_outenb_pad, // Connect to oe_n on gpio pad + output [15:0] gpio_inenb_pad, // Connect to inp_dis on gpio pad + + // LA signals + input [127:0] la_input, // From Mega-Project to cpu + output [127:0] la_output, // From CPU to Mega-Project + output [127:0] la_oe, // LA output enable (sensitiviy according to tri-state ?) + + output adc0_ena, + output adc0_convert, + input [9:0] adc0_data, + input adc0_done, + output adc0_clk, + output [1:0] adc0_inputsrc, + output adc1_ena, + output adc1_convert, + output adc1_clk, + output [1:0] adc1_inputsrc, + input [9:0] adc1_data, + input adc1_done, + + output dac_ena, + output [9:0] dac_value, + + output analog_out_sel, // Analog output select (DAC or bandgap) + output opamp_ena, // Op-amp enable for analog output + output opamp_bias_ena, // Op-amp bias enable for analog output + output bg_ena, // Bandgap enable + + output comp_ena, + output [1:0] comp_ninputsrc, + output [1:0] comp_pinputsrc, + output rcosc_ena, + + output overtemp_ena, + input overtemp, + input rcosc_in, // RC oscillator output + input xtal_in, // crystal oscillator output + input comp_in, // comparator output + input spi_sck, + + input [7:0] spi_ro_config, + input spi_ro_xtal_ena, + input spi_ro_reg_ena, + input spi_ro_pll_dco_ena, + input [4:0] spi_ro_pll_div, + input [2:0] spi_ro_pll_sel, + input [25:0] spi_ro_pll_trim, + + input [11:0] spi_ro_mfgr_id, + input [7:0] spi_ro_prod_id, + input [3:0] spi_ro_mask_rev, + + output ser_tx, + input ser_rx, + + // IRQ + input irq_pin, // dedicated IRQ pin + input irq_spi, // IRQ from standalone SPI + + // trap + output trap, + + // Flash memory control (SPI master) + output flash_csb, + output flash_clk, + + output flash_csb_oeb, + output flash_clk_oeb, + + output flash_io0_oeb, + output flash_io1_oeb, + output flash_io2_oeb, + output flash_io3_oeb, + + output flash_csb_ieb, + output flash_clk_ieb, + + output flash_io0_ieb, + output flash_io1_ieb, + output flash_io2_ieb, + output flash_io3_ieb, + + output flash_io0_do, + output flash_io1_do, + output flash_io2_do, + output flash_io3_do, + + input flash_io0_di, + input flash_io1_di, + input flash_io2_di, + input flash_io3_di, + + // Crossbar Switch Slaves + input [31:0] xbar_dat_i, + input xbar_ack_i, + output xbar_cyc_o, + output xbar_stb_o, + output xbar_we_o, + output [3:0] xbar_sel_o, + output [31:0] xbar_adr_o, + output [31:0] xbar_dat_o +); + /* Memory reverted back to 256 words while memory has to be synthesized */ + parameter integer MEM_WORDS = 256; + parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory + parameter [31:0] PROGADDR_RESET = 32'h 1000_0000; + parameter [31:0] PROGADDR_IRQ = 32'h 0000_0000; + + // Slaves Base Addresses + parameter RAM_BASE_ADR = 32'h 0000_0000; + parameter FLASH_BASE_ADR = 32'h 1000_0000; + parameter UART_BASE_ADR = 32'h 2000_0000; + parameter GPIO_BASE_ADR = 32'h 2100_0000; + parameter LA_BASE_ADR = 32'h 2200_0000; + parameter SYS_BASE_ADR = 32'h 2F00_0000; + parameter SPI_BASE_ADR = 32'h 2E00_0000; + parameter FLASH_CTRL_CFG = 32'h 2D00_0000; + parameter XBAR_BASE_ADR = 32'h 8000_0000; + + // UART + parameter UART_CLK_DIV = 8'h00; + parameter UART_DATA = 8'h04; + + // SOC GPIO + parameter GPIO_DATA = 8'h00; + parameter GPIO_ENA = 8'h04; + parameter GPIO_PU = 8'h08; + parameter GPIO_PD = 8'h0c; + + // LDO + parameter LA_DATA_0 = 8'h00; + parameter LA_DATA_1 = 8'h04; + parameter LA_DATA_2 = 8'h08; + parameter LA_DATA_3 = 8'h0c; + parameter LA_ENA_0 = 8'h10; + parameter LA_ENA_1 = 8'h14; + parameter LA_ENA_2 = 8'h18; + parameter LA_ENA_3 = 8'h1c; + + // SPI-Controlled Registers + parameter SPI_CFG = 8'h00; + parameter SPI_ENA = 8'h04; + parameter SPI_PLL_CFG = 8'h08; + parameter SPI_MFGR_ID = 8'h0c; + parameter SPI_PROD_ID = 8'h10; + parameter SPI_MASK_REV = 8'h14; + parameter SPI_PLL_BYPASS = 8'h18; + + // System Control Registers + parameter OSC_ENA = 8'h00; + parameter OSC_OUT = 8'h04; + parameter XTAL_OUT = 8'h08; + parameter PLL_OUT = 8'h0c; + parameter TRAP_OUT = 8'h10; + parameter IRQ7_SRC = 8'h14; + parameter IRQ8_SRC = 8'h18; + parameter OVERTEMP_ENA = 8'h1c; + parameter OVERTEMP_DATA = 8'h20; + parameter OVERTEMP_OUT = 8'h24; + + // Wishbone Interconnect + localparam ADR_WIDTH = 32; + localparam DAT_WIDTH = 32; + localparam NUM_SLAVES = 9; + + parameter [NUM_SLAVES*ADR_WIDTH-1: 0] ADR_MASK = { + {8'h80, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}}, + {8'hFF, {ADR_WIDTH-8{1'b0}}} + }; + parameter [NUM_SLAVES*ADR_WIDTH-1: 0] SLAVE_ADR = { + {XBAR_BASE_ADR}, + {SYS_BASE_ADR}, + {SPI_BASE_ADR}, + {FLASH_CTRL_CFG}, + {LA_BASE_ADR}, + {GPIO_BASE_ADR}, + {UART_BASE_ADR}, + {FLASH_BASE_ADR}, + {RAM_BASE_ADR} + }; + + // memory-mapped I/O control registers + wire [15:0] gpio_pullup; // Intermediate GPIO pullup + wire [15:0] gpio_pulldown; // Intermediate GPIO pulldown + wire [15:0] gpio_outenb; // Intermediate GPIO out enable (bar) + wire [15:0] gpio_out; // Intermediate GPIO output + + wire [15:0] gpio; // GPIO output data + wire [15:0] gpio_pu; // GPIO pull-up enable + wire [15:0] gpio_pd; // GPIO pull-down enable + wire [15:0] gpio_oeb; // GPIO output enable (sense negative) + + wire [1:0] rcosc_output_dest; // RC oscillator output destination + wire [1:0] overtemp_dest; // Over-temperature alarm destination + wire [1:0] pll_output_dest; // PLL clock output destination + wire [1:0] xtal_output_dest; // Crystal oscillator output destination + wire [1:0] trap_output_dest; // Trap signal output destination + wire [1:0] irq_7_inputsrc; // IRQ 5 source + wire [1:0] irq_8_inputsrc; // IRQ 6 source + + // Analgo registers (not-used) + reg adc0_ena; // ADC0 enable + reg adc0_convert; // ADC0 convert + reg [1:0] adc0_clksrc; // ADC0 clock source + reg [1:0] adc0_inputsrc; // ADC0 input source + reg adc1_ena; // ADC1 enable + reg adc1_convert; // ADC1 convert + reg [1:0] adc1_clksrc; // ADC1 clock source + reg [1:0] adc1_inputsrc; // ADC1 input source + reg dac_ena; // DAC enable + reg [9:0] dac_value; // DAC output value + reg comp_ena; // Comparator enable + reg [1:0] comp_ninputsrc; // Comparator negative input source + reg [1:0] comp_pinputsrc; // Comparator positive input source + reg [1:0] comp_output_dest; // Comparator output destination + + reg analog_out_sel; // Analog output select + reg opamp_ena; // Analog output op-amp enable + reg opamp_bias_ena; // Analog output op-amp bias enable + reg bg_ena; // Bandgap enable + wire adc0_clk; // ADC0 clock (multiplexed) + wire adc1_clk; // ADC1 clock (multiplexed) + + // ADC clock assignments + assign adc0_clk = (adc0_clksrc == 2'b00) ? rcosc_in : + (adc0_clksrc == 2'b01) ? spi_sck : + (adc0_clksrc == 2'b10) ? xtal_in : + ext_clk; + + assign adc1_clk = (adc1_clksrc == 2'b00) ? rcosc_in : + (adc1_clksrc == 2'b01) ? spi_sck : + (adc1_clksrc == 2'b10) ? xtal_in : + ext_clk; + + // GPIO assignments + assign gpio_out[0] = (comp_output_dest == 2'b01) ? comp_in : gpio[0]; + assign gpio_out[1] = (comp_output_dest == 2'b10) ? comp_in : gpio[1]; + assign gpio_out[2] = (rcosc_output_dest == 2'b01) ? rcosc_in : gpio[2]; + assign gpio_out[3] = (rcosc_output_dest == 2'b10) ? rcosc_in : gpio[3]; + assign gpio_out[4] = (rcosc_output_dest == 2'b11) ? rcosc_in : gpio[4]; + assign gpio_out[5] = (xtal_output_dest == 2'b01) ? xtal_in : gpio[5]; + assign gpio_out[6] = (xtal_output_dest == 2'b10) ? xtal_in : gpio[6]; + assign gpio_out[7] = (xtal_output_dest == 2'b11) ? xtal_in : gpio[7]; + assign gpio_out[8] = (pll_output_dest == 2'b01) ? pll_clk : gpio[8]; + assign gpio_out[9] = (pll_output_dest == 2'b10) ? pll_clk : gpio[9]; + assign gpio_out[10] = (pll_output_dest == 2'b11) ? clk : gpio[10]; + assign gpio_out[11] = (trap_output_dest == 2'b01) ? trap : gpio[11]; + assign gpio_out[12] = (trap_output_dest == 2'b10) ? trap : gpio[12]; + assign gpio_out[13] = (trap_output_dest == 2'b11) ? trap : gpio[13]; + assign gpio_out[14] = (overtemp_dest == 2'b01) ? overtemp : gpio[14]; + assign gpio_out[15] = (overtemp_dest == 2'b10) ? overtemp : gpio[15]; + + assign gpio_outenb[0] = (comp_output_dest == 2'b00) ? gpio_oeb[0] : 1'b0; + assign gpio_outenb[1] = (comp_output_dest == 2'b00) ? gpio_oeb[1] : 1'b0; + assign gpio_outenb[2] = (rcosc_output_dest == 2'b00) ? gpio_oeb[2] : 1'b0; + assign gpio_outenb[3] = (rcosc_output_dest == 2'b00) ? gpio_oeb[3] : 1'b0; + assign gpio_outenb[4] = (rcosc_output_dest == 2'b00) ? gpio_oeb[4] : 1'b0; + assign gpio_outenb[5] = (xtal_output_dest == 2'b00) ? gpio_oeb[5] : 1'b0; + assign gpio_outenb[6] = (xtal_output_dest == 2'b00) ? gpio_oeb[6] : 1'b0; + assign gpio_outenb[7] = (xtal_output_dest == 2'b00) ? gpio_oeb[7] : 1'b0; + assign gpio_outenb[8] = (pll_output_dest == 2'b00) ? gpio_oeb[8] : 1'b0; + assign gpio_outenb[9] = (pll_output_dest == 2'b00) ? gpio_oeb[9] : 1'b0; + assign gpio_outenb[10] = (pll_output_dest == 2'b00) ? gpio_oeb[10] : 1'b0; + assign gpio_outenb[11] = (trap_output_dest == 2'b00) ? gpio_oeb[11] : 1'b0; + assign gpio_outenb[12] = (trap_output_dest == 2'b00) ? gpio_oeb[12] : 1'b0; + assign gpio_outenb[13] = (trap_output_dest == 2'b00) ? gpio_oeb[13] : 1'b0; + assign gpio_outenb[14] = (overtemp_dest == 2'b00) ? gpio_oeb[14] : 1'b0; + assign gpio_outenb[15] = (overtemp_dest == 2'b00) ? gpio_oeb[15] : 1'b0; + + assign gpio_pullup[0] = (comp_output_dest == 2'b00) ? gpio_pu[0] : 1'b0; + assign gpio_pullup[1] = (comp_output_dest == 2'b00) ? gpio_pu[1] : 1'b0; + assign gpio_pullup[2] = (rcosc_output_dest == 2'b00) ? gpio_pu[2] : 1'b0; + assign gpio_pullup[3] = (rcosc_output_dest == 2'b00) ? gpio_pu[3] : 1'b0; + assign gpio_pullup[4] = (rcosc_output_dest == 2'b00) ? gpio_pu[4] : 1'b0; + assign gpio_pullup[5] = (xtal_output_dest == 2'b00) ? gpio_pu[5] : 1'b0; + assign gpio_pullup[6] = (xtal_output_dest == 2'b00) ? gpio_pu[6] : 1'b0; + assign gpio_pullup[7] = (xtal_output_dest == 2'b00) ? gpio_pu[7] : 1'b0; + assign gpio_pullup[8] = (pll_output_dest == 2'b00) ? gpio_pu[8] : 1'b0; + assign gpio_pullup[9] = (pll_output_dest == 2'b00) ? gpio_pu[9] : 1'b0; + assign gpio_pullup[10] = (pll_output_dest == 2'b00) ? gpio_pu[10] : 1'b0; + assign gpio_pullup[11] = (trap_output_dest == 2'b00) ? gpio_pu[11] : 1'b0; + assign gpio_pullup[12] = (trap_output_dest == 2'b00) ? gpio_pu[12] : 1'b0; + assign gpio_pullup[13] = (trap_output_dest == 2'b00) ? gpio_pu[13] : 1'b0; + assign gpio_pullup[14] = (overtemp_dest == 2'b00) ? gpio_pu[14] : 1'b0; + assign gpio_pullup[15] = (overtemp_dest == 2'b00) ? gpio_pu[15] : 1'b0; + + assign gpio_pulldown[0] = (comp_output_dest == 2'b00) ? gpio_pd[0] : 1'b0; + assign gpio_pulldown[1] = (comp_output_dest == 2'b00) ? gpio_pd[1] : 1'b0; + assign gpio_pulldown[2] = (rcosc_output_dest == 2'b00) ? gpio_pd[2] : 1'b0; + assign gpio_pulldown[3] = (rcosc_output_dest == 2'b00) ? gpio_pd[3] : 1'b0; + assign gpio_pulldown[4] = (rcosc_output_dest == 2'b00) ? gpio_pd[4] : 1'b0; + assign gpio_pulldown[5] = (xtal_output_dest == 2'b00) ? gpio_pd[5] : 1'b0; + assign gpio_pulldown[6] = (xtal_output_dest == 2'b00) ? gpio_pd[6] : 1'b0; + assign gpio_pulldown[7] = (xtal_output_dest == 2'b00) ? gpio_pd[7] : 1'b0; + assign gpio_pulldown[8] = (pll_output_dest == 2'b00) ? gpio_pd[8] : 1'b0; + assign gpio_pulldown[9] = (pll_output_dest == 2'b00) ? gpio_pd[9] : 1'b0; + assign gpio_pulldown[10] = (pll_output_dest == 2'b00) ? gpio_pd[10] : 1'b0; + assign gpio_pulldown[11] = (trap_output_dest == 2'b00) ? gpio_pd[11] : 1'b0; + assign gpio_pulldown[12] = (trap_output_dest == 2'b00) ? gpio_pd[12] : 1'b0; + assign gpio_pulldown[13] = (trap_output_dest == 2'b00) ? gpio_pd[13] : 1'b0; + assign gpio_pulldown[14] = (overtemp_dest == 2'b00) ? gpio_pd[14] : 1'b0; + assign gpio_pulldown[15] = (overtemp_dest == 2'b00) ? gpio_pd[15] : 1'b0; + + // Convert GPIO signals to s8 pad signals + convert_gpio_sigs convert_gpio_bit [15:0] ( + .gpio_out(gpio_out), + .gpio_outenb(gpio_outenb), + .gpio_pu(gpio_pullup), + .gpio_pd(gpio_pulldown), + .gpio_out_pad(gpio_out_pad), + .gpio_outenb_pad(gpio_outenb_pad), + .gpio_inenb_pad(gpio_inenb_pad), + .gpio_mode1_pad(gpio_mode1_pad), + .gpio_mode0_pad(gpio_mode0_pad) + ); + + reg [31:0] irq; + wire irq_7; + wire irq_8; + wire irq_stall; + wire irq_uart; + + assign irq_7 = (irq_7_inputsrc == 2'b01) ? gpio_in_pad[0] : + (irq_7_inputsrc == 2'b10) ? gpio_in_pad[1] : + (irq_7_inputsrc == 2'b11) ? gpio_in_pad[2] : 1'b0; + assign irq_8 = (irq_8_inputsrc == 2'b01) ? gpio_in_pad[3] : + (irq_8_inputsrc == 2'b10) ? gpio_in_pad[4] : + (irq_8_inputsrc == 2'b11) ? gpio_in_pad[5] : 1'b0; + + assign irq_uart = 0; + assign irq_stall = 0; + + always @* begin + irq = 0; + irq[3] = irq_stall; + irq[4] = irq_uart; + irq[5] = irq_pin; + irq[6] = irq_spi; + irq[7] = irq_7; + irq[8] = irq_8; + irq[9] = comp_output_dest[0] & comp_output_dest[1] & comp_in; + irq[10] = overtemp_dest[0] & overtemp_dest[1] & overtemp; + end + + // wire mem_valid; + // wire mem_instr; + // wire mem_ready; + // wire [31:0] mem_addr; + // wire [31:0] mem_wdata; + // wire [3:0] mem_wstrb; + // wire [31:0] mem_rdata; + + // wire spimem_ready; + // wire [31:0] spimem_rdata; + + // reg ram_ready; + // wire [31:0] ram_rdata; + + // assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01); + // assign iomem_wstrb = mem_wstrb; + // assign iomem_addr = mem_addr; + // assign iomem_wdata = mem_wdata; + + // wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000); + // wire [31:0] spimemio_cfgreg_do; + + // wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004); + // wire [31:0] simpleuart_reg_div_do; + + // wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008); + // wire [31:0] simpleuart_reg_dat_do; + // wire simpleuart_reg_dat_wait; + + // Akin to the slave ack ? + // assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel || + // simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait); + + // Akin to wb_intercon -- mem_rdata like cpu_dat_i + // assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata : + // spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do : + // simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000; + + wire wb_clk_i; + wire wb_rst_i; + + // Assumption : no syscon module and wb_clk is the clock coming from the chip pin ? + assign wb_clk_i = clk; + assign wb_rst_i = ~resetn; // Redundant + + // Wishbone Master + wire [31:0] cpu_adr_o; + wire [31:0] cpu_dat_i; + wire [3:0] cpu_sel_o; + wire cpu_we_o; + wire cpu_cyc_o; + wire cpu_stb_o; + wire [31:0] cpu_dat_o; + wire cpu_ack_i; + + assign xbar_cyc_o = cpu_cyc_o; + assign xbar_we_o = cpu_we_o; + assign xbar_sel_o = cpu_sel_o; + assign xbar_adr_o = cpu_adr_o; + assign xbar_dat_o = cpu_dat_o; + + picorv32_wb #( + .STACKADDR(STACKADDR), + .PROGADDR_RESET(PROGADDR_RESET), + .PROGADDR_IRQ(PROGADDR_IRQ), + .BARREL_SHIFTER(1), + .COMPRESSED_ISA(1), + .ENABLE_MUL(1), + .ENABLE_DIV(1), + .ENABLE_IRQ(1), + .ENABLE_IRQ_QREGS(0) + ) cpu ( + .wb_clk_i (wb_clk_i), + .wb_rst_i (wb_rst_i), + .trap (trap), + .irq (irq), + .mem_instr(mem_instr), + .wbm_adr_o(cpu_adr_o), + .wbm_dat_i(cpu_dat_i), + .wbm_stb_o(cpu_stb_o), + .wbm_ack_i(cpu_ack_i), + .wbm_cyc_o(cpu_cyc_o), + .wbm_dat_o(cpu_dat_o), + .wbm_we_o(cpu_we_o), + .wbm_sel_o(cpu_sel_o) + ); + + // Wishbone Slave SPIMEMIO + wire spimemio_flash_stb_i; + wire spimemio_flash_ack_o; + wire [31:0] spimemio_flash_dat_o; + + wire spimemio_cfg_stb_i; + wire spimemio_cfg_ack_o; + wire [31:0] spimemio_cfg_dat_o; + + spimemio_wb spimemio ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + // FLash Slave + .wb_flash_stb_i(spimemio_flash_stb_i), + .wb_flash_ack_o(spimemio_flash_ack_o), + .wb_flash_dat_o(spimemio_flash_dat_o), + + // Config Register Slave + .wb_cfg_stb_i(spimemio_cfg_stb_i), + .wb_cfg_ack_o(spimemio_cfg_ack_o), + .wb_cfg_dat_o(spimemio_cfg_dat_o), + + .flash_csb (flash_csb), + .flash_clk (flash_clk), + + .flash_csb_oeb (flash_csb_oeb), + .flash_clk_oeb (flash_clk_oeb), + + .flash_io0_oeb (flash_io0_oeb), + .flash_io1_oeb (flash_io1_oeb), + .flash_io2_oeb (flash_io2_oeb), + .flash_io3_oeb (flash_io3_oeb), + + .flash_csb_ieb (flash_csb_ieb), + .flash_clk_ieb (flash_clk_ieb), + + .flash_io0_ieb (flash_io0_ieb), + .flash_io1_ieb (flash_io1_ieb), + .flash_io2_ieb (flash_io2_ieb), + .flash_io3_ieb (flash_io3_ieb), + + .flash_io0_do (flash_io0_do), + .flash_io1_do (flash_io1_do), + .flash_io2_do (flash_io2_do), + .flash_io3_do (flash_io3_do), + + .flash_io0_di (flash_io0_di), + .flash_io1_di (flash_io1_di), + .flash_io2_di (flash_io2_di), + .flash_io3_di (flash_io3_di) + ); + + // Wishbone Slave uart + wire uart_stb_i; + wire uart_ack_o; + wire [31:0] uart_dat_o; + + simpleuart_wb #( + .BASE_ADR(UART_BASE_ADR), + .CLK_DIV(UART_CLK_DIV), + .DATA(UART_DATA) + ) simpleuart ( + // Wishbone Interface + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(uart_stb_i), + .wb_ack_o(uart_ack_o), + .wb_dat_o(uart_dat_o), + + .ser_tx(ser_tx), + .ser_rx(ser_rx) + ); + + // Wishbone Slave GPIO Registers + wire gpio_stb_i; + wire gpio_ack_o; + wire [31:0] gpio_dat_o; + + gpio_wb #( + .BASE_ADR(GPIO_BASE_ADR), + .GPIO_DATA(GPIO_DATA), + .GPIO_ENA(GPIO_ENA), + .GPIO_PD(GPIO_PD), + .GPIO_PU(GPIO_PU) + ) gpio_wb ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(gpio_stb_i), + .wb_ack_o(gpio_ack_o), + .wb_dat_o(gpio_dat_o), + .gpio_in_pad(gpio_in_pad), + + .gpio(gpio), + .gpio_oeb(gpio_oeb), + .gpio_pu(gpio_pu), + .gpio_pd(gpio_pd) + ); + + // Wishbone SPI System Control Registers (RO) + wire spi_sys_stb_i; + wire spi_sys_ack_o; + wire [31:0] spi_sys_dat_o; + + spi_sysctrl_wb #( + .BASE_ADR(SPI_BASE_ADR), + .SPI_CFG(SPI_CFG), + .SPI_ENA(SPI_ENA), + .SPI_PLL_CFG(SPI_PLL_CFG), + .SPI_MFGR_ID(SPI_MFGR_ID), + .SPI_PROD_ID(SPI_PROD_ID), + .SPI_MASK_REV(SPI_MASK_REV), + .SPI_PLL_BYPASS(SPI_PLL_BYPASS) + ) spi_sysctrl ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(spi_sys_stb_i), + .wb_ack_o(spi_sys_ack_o), + .wb_dat_o(spi_sys_dat_o), + + .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + .spi_ro_pll_div(spi_ro_pll_div), + .spi_ro_pll_sel(spi_ro_pll_sel), + .spi_ro_xtal_ena(spi_ro_xtal_ena), + .spi_ro_reg_ena(spi_ro_reg_ena), + + .spi_ro_pll_trim(spi_ro_pll_trim), + .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena), + + .spi_ro_mfgr_id(spi_ro_mfgr_id), + .spi_ro_prod_id(spi_ro_prod_id), + .spi_ro_mask_rev(spi_ro_mask_rev), + .pll_bypass(ext_clk_sel) + ); + + // Wishbone Slave System Control Register + wire sys_stb_i; + wire sys_ack_o; + wire [31:0] sys_dat_o; + + sysctrl_wb #( + .BASE_ADR(SYS_BASE_ADR), + .OSC_ENA(OSC_ENA), + .OSC_OUT(OSC_OUT), + .XTAL_OUT(XTAL_OUT), + .PLL_OUT(PLL_OUT), + .TRAP_OUT(TRAP_OUT), + .IRQ7_SRC(IRQ7_SRC), + .IRQ8_SRC(IRQ8_SRC), + .OVERTEMP_ENA(OVERTEMP_ENA), + .OVERTEMP_DATA(OVERTEMP_DATA), + .OVERTEMP_OUT(OVERTEMP_OUT) + ) sysctrl ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(sys_stb_i), + .wb_ack_o(sys_ack_o), + .wb_dat_o(sys_dat_o), + + .overtemp(overtemp), + .rcosc_ena(rcosc_ena), + .rcosc_output_dest(rcosc_output_dest), + .xtal_output_dest(xtal_output_dest), + .pll_output_dest(pll_output_dest), + .trap_output_dest(trap_output_dest), + .irq_7_inputsrc(irq_7_inputsrc), + .irq_8_inputsrc(irq_8_inputsrc), + .overtemp_ena(overtemp_ena), + .overtemp_dest(overtemp_dest) + ); + + // Logic Analyzer + wire la_stb_i; + wire la_ack_o; + wire [31:0] la_dat_o; + + la_wb #( + .BASE_ADR(LA_BASE_ADR), + .LA_DATA_0(LA_DATA_0), + .LA_DATA_1(LA_DATA_1), + .LA_DATA_3(LA_DATA_3), + .LA_ENA_0(LA_ENA_0), + .LA_ENA_1(LA_ENA_1), + .LA_ENA_2(LA_ENA_2), + .LA_ENA_3(LA_ENA_3) + ) la ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(la_stb_i), + .wb_ack_o(la_ack_o), + .wb_dat_o(la_dat_o), + + .la_data(la_output), + .la_ena(la_oe) + ); + + // Wishbone Slave RAM + wire mem_stb_i; + wire mem_ack_o; + wire [31:0] mem_dat_o; + + mem_wb #( + .MEM_WORDS(MEM_WORDS) + ) soc_mem ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(cpu_adr_o), + .wb_dat_i(cpu_dat_o), + .wb_sel_i(cpu_sel_o), + .wb_we_i(cpu_we_o), + .wb_cyc_i(cpu_cyc_o), + + .wb_stb_i(mem_stb_i), + .wb_ack_o(mem_ack_o), + .wb_dat_o(mem_dat_o) + ); + + // Wishbone intercon logic + wb_intercon #( + .AW(ADR_WIDTH), + .DW(DAT_WIDTH), + .NS(NUM_SLAVES), + .ADR_MASK(ADR_MASK), + .SLAVE_ADR(SLAVE_ADR) + ) intercon ( + // Master Interface + .wbm_adr_i(cpu_adr_o), + .wbm_stb_i(cpu_stb_o), + .wbm_dat_o(cpu_dat_i), + .wbm_ack_o(cpu_ack_i), + + // Slaves Interface + .wbs_stb_o({ xbar_stb_o, sys_stb_i, spi_sys_stb_i, spimemio_cfg_stb_i, la_stb_i, gpio_stb_i, uart_stb_i, spimemio_flash_stb_i, mem_stb_i }), + .wbs_dat_i({ xbar_dat_i, sys_dat_o, spi_sys_dat_o, spimemio_cfg_dat_o, la_dat_o, gpio_dat_o, uart_dat_o, spimemio_flash_dat_o, mem_dat_o }), + .wbs_ack_i({ xbar_ack_i, sys_ack_o, spi_sys_ack_o, spimemio_cfg_ack_o, la_ack_o, gpio_ack_o, uart_ack_o, spimemio_flash_ack_o, mem_ack_o }) + ); + + // Akin to ram ack + // always @(posedge clk) + // ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS; + + always @(posedge clk) begin + if (!resetn) begin + adc0_ena <= 0; + adc0_convert <= 0; + adc0_clksrc <= 0; + adc0_inputsrc <= 0; + adc1_ena <= 0; + adc1_convert <= 0; + adc1_clksrc <= 0; + adc1_inputsrc <= 0; + dac_ena <= 0; + dac_value <= 0; + comp_ena <= 0; + comp_ninputsrc <= 0; + comp_pinputsrc <= 0; + comp_output_dest <= 0; + analog_out_sel <= 0; + opamp_ena <= 0; + opamp_bias_ena <= 0; + bg_ena <= 0; + end else begin + // iomem_ready <= 0; + // if (iomem_valid && !iomem_ready && iomem_addr[31:8] == 24'h030000) begin + // iomem_ready <= 1; + // end else if (iomem_addr[7:0] == 8'hc0) begin + // iomem_rdata <= {31'd0, analog_out_sel}; + // if (iomem_wstrb[0]) analog_out_sel <= iomem_wdata[0]; + // end else if (iomem_addr[7:0] == 8'hc4) begin + // iomem_rdata <= {31'd0, opamp_bias_ena}; + // if (iomem_wstrb[0]) opamp_bias_ena <= iomem_wdata[0]; + // end else if (iomem_addr[7:0] == 8'hc8) begin + // iomem_rdata <= {31'd0, opamp_ena}; + // if (iomem_wstrb[0]) opamp_ena <= iomem_wdata[0]; + // end else if (iomem_addr[7:0] == 8'hd0) begin + // iomem_rdata <= {31'd0, bg_ena}; + // if (iomem_wstrb[0]) bg_ena <= iomem_wdata[0]; + // end + end + end + +endmodule + + +/* Convert the standard set of GPIO signals: input, output, output_enb, + * pullup, and pulldown into the set needed by the s8 GPIO pads: + * input, output, output_enb, input_enb, mode. Note that dm[2] on + * thepads is always equal to dm[1] in this setup, so mode is shown as + * only a 2-bit signal. + * + * This module is bit-sliced. Instantiate once for each GPIO pad. + */ + +module convert_gpio_sigs ( + input gpio_out, + input gpio_outenb, + input gpio_pu, + input gpio_pd, + output gpio_out_pad, + output gpio_outenb_pad, + output gpio_inenb_pad, + output gpio_mode1_pad, + output gpio_mode0_pad +); + + assign gpio_out_pad = (gpio_pu == 1'b0 && gpio_pd == 1'b0) ? gpio_out : + (gpio_pu == 1'b1) ? 1 : 0; + + assign gpio_outenb_pad = (gpio_outenb == 1'b0) ? 0 : + (gpio_pu == 1'b1 || gpio_pd == 1'b1) ? 0 : 1; + + assign gpio_inenb_pad = ~gpio_outenb; + + assign gpio_mode1_pad = ~gpio_outenb_pad; + assign gpio_mode0_pad = gpio_outenb; + +endmodule + +// Implementation note: +// Replace the following two modules with wrappers for your SRAM cells. +module openstriVe_soc_regs ( + input clk, wen, + input [5:0] waddr, + input [5:0] raddr1, + input [5:0] raddr2, + input [31:0] wdata, + output [31:0] rdata1, + output [31:0] rdata2 +); + reg [31:0] regs [0:31]; + + always @(posedge clk) + if (wen) regs[waddr[4:0]] <= wdata; + + assign rdata1 = regs[raddr1[4:0]]; + assign rdata2 = regs[raddr2[4:0]]; +endmodule
diff --git a/verilog/rtl/picorv32.v b/verilog/rtl/picorv32.v index af634b4..cbbbb60 100644 --- a/verilog/rtl/picorv32.v +++ b/verilog/rtl/picorv32.v
@@ -17,6 +17,11 @@ * */ +/* verilator lint_off WIDTH */ +/* verilator lint_off PINMISSING */ +/* verilator lint_off CASEOVERLAP */ +/* verilator lint_off CASEINCOMPLETE */ + `timescale 1 ns / 1 ps // `default_nettype none // `define DEBUGNETS @@ -122,6 +127,8 @@ output reg rvfi_trap, output reg rvfi_halt, output reg rvfi_intr, + output reg [ 1:0] rvfi_mode, + output reg [ 1:0] rvfi_ixl, output reg [ 4:0] rvfi_rs1_addr, output reg [ 4:0] rvfi_rs2_addr, output reg [31:0] rvfi_rs1_rdata, @@ -135,6 +142,16 @@ output reg [ 3:0] rvfi_mem_wmask, output reg [31:0] rvfi_mem_rdata, output reg [31:0] rvfi_mem_wdata, + + output reg [63:0] rvfi_csr_mcycle_rmask, + output reg [63:0] rvfi_csr_mcycle_wmask, + output reg [63:0] rvfi_csr_mcycle_rdata, + output reg [63:0] rvfi_csr_mcycle_wdata, + + output reg [63:0] rvfi_csr_minstret_rmask, + output reg [63:0] rvfi_csr_minstret_wmask, + output reg [63:0] rvfi_csr_minstret_rdata, + output reg [63:0] rvfi_csr_minstret_wdata, `endif // Trace Interface @@ -636,7 +653,7 @@ wire instr_trap; reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2; - reg [31:0] decoded_imm, decoded_imm_uj; + reg [31:0] decoded_imm, decoded_imm_j; reg decoder_trigger; reg decoder_trigger_q; reg decoder_pseudo_trigger; @@ -858,7 +875,7 @@ is_alu_reg_imm <= mem_rdata_latched[6:0] == 7'b0010011; is_alu_reg_reg <= mem_rdata_latched[6:0] == 7'b0110011; - { decoded_imm_uj[31:20], decoded_imm_uj[10:1], decoded_imm_uj[11], decoded_imm_uj[19:12], decoded_imm_uj[0] } <= $signed({mem_rdata_latched[31:12], 1'b0}); + { decoded_imm_j[31:20], decoded_imm_j[10:1], decoded_imm_j[11], decoded_imm_j[19:12], decoded_imm_j[0] } <= $signed({mem_rdata_latched[31:12], 1'b0}); decoded_rd <= mem_rdata_latched[11:7]; decoded_rs1 <= mem_rdata_latched[19:15]; @@ -877,8 +894,8 @@ decoded_rs1 <= 0; decoded_rs2 <= 0; - { decoded_imm_uj[31:11], decoded_imm_uj[4], decoded_imm_uj[9:8], decoded_imm_uj[10], decoded_imm_uj[6], - decoded_imm_uj[7], decoded_imm_uj[3:1], decoded_imm_uj[5], decoded_imm_uj[0] } <= $signed({mem_rdata_latched[12:2], 1'b0}); + { decoded_imm_j[31:11], decoded_imm_j[4], decoded_imm_j[9:8], decoded_imm_j[10], decoded_imm_j[6], + decoded_imm_j[7], decoded_imm_j[3:1], decoded_imm_j[5], decoded_imm_j[0] } <= $signed({mem_rdata_latched[12:2], 1'b0}); case (mem_rdata_latched[1:0]) 2'b00: begin // Quadrant 0 @@ -1099,7 +1116,7 @@ (* parallel_case *) case (1'b1) instr_jal: - decoded_imm <= decoded_imm_uj; + decoded_imm <= decoded_imm_j; |{instr_lui, instr_auipc}: decoded_imm <= mem_rdata_q[31:12] << 12; |{instr_jalr, is_lb_lh_lw_lbu_lhu, is_alu_reg_imm}: @@ -1314,7 +1331,13 @@ `ifndef PICORV32_REGS always @(posedge clk) begin if (resetn && cpuregs_write && latched_rd) +`ifdef PICORV32_TESTBUG_001 + cpuregs[latched_rd ^ 1] <= cpuregs_wrdata; +`elsif PICORV32_TESTBUG_002 + cpuregs[latched_rd] <= cpuregs_wrdata ^ 1; +`else cpuregs[latched_rd] <= cpuregs_wrdata; +`endif end always @* begin @@ -1412,15 +1435,9 @@ next_irq_pending = ENABLE_IRQ ? irq_pending & LATCHED_IRQ : 'bx; if (ENABLE_IRQ && ENABLE_IRQ_TIMER && timer) begin - if (timer - 1 == 0) - next_irq_pending[irq_timer] = 1; timer <= timer - 1; end - if (ENABLE_IRQ) begin - next_irq_pending = next_irq_pending | irq; - end - decoder_trigger <= mem_do_rinst && mem_done; decoder_trigger_q <= decoder_trigger; decoder_pseudo_trigger <= 0; @@ -1544,7 +1561,7 @@ end if (instr_jal) begin mem_do_rinst <= 1; - reg_next_pc <= current_pc + decoded_imm_uj; + reg_next_pc <= current_pc + decoded_imm_j; latched_branch <= 1; end else begin mem_do_rinst <= 0; @@ -1890,6 +1907,13 @@ end endcase + if (ENABLE_IRQ) begin + next_irq_pending = next_irq_pending | irq; + if(ENABLE_IRQ_TIMER && timer) + if (timer - 1 == 0) + next_irq_pending[irq_timer] = 1; + end + if (CATCH_MISALIGN && resetn && (mem_do_rdata || mem_do_wdata)) begin if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin `debug($display("MISALIGNED WORD: 0x%08x", reg_op1);) @@ -1962,6 +1986,8 @@ rvfi_trap <= trap; rvfi_halt <= trap; rvfi_intr <= dbg_irq_enter; + rvfi_mode <= 3; + rvfi_ixl <= 1; if (!resetn) begin dbg_irq_call <= 0; @@ -1981,8 +2007,16 @@ rvfi_rd_wdata <= 0; end else if (cpuregs_write && !irq_state) begin +`ifdef PICORV32_TESTBUG_003 + rvfi_rd_addr <= latched_rd ^ 1; +`else rvfi_rd_addr <= latched_rd; +`endif +`ifdef PICORV32_TESTBUG_004 + rvfi_rd_wdata <= latched_rd ? cpuregs_wrdata ^ 1 : 0; +`else rvfi_rd_wdata <= latched_rd ? cpuregs_wrdata : 0; +`endif end else if (rvfi_valid) begin rvfi_rd_addr <= 0; @@ -2023,7 +2057,40 @@ end always @* begin +`ifdef PICORV32_TESTBUG_005 + rvfi_pc_wdata = (dbg_irq_call ? dbg_irq_ret : dbg_insn_addr) ^ 4; +`else rvfi_pc_wdata = dbg_irq_call ? dbg_irq_ret : dbg_insn_addr; +`endif + + rvfi_csr_mcycle_rmask = 0; + rvfi_csr_mcycle_wmask = 0; + rvfi_csr_mcycle_rdata = 0; + rvfi_csr_mcycle_wdata = 0; + + rvfi_csr_minstret_rmask = 0; + rvfi_csr_minstret_wmask = 0; + rvfi_csr_minstret_rdata = 0; + rvfi_csr_minstret_wdata = 0; + + if (rvfi_valid && rvfi_insn[6:0] == 7'b 1110011 && rvfi_insn[13:12] == 3'b010) begin + if (rvfi_insn[31:20] == 12'h C00) begin + rvfi_csr_mcycle_rmask = 64'h 0000_0000_FFFF_FFFF; + rvfi_csr_mcycle_rdata = {32'h 0000_0000, rvfi_rd_wdata}; + end + if (rvfi_insn[31:20] == 12'h C80) begin + rvfi_csr_mcycle_rmask = 64'h FFFF_FFFF_0000_0000; + rvfi_csr_mcycle_rdata = {rvfi_rd_wdata, 32'h 0000_0000}; + end + if (rvfi_insn[31:20] == 12'h C02) begin + rvfi_csr_minstret_rmask = 64'h 0000_0000_FFFF_FFFF; + rvfi_csr_minstret_rdata = {32'h 0000_0000, rvfi_rd_wdata}; + end + if (rvfi_insn[31:20] == 12'h C82) begin + rvfi_csr_minstret_rmask = 64'h FFFF_FFFF_0000_0000; + rvfi_csr_minstret_rdata = {rvfi_rd_wdata, 32'h 0000_0000}; + end + end end `endif @@ -2913,7 +2980,7 @@ .trace_valid(trace_valid), .trace_data (trace_data) ); - + // Wishbone Controller localparam IDLE = 2'b00; localparam WBSTART = 2'b01; localparam WBEND = 2'b10;
diff --git a/verilog/rtl/ring_osc2x13.v b/verilog/rtl/ring_osc2x13.v index 4363c00..58a01af 100644 --- a/verilog/rtl/ring_osc2x13.v +++ b/verilog/rtl/ring_osc2x13.v
@@ -10,40 +10,40 @@ wire d0, d1, d2; - sky130_fd_sc_hd__clkbuf_2 delaybuf0 ( + scs8hd_clkbuf_2 delaybuf0 ( .A(in), .X(ts) ); - sky130_fd_sc_hd__clkbuf_1 delaybuf1 ( + scs8hd_clkbuf_1 delaybuf1 ( .A(ts), .X(d0) ); - sky130_fd_sc_hd__einvp_2 delayen1 ( + scs8hd_einvp_2 delayen1 ( .A(d0), .TE(trim[1]), .Z(d1) ); - sky130_fd_sc_hd__einvn_4 delayenb1 ( + scs8hd_einvn_4 delayenb1 ( .A(ts), .TEB(trim[1]), .Z(d1) ); - sky130_fd_sc_hd__clkinv_1 delayint0 ( + scs8hd_clkinv_1 delayint0 ( .A(d1), .Y(d2) ); - sky130_fd_sc_hd__einvp_2 delayen0 ( + scs8hd_einvp_2 delayen0 ( .A(d2), .TE(trim[0]), .Z(out) ); - sky130_fd_sc_hd__einvn_8 delayenb0 ( + scs8hd_einvn_8 delayenb0 ( .A(ts), .TEB(trim[0]), .Z(out) @@ -59,53 +59,53 @@ wire d0, d1, d2, ctrl0, one; - sky130_fd_sc_hd__clkbuf_1 delaybuf0 ( + scs8hd_clkbuf_1 delaybuf0 ( .A(in), .X(d0) ); - sky130_fd_sc_hd__einvp_2 delayen1 ( + scs8hd_einvp_2 delayen1 ( .A(d0), .TE(trim[1]), .Z(d1) ); - sky130_fd_sc_hd__einvn_4 delayenb1 ( + scs8hd_einvn_4 delayenb1 ( .A(in), .TEB(trim[1]), .Z(d1) ); - sky130_fd_sc_hd__clkinv_1 delayint0 ( + scs8hd_clkinv_1 delayint0 ( .A(d1), .Y(d2) ); - sky130_fd_sc_hd__einvp_2 delayen0 ( + scs8hd_einvp_2 delayen0 ( .A(d2), .TE(trim[0]), .Z(out) ); - sky130_fd_sc_hd__einvn_8 delayenb0 ( + scs8hd_einvn_8 delayenb0 ( .A(in), .TEB(ctrl0), .Z(out) ); - sky130_fd_sc_hd__einvp_1 reseten0 ( + scs8hd_einvp_1 reseten0 ( .A(one), .TE(reset), .Z(out) ); - sky130_fd_sc_hd__or2_2 ctrlen0 ( + scs8hd_or2_2 ctrlen0 ( .A(reset), .B(trim[0]), .X(ctrl0) ); - sky130_fd_sc_hd__conb_1 const1 ( + scs8hd_conb_1 const1 ( .HI(one), .LO() ); @@ -159,19 +159,19 @@ // Buffered outputs a 0 and 90 degrees phase (approximately) - sky130_fd_sc_hd__clkinv_2 ibufp00 ( + scs8hd_clkinv_2 ibufp00 ( .A(d[0]), .Y(c[0]) ); - sky130_fd_sc_hd__clkinv_8 ibufp01 ( + scs8hd_clkinv_8 ibufp01 ( .A(c[0]), .Y(clockp[0]) ); - sky130_fd_sc_hd__clkinv_2 ibufp10 ( + scs8hd_clkinv_2 ibufp10 ( .A(d[6]), .Y(c[1]) ); - sky130_fd_sc_hd__clkinv_8 ibufp11 ( + scs8hd_clkinv_8 ibufp11 ( .A(c[1]), .Y(clockp[1]) );
diff --git a/verilog/rtl/simpleuart.v b/verilog/rtl/simpleuart.v index 50808cb..51e95c7 100644 --- a/verilog/rtl/simpleuart.v +++ b/verilog/rtl/simpleuart.v
@@ -17,121 +17,180 @@ * */ -module simpleuart ( - input clk, - input resetn, +module simpleuart_wb # ( + parameter BASE_ADR = 32'h 2000_0000, + parameter CLK_DIV = 8'h00, + parameter DATA = 8'h04 +) ( + input wb_clk_i, + input wb_rst_i, - output ser_tx, - input ser_rx, + input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?) + input [31:0] wb_dat_i, + input [3:0] wb_sel_i, + input wb_we_i, + input wb_cyc_i, + input wb_stb_i, - input [3:0] reg_div_we, - input [31:0] reg_div_di, - output [31:0] reg_div_do, + output wb_ack_o, + output [31:0] wb_dat_o, - input reg_dat_we, - input reg_dat_re, - input [31:0] reg_dat_di, - output [31:0] reg_dat_do, - output reg_dat_wait + output ser_tx, + input ser_rx + ); - reg [31:0] cfg_divider; + wire [31:0] simpleuart_reg_div_do; + wire [31:0] simpleuart_reg_dat_do; - reg [3:0] recv_state; - reg [31:0] recv_divcnt; - reg [7:0] recv_pattern; - reg [7:0] recv_buf_data; - reg recv_buf_valid; + wire resetn = ~wb_rst_i; + wire valid = wb_stb_i && wb_cyc_i; + wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV)); + wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA)); - reg [9:0] send_pattern; - reg [3:0] send_bitcnt; - reg [31:0] send_divcnt; - reg send_dummy; + wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; // simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000), // sel: depends on address buss + wire reg_dat_we = simpleuart_reg_dat_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; // simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0 - assign reg_div_do = cfg_divider; + wire [31:0] mem_wdata = wb_dat_i; + wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable - assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy); - assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0; + assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do: simpleuart_reg_dat_do; + assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel) && (!reg_dat_wait); + + simpleuart simpleuart ( + .clk (wb_clk_i), + .resetn (resetn), - always @(posedge clk) begin - if (!resetn) begin - cfg_divider <= 1; - end else begin - if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0]; - if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8]; - if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16]; - if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24]; - end - end + .ser_tx (ser_tx), + .ser_rx (ser_rx), - always @(posedge clk) begin - if (!resetn) begin - recv_state <= 0; - recv_divcnt <= 0; - recv_pattern <= 0; - recv_buf_data <= 0; - recv_buf_valid <= 0; - end else begin - recv_divcnt <= recv_divcnt + 1; - if (reg_dat_re) - recv_buf_valid <= 0; - case (recv_state) - 0: begin - if (!ser_rx) - recv_state <= 1; - recv_divcnt <= 0; - end - 1: begin - if (2*recv_divcnt > cfg_divider) begin - recv_state <= 2; - recv_divcnt <= 0; - end - end - 10: begin - if (recv_divcnt > cfg_divider) begin - recv_buf_data <= recv_pattern; - recv_buf_valid <= 1; - recv_state <= 0; - end - end - default: begin - if (recv_divcnt > cfg_divider) begin - recv_pattern <= {ser_rx, recv_pattern[7:1]}; - recv_state <= recv_state + 1; - recv_divcnt <= 0; - end - end - endcase - end - end + .reg_div_we (reg_div_we), + .reg_div_di (mem_wdata), + .reg_div_do (simpleuart_reg_div_do), - assign ser_tx = send_pattern[0]; + .reg_dat_we (reg_dat_we), + .reg_dat_re (reg_dat_re), + .reg_dat_di (mem_wdata), + .reg_dat_do (simpleuart_reg_dat_do), + .reg_dat_wait(reg_dat_wait) + ); - always @(posedge clk) begin - if (reg_div_we) - send_dummy <= 1; - send_divcnt <= send_divcnt + 1; - if (!resetn) begin - send_pattern <= ~0; - send_bitcnt <= 0; - send_divcnt <= 0; - send_dummy <= 1; - end else begin - if (send_dummy && !send_bitcnt) begin - send_pattern <= ~0; - send_bitcnt <= 15; - send_divcnt <= 0; - send_dummy <= 0; - end else - if (reg_dat_we && !send_bitcnt) begin - send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0}; - send_bitcnt <= 10; - send_divcnt <= 0; - end else - if (send_divcnt > cfg_divider && send_bitcnt) begin - send_pattern <= {1'b1, send_pattern[9:1]}; - send_bitcnt <= send_bitcnt - 1; - send_divcnt <= 0; - end - end - end +endmodule + +module simpleuart ( + input clk, + input resetn, + + output ser_tx, + input ser_rx, + + input [3:0] reg_div_we, + input [31:0] reg_div_di, + output [31:0] reg_div_do, + + input reg_dat_we, + input reg_dat_re, + input [31:0] reg_dat_di, + output [31:0] reg_dat_do, + output reg_dat_wait +); + reg [31:0] cfg_divider; + + reg [3:0] recv_state; + reg [31:0] recv_divcnt; + reg [7:0] recv_pattern; + reg [7:0] recv_buf_data; + reg recv_buf_valid; + + reg [9:0] send_pattern; + reg [3:0] send_bitcnt; + reg [31:0] send_divcnt; + reg send_dummy; + + assign reg_div_do = cfg_divider; + + assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy); + assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0; + + always @(posedge clk) begin + if (!resetn) begin + cfg_divider <= 1; + end else begin + if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0]; + if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8]; + if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16]; + if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24]; + end + end + + always @(posedge clk) begin + if (!resetn) begin + recv_state <= 0; + recv_divcnt <= 0; + recv_pattern <= 0; + recv_buf_data <= 0; + recv_buf_valid <= 0; + end else begin + recv_divcnt <= recv_divcnt + 1; + if (reg_dat_re) + recv_buf_valid <= 0; + case (recv_state) + 0: begin + if (!ser_rx) + recv_state <= 1; + recv_divcnt <= 0; + end + 1: begin + if (2*recv_divcnt > cfg_divider) begin + recv_state <= 2; + recv_divcnt <= 0; + end + end + 10: begin + if (recv_divcnt > cfg_divider) begin + recv_buf_data <= recv_pattern; + recv_buf_valid <= 1; + recv_state <= 0; + end + end + default: begin + if (recv_divcnt > cfg_divider) begin + recv_pattern <= {ser_rx, recv_pattern[7:1]}; + recv_state <= recv_state + 1; + recv_divcnt <= 0; + end + end + endcase + end + end + + assign ser_tx = send_pattern[0]; + + always @(posedge clk) begin + if (reg_div_we) + send_dummy <= 1; + send_divcnt <= send_divcnt + 1; + if (!resetn) begin + send_pattern <= ~0; + send_bitcnt <= 0; + send_divcnt <= 0; + send_dummy <= 1; + end else begin + if (send_dummy && !send_bitcnt) begin + send_pattern <= ~0; + send_bitcnt <= 15; + send_divcnt <= 0; + send_dummy <= 0; + end else + if (reg_dat_we && !send_bitcnt) begin + send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0}; + send_bitcnt <= 10; + send_divcnt <= 0; + end else + if (send_divcnt > cfg_divider && send_bitcnt) begin + send_pattern <= {1'b1, send_pattern[9:1]}; + send_bitcnt <= send_bitcnt - 1; + send_divcnt <= 0; + end + end + end endmodule
diff --git a/verilog/rtl/spi_slave.v b/verilog/rtl/spi_slave.v index 50a6520..16a1923 100644 --- a/verilog/rtl/spi_slave.v +++ b/verilog/rtl/spi_slave.v
@@ -83,97 +83,97 @@ // Readback data is captured on the falling edge of SCK so that // it is guaranteed valid at the next rising edge. always @(negedge SCK or posedge CSB) begin - if (CSB == 1'b1) begin - wrstb <= 1'b0; - ldata <= 8'b00000000; - sdoenb <= 1'b1; + if (CSB == 1'b1) begin + wrstb <= 1'b0; + ldata <= 8'b00000000; + sdoenb <= 1'b1; end else begin - // After CSB low, 1st SCK starts command + // After CSB low, 1st SCK starts command - if (state == `DATA) begin - if (readmode == 1'b1) begin - sdoenb <= 1'b0; - if (count == 3'b000) begin - ldata <= idata; - end else begin - ldata <= {ldata[6:0], 1'b0}; // Shift out - end - end else begin - sdoenb <= 1'b1; - end + if (state == `DATA) begin + if (readmode == 1'b1) begin + sdoenb <= 1'b0; + if (count == 3'b000) begin + ldata <= idata; + end else begin + ldata <= {ldata[6:0], 1'b0}; // Shift out + end + end else begin + sdoenb <= 1'b1; + end - // Apply write strobe on SCK negative edge on the next-to-last - // data bit so that it updates data on the rising edge of SCK - // on the last data bit. + // Apply write strobe on SCK negative edge on the next-to-last + // data bit so that it updates data on the rising edge of SCK + // on the last data bit. - if (count == 3'b111) begin - if (writemode == 1'b1) begin - wrstb <= 1'b1; - end - end else begin - wrstb <= 1'b0; - end - end else begin - wrstb <= 1'b0; - sdoenb <= 1'b1; - end // ! state `DATA - end // ! CSB + if (count == 3'b111) begin + if (writemode == 1'b1) begin + wrstb <= 1'b1; + end + end else begin + wrstb <= 1'b0; + end + end else begin + wrstb <= 1'b0; + sdoenb <= 1'b1; + end // ! state `DATA + end // ! CSB end // always @ ~SCK always @(posedge SCK or posedge CSB) begin - if (CSB == 1'b1) begin - // Default state on reset - addr <= 8'h00; - rdstb <= 1'b0; - predata <= 7'b0000000; - state <= `COMMAND; - count <= 3'b000; - readmode <= 1'b0; - writemode <= 1'b0; - fixed <= 3'b000; + if (CSB == 1'b1) begin + // Default state on reset + addr <= 8'h00; + rdstb <= 1'b0; + predata <= 7'b0000000; + state <= `COMMAND; + count <= 3'b000; + readmode <= 1'b0; + writemode <= 1'b0; + fixed <= 3'b000; end else begin - // After CSB low, 1st SCK starts command - if (state == `COMMAND) begin - rdstb <= 1'b0; - count <= count + 1; - if (count == 3'b000) begin - writemode <= SDI; - end else if (count == 3'b001) begin - readmode <= SDI; - end else if (count < 3'b101) begin - fixed <= {fixed[1:0], SDI}; - end else if (count == 3'b111) begin - state <= `ADDRESS; - end - end else if (state == `ADDRESS) begin - count <= count + 1; - addr <= {addr[6:0], SDI}; - if (count == 3'b111) begin - if (readmode == 1'b1) begin - rdstb <= 1'b1; - end - state <= `DATA; - end else begin - rdstb <= 1'b0; - end - end else if (state == `DATA) begin - predata <= {predata[6:0], SDI}; - count <= count + 1; - if (count == 3'b111) begin - if (fixed == 3'b001) begin - state <= `COMMAND; - end else if (fixed != 3'b000) begin - fixed <= fixed - 1; - addr <= addr + 1; // Auto increment address (fixed) - end else begin - addr <= addr + 1; // Auto increment address (streaming) - end - end else begin - rdstb <= 1'b0; - end - end // ! state `DATA - end // ! CSB + // After CSB low, 1st SCK starts command + if (state == `COMMAND) begin + rdstb <= 1'b0; + count <= count + 1; + if (count == 3'b000) begin + writemode <= SDI; + end else if (count == 3'b001) begin + readmode <= SDI; + end else if (count < 3'b101) begin + fixed <= {fixed[1:0], SDI}; + end else if (count == 3'b111) begin + state <= `ADDRESS; + end + end else if (state == `ADDRESS) begin + count <= count + 1; + addr <= {addr[6:0], SDI}; + if (count == 3'b111) begin + if (readmode == 1'b1) begin + rdstb <= 1'b1; + end + state <= `DATA; + end else begin + rdstb <= 1'b0; + end + end else if (state == `DATA) begin + predata <= {predata[6:0], SDI}; + count <= count + 1; + if (count == 3'b111) begin + if (fixed == 3'b001) begin + state <= `COMMAND; + end else if (fixed != 3'b000) begin + fixed <= fixed - 1; + addr <= addr + 1; // Auto increment address (fixed) + end else begin + addr <= addr + 1; // Auto increment address (streaming) + end + end else begin + rdstb <= 1'b0; + end + end // ! state `DATA + end // ! CSB end // always @ SCK endmodule // spi_slave
diff --git a/verilog/rtl/spi_sysctrl.v b/verilog/rtl/spi_sysctrl.v new file mode 100644 index 0000000..7a34a7f --- /dev/null +++ b/verilog/rtl/spi_sysctrl.v
@@ -0,0 +1,182 @@ +module spi_sysctrl_wb #( + parameter BASE_ADR = 32'h2E00_0000, + parameter SPI_CFG = 8'h00, + parameter SPI_ENA = 8'h04, + parameter SPI_PLL_CFG = 8'h08, + parameter SPI_MFGR_ID = 8'h0c, + parameter SPI_PROD_ID = 8'h10, + parameter SPI_MASK_REV = 8'h14, + parameter SPI_PLL_BYPASS = 8'h18 +) ( + input wb_clk_i, + input wb_rst_i, + + input [31:0] wb_dat_i, + input [31:0] wb_adr_i, + input [3:0] wb_sel_i, + input wb_cyc_i, + input wb_stb_i, + input wb_we_i, + + output [31:0] wb_dat_o, + output wb_ack_o, + + // Read-Only HKSPI Registers + input [7:0] spi_ro_config, // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + + input [4:0] spi_ro_pll_div, + input [2:0] spi_ro_pll_sel, + input spi_ro_xtal_ena, + input spi_ro_reg_ena, + + input [25:0] spi_ro_pll_trim, + input spi_ro_pll_dco_ena, + + input [11:0] spi_ro_mfgr_id, + input [7:0] spi_ro_prod_id, + input [3:0] spi_ro_mask_rev, + input pll_bypass +); + + wire resetn; + wire valid; + wire ready; + wire [3:0] iomem_we; + + assign resetn = ~wb_rst_i; + assign valid = wb_stb_i && wb_cyc_i; + + assign iomem_we = wb_sel_i & {4{wb_we_i}}; + assign wb_ack_o = ready; + + spi_sysctrl #( + .BASE_ADR(BASE_ADR), + .SPI_CFG(SPI_CFG), + .SPI_ENA(SPI_ENA), + .SPI_PLL_CFG(SPI_PLL_CFG), + .SPI_MFGR_ID(SPI_MFGR_ID), + .SPI_PROD_ID(SPI_PROD_ID), + .SPI_MASK_REV(SPI_MASK_REV), + .SPI_PLL_BYPASS(SPI_PLL_BYPASS) + ) spi_sysctrl ( + .clk(wb_clk_i), + .resetn(resetn), + + .iomem_addr(wb_adr_i), + .iomem_valid(valid), + .iomem_wstrb(iomem_we), + .iomem_wdata(wb_dat_i), + .iomem_rdata(wb_dat_o), + .iomem_ready(ready), + + .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + .spi_ro_pll_div(spi_ro_pll_div), + .spi_ro_pll_sel(spi_ro_pll_sel), + .spi_ro_xtal_ena(spi_ro_xtal_ena), + .spi_ro_reg_ena(spi_ro_reg_ena), + + .spi_ro_pll_trim(spi_ro_pll_trim), + .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena), + + .spi_ro_mfgr_id(spi_ro_mfgr_id), + .spi_ro_prod_id(spi_ro_prod_id), + .spi_ro_mask_rev(spi_ro_mask_rev), + .pll_bypass(pll_bypass) + ); + +endmodule + +module spi_sysctrl #( + parameter BASE_ADR = 32'h2300_0000, + parameter SPI_CFG = 8'h00, + parameter SPI_ENA = 8'h04, + parameter SPI_PLL_CFG = 8'h08, + parameter SPI_MFGR_ID = 8'h0c, + parameter SPI_PROD_ID = 8'h10, + parameter SPI_MASK_REV = 8'h14, + parameter SPI_PLL_BYPASS = 8'h18 +) ( + input clk, + input resetn, + + input [31:0] iomem_addr, + input iomem_valid, + input [3:0] iomem_wstrb, + input [31:0] iomem_wdata, + output reg [31:0] iomem_rdata, + output reg iomem_ready, + + input [7:0] spi_ro_config, // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + + input [4:0] spi_ro_pll_div, + input [2:0] spi_ro_pll_sel, + input spi_ro_xtal_ena, + input spi_ro_reg_ena, + + input [25:0] spi_ro_pll_trim, + input spi_ro_pll_dco_ena, + + input [11:0] spi_ro_mfgr_id, + input [7:0] spi_ro_prod_id, + input [3:0] spi_ro_mask_rev, + input pll_bypass +); + // Read-only Registers + + wire spi_cfg_sel; + wire spi_ena_sel; + wire pll_cfg_sel; + wire spi_mfgr_sel; + wire spi_prod_sel; + wire spi_maskrev_sel; + wire pll_bypass_sel; + + + assign spi_cfg_sel = (iomem_addr[7:0] == SPI_CFG); + assign spi_ena_sel = (iomem_addr[7:0] == SPI_ENA); + assign pll_cfg_sel = (iomem_addr[7:0] == SPI_PLL_CFG); + assign spi_mfgr_sel = (iomem_addr[7:0] == SPI_MFGR_ID); + assign spi_prod_sel = (iomem_addr[7:0] == SPI_PROD_ID); + + assign spi_maskrev_sel = (iomem_addr[7:0] == SPI_MASK_REV); + assign pll_bypass_sel = (iomem_addr[7:0] == SPI_PLL_BYPASS); + + always @(posedge clk) begin + iomem_ready <= 0; + if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin + iomem_ready <= 1; + if (spi_cfg_sel) begin + iomem_rdata <= {24'd0, spi_ro_config}; + + end else if (spi_ena_sel) begin + iomem_rdata <= { + 22'd0, + spi_ro_pll_div, + spi_ro_pll_sel, + spi_ro_xtal_ena, + spi_ro_reg_ena + }; + + end else if (pll_cfg_sel) begin + iomem_rdata <= { + 5'd0, + spi_ro_pll_trim, + spi_ro_pll_dco_ena + }; + + end else if (spi_mfgr_sel) begin + iomem_rdata <= {20'd0, spi_ro_mfgr_id}; + + end else if (spi_prod_sel) begin + iomem_rdata <= {24'd0, spi_ro_prod_id}; + + end else if (spi_maskrev_sel) begin + iomem_rdata <= {28'd0, spi_ro_mask_rev}; + + end else if (pll_bypass_sel) begin + iomem_rdata <= {31'd0, pll_bypass}; + end + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/spimemio.v b/verilog/rtl/spimemio.v index f5cc5c0..053aa61 100644 --- a/verilog/rtl/spimemio.v +++ b/verilog/rtl/spimemio.v
@@ -17,585 +17,700 @@ * */ -module spimemio ( - input clk, resetn, +module spimemio_wb ( + input wb_clk_i, + input wb_rst_i, - input valid, - output ready, - input [23:0] addr, - output reg [31:0] rdata, + input [31:0] wb_adr_i, + input [31:0] wb_dat_i, + input [3:0] wb_sel_i, + input wb_we_i, + input wb_cyc_i, - output flash_csb, - output flash_clk, + input wb_flash_stb_i, + input wb_cfg_stb_i, - output flash_csb_oeb, - output flash_clk_oeb, + output wb_flash_ack_o, + output wb_cfg_ack_o, - output flash_io0_oeb, - output flash_io1_oeb, - output flash_io2_oeb, - output flash_io3_oeb, + output [31:0] wb_flash_dat_o, + output [31:0] wb_cfg_dat_o, - output flash_csb_ieb, - output flash_clk_ieb, + output flash_csb, + output flash_clk, - output flash_io0_ieb, - output flash_io1_ieb, - output flash_io2_ieb, - output flash_io3_ieb, + output flash_csb_oeb, + output flash_clk_oeb, - output flash_io0_do, - output flash_io1_do, - output flash_io2_do, - output flash_io3_do, + output flash_io0_oeb, + output flash_io1_oeb, + output flash_io2_oeb, + output flash_io3_oeb, - input flash_io0_di, - input flash_io1_di, - input flash_io2_di, - input flash_io3_di, + output flash_csb_ieb, + output flash_clk_ieb, - input [3:0] cfgreg_we, - input [31:0] cfgreg_di, - output [31:0] cfgreg_do + output flash_io0_ieb, + output flash_io1_ieb, + output flash_io2_ieb, + output flash_io3_ieb, + + output flash_io0_do, + output flash_io1_do, + output flash_io2_do, + output flash_io3_do, + + input flash_io0_di, + input flash_io1_di, + input flash_io2_di, + input flash_io3_di + ); - reg xfer_resetn; - reg din_valid; - wire din_ready; - reg [7:0] din_data; - reg [3:0] din_tag; - reg din_cont; - reg din_qspi; - reg din_ddr; - reg din_rd; + wire spimem_ready; + wire [23:0] mem_addr; + wire [31:0] spimem_rdata; + wire [31:0] spimemio_cfgreg_do; + wire [3:0] cfgreg_we; + wire spimemio_cfgreg_sel; + wire valid; + wire resetn; - wire dout_valid; - wire [7:0] dout_data; - wire [3:0] dout_tag; + assign resetn = ~wb_rst_i; + assign valid = wb_cyc_i && wb_flash_stb_i; + assign wb_flash_ack_o = spimem_ready; + assign wb_cfg_ack_o = spimemio_cfgreg_sel; - reg [23:0] buffer; + assign mem_addr = wb_adr_i[23:0]; + assign spimemio_cfgreg_sel = wb_cyc_i && wb_cfg_stb_i; - reg [23:0] rd_addr; - reg rd_valid; - reg rd_wait; - reg rd_inc; + assign cfgreg_we = spimemio_cfgreg_sel ? wb_sel_i & {4{wb_we_i}} : 4'b 0000; + assign wb_flash_dat_o = spimem_rdata; + assign wb_cfg_dat_o = spimemio_cfgreg_do; - assign ready = valid && (addr == rd_addr) && rd_valid; - wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid; + spimemio spimemio ( + .clk (wb_clk_i), + .resetn (resetn), + .valid (valid), + .ready (spimem_ready), + .addr (mem_addr), + .rdata (spimem_rdata), - reg softreset; + .flash_csb (flash_csb), + .flash_clk (flash_clk), - reg config_en; // cfgreg[31] - reg config_ddr; // cfgreg[22] - reg config_qspi; // cfgreg[21] - reg config_cont; // cfgreg[20] - reg [3:0] config_dummy; // cfgreg[19:16] - reg [3:0] config_oe; // cfgreg[11:8] - reg config_csb; // cfgreg[5] - reg config_clk; // cfgref[4] - reg [3:0] config_do; // cfgreg[3:0] + .flash_csb_oeb (flash_csb_oeb), + .flash_clk_oeb (flash_clk_oeb), - assign cfgreg_do[31] = config_en; - assign cfgreg_do[30:23] = 0; - assign cfgreg_do[22] = config_ddr; - assign cfgreg_do[21] = config_qspi; - assign cfgreg_do[20] = config_cont; - assign cfgreg_do[19:16] = config_dummy; - assign cfgreg_do[15:12] = 0; - assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb}; - assign cfgreg_do[7:6] = 0; - assign cfgreg_do[5] = flash_csb; - assign cfgreg_do[4] = flash_clk; - assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; + .flash_io0_oeb (flash_io0_oeb), + .flash_io1_oeb (flash_io1_oeb), + .flash_io2_oeb (flash_io2_oeb), + .flash_io3_oeb (flash_io3_oeb), - always @(posedge clk) begin - softreset <= !config_en || cfgreg_we; - if (!resetn) begin - softreset <= 1; - config_en <= 1; - config_csb <= 0; - config_clk <= 0; - config_oe <= 0; - config_do <= 0; - config_ddr <= 0; - config_qspi <= 0; - config_cont <= 0; - config_dummy <= 8; - end else begin - if (cfgreg_we[0]) begin - config_csb <= cfgreg_di[5]; - config_clk <= cfgreg_di[4]; - config_do <= cfgreg_di[3:0]; - end - if (cfgreg_we[1]) begin - config_oe <= cfgreg_di[11:8]; - end - if (cfgreg_we[2]) begin - config_ddr <= cfgreg_di[22]; - config_qspi <= cfgreg_di[21]; - config_cont <= cfgreg_di[20]; - config_dummy <= cfgreg_di[19:16]; - end - if (cfgreg_we[3]) begin - config_en <= cfgreg_di[31]; - end - end - end + .flash_csb_ieb (flash_csb_ieb), + .flash_clk_ieb (flash_clk_ieb), - wire xfer_csb; - wire xfer_clk; + .flash_io0_ieb (flash_io0_ieb), + .flash_io1_ieb (flash_io1_ieb), + .flash_io2_ieb (flash_io2_ieb), + .flash_io3_ieb (flash_io3_ieb), - wire xfer_io0_oe; - wire xfer_io1_oe; - wire xfer_io2_oe; - wire xfer_io3_oe; + .flash_io0_do (flash_io0_do), + .flash_io1_do (flash_io1_do), + .flash_io2_do (flash_io2_do), + .flash_io3_do (flash_io3_do), - wire xfer_io0_do; - wire xfer_io1_do; - wire xfer_io2_do; - wire xfer_io3_do; + .flash_io0_di (flash_io0_di), + .flash_io1_di (flash_io1_di), + .flash_io2_di (flash_io2_di), + .flash_io3_di (flash_io3_di), - reg xfer_io0_90; - reg xfer_io1_90; - reg xfer_io2_90; - reg xfer_io3_90; + .cfgreg_we(cfgreg_we), + .cfgreg_di(wb_dat_i), + .cfgreg_do(spimemio_cfgreg_do) + ); - always @(negedge clk) begin - xfer_io0_90 <= xfer_io0_do; - xfer_io1_90 <= xfer_io1_do; - xfer_io2_90 <= xfer_io2_do; - xfer_io3_90 <= xfer_io3_do; - end +endmodule - assign flash_csb = config_en ? xfer_csb : config_csb; - assign flash_clk = config_en ? xfer_clk : config_clk; +module spimemio ( + input clk, resetn, - assign flash_csb_oeb = ~resetn; - assign flash_clk_oeb = ~resetn; + input valid, + output ready, + input [23:0] addr, + output reg [31:0] rdata, - assign flash_io0_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]); - assign flash_io1_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]); - assign flash_io2_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]); - assign flash_io3_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]); - assign flash_csb_ieb = 1'b1; /* Always disabled */ - assign flash_clk_ieb = 1'b1; /* Always disabled */ + output flash_csb, + output flash_clk, - assign flash_io0_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]); - assign flash_io1_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]); - assign flash_io2_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]); - assign flash_io3_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]); + output flash_csb_oeb, + output flash_clk_oeb, - assign flash_io0_do = config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0]; - assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1]; - assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2]; - assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3]; + output flash_io0_oeb, + output flash_io1_oeb, + output flash_io2_oeb, + output flash_io3_oeb, - wire xfer_dspi = din_ddr && !din_qspi; - wire xfer_ddr = din_ddr && din_qspi; + output flash_csb_ieb, + output flash_clk_ieb, - spimemio_xfer xfer ( - .clk (clk ), - .resetn (resetn ), - .xfer_resetn (xfer_resetn ), - .din_valid (din_valid ), - .din_ready (din_ready ), - .din_data (din_data ), - .din_tag (din_tag ), - .din_cont (din_cont ), - .din_dspi (xfer_dspi ), - .din_qspi (din_qspi ), - .din_ddr (xfer_ddr ), - .din_rd (din_rd ), - .dout_valid (dout_valid ), - .dout_data (dout_data ), - .dout_tag (dout_tag ), - .flash_csb (xfer_csb ), - .flash_clk (xfer_clk ), - .flash_io0_oe (xfer_io0_oe ), - .flash_io1_oe (xfer_io1_oe ), - .flash_io2_oe (xfer_io2_oe ), - .flash_io3_oe (xfer_io3_oe ), - .flash_io0_do (xfer_io0_do ), - .flash_io1_do (xfer_io1_do ), - .flash_io2_do (xfer_io2_do ), - .flash_io3_do (xfer_io3_do ), - .flash_io0_di (flash_io0_di), - .flash_io1_di (flash_io1_di), - .flash_io2_di (flash_io2_di), - .flash_io3_di (flash_io3_di) - ); + output flash_io0_ieb, + output flash_io1_ieb, + output flash_io2_ieb, + output flash_io3_ieb, - reg [3:0] state; + output flash_io0_do, + output flash_io1_do, + output flash_io2_do, + output flash_io3_do, - always @(posedge clk) begin - xfer_resetn <= 1; - din_valid <= 0; + input flash_io0_di, + input flash_io1_di, + input flash_io2_di, + input flash_io3_di, - if (!resetn || softreset) begin - state <= 0; - xfer_resetn <= 0; - rd_valid <= 0; - din_tag <= 0; - din_cont <= 0; - din_qspi <= 0; - din_ddr <= 0; - din_rd <= 0; - end else begin - if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data; - if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data; - if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data; - if (dout_valid && dout_tag == 4) begin - rdata <= {dout_data, buffer}; - rd_addr <= rd_inc ? rd_addr + 4 : addr; - rd_valid <= 1; - rd_wait <= rd_inc; - rd_inc <= 1; - end + input [3:0] cfgreg_we, + input [31:0] cfgreg_di, + output [31:0] cfgreg_do +); + reg xfer_resetn; + reg din_valid; + wire din_ready; + reg [7:0] din_data; + reg [3:0] din_tag; + reg din_cont; + reg din_qspi; + reg din_ddr; + reg din_rd; - if (valid) - rd_wait <= 0; + wire dout_valid; + wire [7:0] dout_data; + wire [3:0] dout_tag; - case (state) - 0: begin - din_valid <= 1; - din_data <= 8'h ff; - din_tag <= 0; - if (din_ready) begin - din_valid <= 0; - state <= 1; - end - end - 1: begin - if (dout_valid) begin - xfer_resetn <= 0; - state <= 2; - end - end - 2: begin - din_valid <= 1; - din_data <= 8'h ab; - din_tag <= 0; - if (din_ready) begin - din_valid <= 0; - state <= 3; - end - end - 3: begin - if (dout_valid) begin - xfer_resetn <= 0; - state <= 4; - end - end - 4: begin - rd_inc <= 0; - din_valid <= 1; - din_tag <= 0; - case ({config_ddr, config_qspi}) - 2'b11: din_data <= 8'h ED; - 2'b01: din_data <= 8'h EB; - 2'b10: din_data <= 8'h BB; - 2'b00: din_data <= 8'h 03; - endcase - if (din_ready) begin - din_valid <= 0; - state <= 5; - end - end - 5: begin - if (valid && !ready) begin - din_valid <= 1; - din_tag <= 0; - din_data <= addr[23:16]; - din_qspi <= config_qspi; - din_ddr <= config_ddr; - if (din_ready) begin - din_valid <= 0; - state <= 6; - end - end - end - 6: begin - din_valid <= 1; - din_tag <= 0; - din_data <= addr[15:8]; - if (din_ready) begin - din_valid <= 0; - state <= 7; - end - end - 7: begin - din_valid <= 1; - din_tag <= 0; - din_data <= addr[7:0]; - if (din_ready) begin - din_valid <= 0; - din_data <= 0; - state <= config_qspi || config_ddr ? 8 : 9; - end - end - 8: begin - din_valid <= 1; - din_tag <= 0; - din_data <= config_cont ? 8'h A5 : 8'h FF; - if (din_ready) begin - din_rd <= 1; - din_data <= config_dummy; - din_valid <= 0; - state <= 9; - end - end - 9: begin - din_valid <= 1; - din_tag <= 1; - if (din_ready) begin - din_valid <= 0; - state <= 10; - end - end - 10: begin - din_valid <= 1; - din_data <= 8'h 00; - din_tag <= 2; - if (din_ready) begin - din_valid <= 0; - state <= 11; - end - end - 11: begin - din_valid <= 1; - din_tag <= 3; - if (din_ready) begin - din_valid <= 0; - state <= 12; - end - end - 12: begin - if (!rd_wait || valid) begin - din_valid <= 1; - din_tag <= 4; - if (din_ready) begin - din_valid <= 0; - state <= 9; - end - end - end - endcase + reg [23:0] buffer; - if (jump) begin - rd_inc <= 0; - rd_valid <= 0; - xfer_resetn <= 0; - if (config_cont) begin - state <= 5; - end else begin - state <= 4; - din_qspi <= 0; - din_ddr <= 0; - end - din_rd <= 0; - end - end - end + reg [23:0] rd_addr; + reg rd_valid; + reg rd_wait; + reg rd_inc; + + assign ready = valid && (addr == rd_addr) && rd_valid; + wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid; + + reg softreset; + + reg config_en; // cfgreg[31] + reg config_ddr; // cfgreg[22] + reg config_qspi; // cfgreg[21] + reg config_cont; // cfgreg[20] + reg [3:0] config_dummy; // cfgreg[19:16] + reg [3:0] config_oe; // cfgreg[11:8] + reg config_csb; // cfgreg[5] + reg config_clk; // cfgref[4] + reg [3:0] config_do; // cfgreg[3:0] + + assign cfgreg_do[31] = config_en; + assign cfgreg_do[30:23] = 0; + assign cfgreg_do[22] = config_ddr; + assign cfgreg_do[21] = config_qspi; + assign cfgreg_do[20] = config_cont; + assign cfgreg_do[19:16] = config_dummy; + assign cfgreg_do[15:12] = 0; + assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb}; + assign cfgreg_do[7:6] = 0; + assign cfgreg_do[5] = flash_csb; + assign cfgreg_do[4] = flash_clk; + assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; + + always @(posedge clk) begin + softreset <= !config_en || cfgreg_we; + if (!resetn) begin + softreset <= 1; + config_en <= 1; + config_csb <= 0; + config_clk <= 0; + config_oe <= 0; + config_do <= 0; + config_ddr <= 0; + config_qspi <= 0; + config_cont <= 0; + config_dummy <= 8; + end else begin + if (cfgreg_we[0]) begin + config_csb <= cfgreg_di[5]; + config_clk <= cfgreg_di[4]; + config_do <= cfgreg_di[3:0]; + end + if (cfgreg_we[1]) begin + config_oe <= cfgreg_di[11:8]; + end + if (cfgreg_we[2]) begin + config_ddr <= cfgreg_di[22]; + config_qspi <= cfgreg_di[21]; + config_cont <= cfgreg_di[20]; + config_dummy <= cfgreg_di[19:16]; + end + if (cfgreg_we[3]) begin + config_en <= cfgreg_di[31]; + end + end + end + + wire xfer_csb; + wire xfer_clk; + + wire xfer_io0_oe; + wire xfer_io1_oe; + wire xfer_io2_oe; + wire xfer_io3_oe; + + wire xfer_io0_do; + wire xfer_io1_do; + wire xfer_io2_do; + wire xfer_io3_do; + + reg xfer_io0_90; + reg xfer_io1_90; + reg xfer_io2_90; + reg xfer_io3_90; + + always @(negedge clk) begin + xfer_io0_90 <= xfer_io0_do; + xfer_io1_90 <= xfer_io1_do; + xfer_io2_90 <= xfer_io2_do; + xfer_io3_90 <= xfer_io3_do; + end + + assign flash_csb = config_en ? xfer_csb : config_csb; + assign flash_clk = config_en ? xfer_clk : config_clk; + + assign flash_csb_oeb = ~resetn; + assign flash_clk_oeb = ~resetn; + + assign flash_io0_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]); + assign flash_io1_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]); + assign flash_io2_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]); + assign flash_io3_oeb = ~resetn ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]); + assign flash_csb_ieb = 1'b1; /* Always disabled */ + assign flash_clk_ieb = 1'b1; /* Always disabled */ + + assign flash_io0_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]); + assign flash_io1_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]); + assign flash_io2_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]); + assign flash_io3_ieb = ~resetn ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]); + + assign flash_io0_do = config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0]; + assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1]; + assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2]; + assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3]; + + wire xfer_dspi = din_ddr && !din_qspi; + wire xfer_ddr = din_ddr && din_qspi; + + spimemio_xfer xfer ( + .clk (clk ), + .resetn (resetn ), + .xfer_resetn (xfer_resetn ), + .din_valid (din_valid ), + .din_ready (din_ready ), + .din_data (din_data ), + .din_tag (din_tag ), + .din_cont (din_cont ), + .din_dspi (xfer_dspi ), + .din_qspi (din_qspi ), + .din_ddr (xfer_ddr ), + .din_rd (din_rd ), + .dout_valid (dout_valid ), + .dout_data (dout_data ), + .dout_tag (dout_tag ), + .flash_csb (xfer_csb ), + .flash_clk (xfer_clk ), + .flash_io0_oe (xfer_io0_oe ), + .flash_io1_oe (xfer_io1_oe ), + .flash_io2_oe (xfer_io2_oe ), + .flash_io3_oe (xfer_io3_oe ), + .flash_io0_do (xfer_io0_do ), + .flash_io1_do (xfer_io1_do ), + .flash_io2_do (xfer_io2_do ), + .flash_io3_do (xfer_io3_do ), + .flash_io0_di (flash_io0_di), + .flash_io1_di (flash_io1_di), + .flash_io2_di (flash_io2_di), + .flash_io3_di (flash_io3_di) + ); + + reg [3:0] state; + + always @(posedge clk) begin + xfer_resetn <= 1; + din_valid <= 0; + + if (!resetn || softreset) begin + state <= 0; + xfer_resetn <= 0; + rd_valid <= 0; + din_tag <= 0; + din_cont <= 0; + din_qspi <= 0; + din_ddr <= 0; + din_rd <= 0; + end else begin + if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data; + if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data; + if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data; + if (dout_valid && dout_tag == 4) begin + rdata <= {dout_data, buffer}; + rd_addr <= rd_inc ? rd_addr + 4 : addr; + rd_valid <= 1; + rd_wait <= rd_inc; + rd_inc <= 1; + end + + if (valid) + rd_wait <= 0; + + case (state) + 0: begin + din_valid <= 1; + din_data <= 8'h ff; + din_tag <= 0; + if (din_ready) begin + din_valid <= 0; + state <= 1; + end + end + 1: begin + if (dout_valid) begin + xfer_resetn <= 0; + state <= 2; + end + end + 2: begin + din_valid <= 1; + din_data <= 8'h ab; + din_tag <= 0; + if (din_ready) begin + din_valid <= 0; + state <= 3; + end + end + 3: begin + if (dout_valid) begin + xfer_resetn <= 0; + state <= 4; + end + end + 4: begin + rd_inc <= 0; + din_valid <= 1; + din_tag <= 0; + case ({config_ddr, config_qspi}) + 2'b11: din_data <= 8'h ED; + 2'b01: din_data <= 8'h EB; + 2'b10: din_data <= 8'h BB; + 2'b00: din_data <= 8'h 03; + endcase + if (din_ready) begin + din_valid <= 0; + state <= 5; + end + end + 5: begin + if (valid && !ready) begin + din_valid <= 1; + din_tag <= 0; + din_data <= addr[23:16]; + din_qspi <= config_qspi; + din_ddr <= config_ddr; + if (din_ready) begin + din_valid <= 0; + state <= 6; + end + end + end + 6: begin + din_valid <= 1; + din_tag <= 0; + din_data <= addr[15:8]; + if (din_ready) begin + din_valid <= 0; + state <= 7; + end + end + 7: begin + din_valid <= 1; + din_tag <= 0; + din_data <= addr[7:0]; + if (din_ready) begin + din_valid <= 0; + din_data <= 0; + state <= config_qspi || config_ddr ? 8 : 9; + end + end + 8: begin + din_valid <= 1; + din_tag <= 0; + din_data <= config_cont ? 8'h A5 : 8'h FF; + if (din_ready) begin + din_rd <= 1; + din_data <= config_dummy; + din_valid <= 0; + state <= 9; + end + end + 9: begin + din_valid <= 1; + din_tag <= 1; + if (din_ready) begin + din_valid <= 0; + state <= 10; + end + end + 10: begin + din_valid <= 1; + din_data <= 8'h 00; + din_tag <= 2; + if (din_ready) begin + din_valid <= 0; + state <= 11; + end + end + 11: begin + din_valid <= 1; + din_tag <= 3; + if (din_ready) begin + din_valid <= 0; + state <= 12; + end + end + 12: begin + if (!rd_wait || valid) begin + din_valid <= 1; + din_tag <= 4; + if (din_ready) begin + din_valid <= 0; + state <= 9; + end + end + end + endcase + + if (jump) begin + rd_inc <= 0; + rd_valid <= 0; + xfer_resetn <= 0; + if (config_cont) begin + state <= 5; + end else begin + state <= 4; + din_qspi <= 0; + din_ddr <= 0; + end + din_rd <= 0; + end + end + end endmodule module spimemio_xfer ( - input clk, resetn, xfer_resetn, + input clk, resetn, xfer_resetn, - input din_valid, - output din_ready, - input [7:0] din_data, - input [3:0] din_tag, - input din_cont, - input din_dspi, - input din_qspi, - input din_ddr, - input din_rd, + input din_valid, + output din_ready, + input [7:0] din_data, + input [3:0] din_tag, + input din_cont, + input din_dspi, + input din_qspi, + input din_ddr, + input din_rd, - output dout_valid, - output [7:0] dout_data, - output [3:0] dout_tag, + output dout_valid, + output [7:0] dout_data, + output [3:0] dout_tag, - output reg flash_csb, - output reg flash_clk, + output reg flash_csb, + output reg flash_clk, - output reg flash_io0_oe, - output reg flash_io1_oe, - output reg flash_io2_oe, - output reg flash_io3_oe, + output reg flash_io0_oe, + output reg flash_io1_oe, + output reg flash_io2_oe, + output reg flash_io3_oe, - output reg flash_io0_do, - output reg flash_io1_do, - output reg flash_io2_do, - output reg flash_io3_do, + output reg flash_io0_do, + output reg flash_io1_do, + output reg flash_io2_do, + output reg flash_io3_do, - input flash_io0_di, - input flash_io1_di, - input flash_io2_di, - input flash_io3_di + input flash_io0_di, + input flash_io1_di, + input flash_io2_di, + input flash_io3_di ); - reg [7:0] obuffer; - reg [7:0] ibuffer; + reg [7:0] obuffer; + reg [7:0] ibuffer; - reg [3:0] count; - reg [3:0] dummy_count; + reg [3:0] count; + reg [3:0] dummy_count; - reg xfer_cont; - reg xfer_dspi; - reg xfer_qspi; - reg xfer_ddr; - reg xfer_ddr_q; - reg xfer_rd; - reg [3:0] xfer_tag; - reg [3:0] xfer_tag_q; + reg xfer_cont; + reg xfer_dspi; + reg xfer_qspi; + reg xfer_ddr; + reg xfer_ddr_q; + reg xfer_rd; + reg [3:0] xfer_tag; + reg [3:0] xfer_tag_q; - reg [7:0] next_obuffer; - reg [7:0] next_ibuffer; - reg [3:0] next_count; + reg [7:0] next_obuffer; + reg [7:0] next_ibuffer; + reg [3:0] next_count; - reg fetch; - reg next_fetch; - reg last_fetch; + reg fetch; + reg next_fetch; + reg last_fetch; - always @(posedge clk) begin - xfer_ddr_q <= xfer_ddr; - xfer_tag_q <= xfer_tag; - end + always @(posedge clk) begin + xfer_ddr_q <= xfer_ddr; + xfer_tag_q <= xfer_tag; + end - assign din_ready = din_valid && xfer_resetn && next_fetch; + assign din_ready = din_valid && xfer_resetn && next_fetch; - assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn; - assign dout_data = ibuffer; - assign dout_tag = xfer_tag_q; + assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn; + assign dout_data = ibuffer; + assign dout_tag = xfer_tag_q; - always @* begin - flash_io0_oe = 0; - flash_io1_oe = 0; - flash_io2_oe = 0; - flash_io3_oe = 0; + always @* begin + flash_io0_oe = 0; + flash_io1_oe = 0; + flash_io2_oe = 0; + flash_io3_oe = 0; - flash_io0_do = 0; - flash_io1_do = 0; - flash_io2_do = 0; - flash_io3_do = 0; + flash_io0_do = 0; + flash_io1_do = 0; + flash_io2_do = 0; + flash_io3_do = 0; - next_obuffer = obuffer; - next_ibuffer = ibuffer; - next_count = count; - next_fetch = 0; + next_obuffer = obuffer; + next_ibuffer = ibuffer; + next_count = count; + next_fetch = 0; - if (dummy_count == 0) begin - casez ({xfer_ddr, xfer_qspi, xfer_dspi}) - 3'b 000: begin - flash_io0_oe = 1; - flash_io0_do = obuffer[7]; + if (dummy_count == 0) begin + casez ({xfer_ddr, xfer_qspi, xfer_dspi}) + 3'b 000: begin + flash_io0_oe = 1; + flash_io0_do = obuffer[7]; - if (flash_clk) begin - next_obuffer = {obuffer[6:0], 1'b 0}; - next_count = count - |count; - end else begin - next_ibuffer = {ibuffer[6:0], flash_io1_di}; - end + if (flash_clk) begin + next_obuffer = {obuffer[6:0], 1'b 0}; + next_count = count - |count; + end else begin + next_ibuffer = {ibuffer[6:0], flash_io1_di}; + end - next_fetch = (next_count == 0); - end - 3'b 01?: begin - flash_io0_oe = !xfer_rd; - flash_io1_oe = !xfer_rd; - flash_io2_oe = !xfer_rd; - flash_io3_oe = !xfer_rd; + next_fetch = (next_count == 0); + end + 3'b 01?: begin + flash_io0_oe = !xfer_rd; + flash_io1_oe = !xfer_rd; + flash_io2_oe = !xfer_rd; + flash_io3_oe = !xfer_rd; - flash_io0_do = obuffer[4]; - flash_io1_do = obuffer[5]; - flash_io2_do = obuffer[6]; - flash_io3_do = obuffer[7]; + flash_io0_do = obuffer[4]; + flash_io1_do = obuffer[5]; + flash_io2_do = obuffer[6]; + flash_io3_do = obuffer[7]; - if (flash_clk) begin - next_obuffer = {obuffer[3:0], 4'b 0000}; - next_count = count - {|count, 2'b00}; - end else begin - next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; - end + if (flash_clk) begin + next_obuffer = {obuffer[3:0], 4'b 0000}; + next_count = count - {|count, 2'b00}; + end else begin + next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; + end - next_fetch = (next_count == 0); - end - 3'b 11?: begin - flash_io0_oe = !xfer_rd; - flash_io1_oe = !xfer_rd; - flash_io2_oe = !xfer_rd; - flash_io3_oe = !xfer_rd; + next_fetch = (next_count == 0); + end + 3'b 11?: begin + flash_io0_oe = !xfer_rd; + flash_io1_oe = !xfer_rd; + flash_io2_oe = !xfer_rd; + flash_io3_oe = !xfer_rd; - flash_io0_do = obuffer[4]; - flash_io1_do = obuffer[5]; - flash_io2_do = obuffer[6]; - flash_io3_do = obuffer[7]; + flash_io0_do = obuffer[4]; + flash_io1_do = obuffer[5]; + flash_io2_do = obuffer[6]; + flash_io3_do = obuffer[7]; - next_obuffer = {obuffer[3:0], 4'b 0000}; - next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; - next_count = count - {|count, 2'b00}; + next_obuffer = {obuffer[3:0], 4'b 0000}; + next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; + next_count = count - {|count, 2'b00}; - next_fetch = (next_count == 0); - end - 3'b ??1: begin - flash_io0_oe = !xfer_rd; - flash_io1_oe = !xfer_rd; + next_fetch = (next_count == 0); + end + 3'b ??1: begin + flash_io0_oe = !xfer_rd; + flash_io1_oe = !xfer_rd; - flash_io0_do = obuffer[6]; - flash_io1_do = obuffer[7]; + flash_io0_do = obuffer[6]; + flash_io1_do = obuffer[7]; - if (flash_clk) begin - next_obuffer = {obuffer[5:0], 2'b 00}; - next_count = count - {|count, 1'b0}; - end else begin - next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di}; - end + if (flash_clk) begin + next_obuffer = {obuffer[5:0], 2'b 00}; + next_count = count - {|count, 1'b0}; + end else begin + next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di}; + end - next_fetch = (next_count == 0); - end - endcase - end - end + next_fetch = (next_count == 0); + end + endcase + end + end - always @(posedge clk) begin - if (!resetn || !xfer_resetn) begin - fetch <= 1; - last_fetch <= 1; - flash_csb <= 1; - flash_clk <= 0; - count <= 0; - dummy_count <= 0; - xfer_tag <= 0; - xfer_cont <= 0; - xfer_dspi <= 0; - xfer_qspi <= 0; - xfer_ddr <= 0; - xfer_rd <= 0; - end else begin - fetch <= next_fetch; - last_fetch <= xfer_ddr ? fetch : 1; - if (dummy_count) begin - flash_clk <= !flash_clk && !flash_csb; - dummy_count <= dummy_count - flash_clk; - end else - if (count) begin - flash_clk <= !flash_clk && !flash_csb; - obuffer <= next_obuffer; - ibuffer <= next_ibuffer; - count <= next_count; - end - if (din_valid && din_ready) begin - flash_csb <= 0; - flash_clk <= 0; + always @(posedge clk) begin + if (!resetn || !xfer_resetn) begin + fetch <= 1; + last_fetch <= 1; + flash_csb <= 1; + flash_clk <= 0; + count <= 0; + dummy_count <= 0; + xfer_tag <= 0; + xfer_cont <= 0; + xfer_dspi <= 0; + xfer_qspi <= 0; + xfer_ddr <= 0; + xfer_rd <= 0; + end else begin + fetch <= next_fetch; + last_fetch <= xfer_ddr ? fetch : 1; + if (dummy_count) begin + flash_clk <= !flash_clk && !flash_csb; + dummy_count <= dummy_count - flash_clk; + end else + if (count) begin + flash_clk <= !flash_clk && !flash_csb; + obuffer <= next_obuffer; + ibuffer <= next_ibuffer; + count <= next_count; + end + if (din_valid && din_ready) begin + flash_csb <= 0; + flash_clk <= 0; - count <= 8; - dummy_count <= din_rd ? din_data : 0; - obuffer <= din_data; + count <= 8; + dummy_count <= din_rd ? din_data : 0; + obuffer <= din_data; - xfer_tag <= din_tag; - xfer_cont <= din_cont; - xfer_dspi <= din_dspi; - xfer_qspi <= din_qspi; - xfer_ddr <= din_ddr; - xfer_rd <= din_rd; - end - end - end + xfer_tag <= din_tag; + xfer_cont <= din_cont; + xfer_dspi <= din_dspi; + xfer_qspi <= din_qspi; + xfer_ddr <= din_ddr; + xfer_rd <= din_rd; + end + end + end endmodule +
diff --git a/verilog/rtl/sram_1rw1r_32_256_8_sky130.v b/verilog/rtl/sram_1rw1r_32_256_8_sky130.v new file mode 100644 index 0000000..2dd1c62 --- /dev/null +++ b/verilog/rtl/sram_1rw1r_32_256_8_sky130.v
@@ -0,0 +1,108 @@ +// OpenRAM SRAM model +// Words: 256 +// Word size: 32 +// Write size: 8 + +module sram_1rw1r_32_256_8_sky130( +// Port 0: RW + clk0,csb0,web0,wmask0,addr0,din0,dout0, +// Port 1: R + clk1,csb1,addr1,dout1 + ); + + parameter NUM_WMASKS = 4 ; + parameter DATA_WIDTH = 32 ; + parameter ADDR_WIDTH = 8 ; + parameter RAM_DEPTH = 1 << ADDR_WIDTH; + // FIXME: This delay is arbitrary. + parameter DELAY = 1 ; + + input clk0; // clock + input csb0; // active low chip select + input web0; // active low write control + input [NUM_WMASKS-1:0] wmask0; // write mask + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; + input clk1; // clock + input csb1; // active low chip select + input [ADDR_WIDTH-1:0] addr1; + output [DATA_WIDTH-1:0] dout1; + + reg csb0_reg; + reg web0_reg; + reg [NUM_WMASKS-1:0] wmask0_reg; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; + + // All inputs are registers + always @(posedge clk0) + begin + csb0_reg = csb0; + web0_reg = web0; + wmask0_reg = wmask0; + addr0_reg = addr0; + din0_reg = din0; + dout0 = 32'bx; +`ifdef DBG + if ( !csb0_reg && web0_reg ) + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); + if ( !csb0_reg && !web0_reg ) + $display($time," Writing %m addr0=%b din0=%b wmask0=%b",addr0_reg,din0_reg,wmask0_reg); +`endif + end + + reg csb1_reg; + reg [ADDR_WIDTH-1:0] addr1_reg; + reg [DATA_WIDTH-1:0] dout1; + + // All inputs are registers + always @(posedge clk1) + begin + csb1_reg = csb1; + addr1_reg = addr1; +`ifdef DBG + if (!csb0 && !web0 && !csb1 && (addr0 == addr1)) + $display($time," WARNING: Writing and reading addr0=%b and addr1=%b simultaneously!",addr0,addr1); + dout1 = 32'bx; + if ( !csb1_reg ) + $display($time," Reading %m addr1=%b dout1=%b",addr1_reg,mem[addr1_reg]); +`endif + end + +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; + + // Memory Write Block Port 0 + // Write Operation : When web0 = 0, csb0 = 0 + always @ (negedge clk0) + begin : MEM_WRITE0 + if ( !csb0_reg && !web0_reg ) begin + if (wmask0_reg[0]) + mem[addr0_reg][7:0] = din0_reg[7:0]; + if (wmask0_reg[1]) + mem[addr0_reg][15:8] = din0_reg[15:8]; + if (wmask0_reg[2]) + mem[addr0_reg][23:16] = din0_reg[23:16]; + if (wmask0_reg[3]) + mem[addr0_reg][31:24] = din0_reg[31:24]; + end + end + + // Memory Read Block Port 0 + // Read Operation : When web0 = 1, csb0 = 0 + always @ (negedge clk0) + begin : MEM_READ0 + if (!csb0_reg && web0_reg) + dout0 <= #(DELAY) mem[addr0_reg]; + end + + // Memory Read Block Port 1 + // Read Operation : When web1 = 1, csb1 = 0 + always @ (negedge clk1) + begin : MEM_READ1 + if (!csb1_reg) + dout1 <= #(DELAY) mem[addr1_reg]; + end + +endmodule
diff --git a/verilog/rtl/striVe_clkrst.v b/verilog/rtl/striVe_clkrst.v index 6310274..ff42831 100644 --- a/verilog/rtl/striVe_clkrst.v +++ b/verilog/rtl/striVe_clkrst.v
@@ -1,31 +1,35 @@ module striVe_clkrst( - input ext_clk_sel, - input ext_clk, - input pll_clk, - input reset, - input ext_reset, - output clk, - output resetn +`ifdef LVS + input vdd1v8, + input vss, +`endif + input ext_clk_sel, + input ext_clk, + input pll_clk, + input reset, + input ext_reset, + output clk, + output resetn ); - // Clock assignment (to do: make this glitch-free) - assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk; + // Clock assignment (to do: make this glitch-free) + assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk; - // Reset assignment. "reset" comes from POR, while "ext_reset" - // comes from standalone SPI (and is normally zero unless - // activated from the SPI). + // Reset assignment. "reset" comes from POR, while "ext_reset" + // comes from standalone SPI (and is normally zero unless + // activated from the SPI). - // Staged-delay reset - reg [2:0] reset_delay; + // Staged-delay reset + reg [2:0] reset_delay; - always @(posedge clk or posedge reset) begin - if (reset == 1'b1) begin - reset_delay <= 3'b111; - end else begin - reset_delay <= {1'b0, reset_delay[2:1]}; - end - end + always @(posedge clk or posedge reset) begin + if (reset == 1'b1) begin + reset_delay <= 3'b111; + end else begin + reset_delay <= {1'b0, reset_delay[2:1]}; + end + end - assign resetn = ~(reset_delay[0] | ext_reset); + assign resetn = ~(reset_delay[0] | ext_reset); endmodule
diff --git a/verilog/rtl/striVe_soc.v b/verilog/rtl/striVe_soc.v deleted file mode 100644 index 1899a99..0000000 --- a/verilog/rtl/striVe_soc.v +++ /dev/null
@@ -1,837 +0,0 @@ -/* - * PicoSoC - A simple example SoC using PicoRV32 - * - * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Revision 1, July 2019: Added signals to drive flash_clk and flash_csb - * output enable (inverted), tied to reset so that the flash is completely - * isolated from the processor when the processor is in reset. - * - * Also: Made ram_wenb a 4-bit bus so that the memory access can be made - * byte-wide for byte-wide instructions. - */ - -`ifdef PICORV32_V -`error "openstriVe_soc.v must be read before picorv32.v!" -`endif - -/* Note: Synthesize register memory from flops */ -/* Inefficient, but not terribly so */ - -/* Also note: To avoid having a hard macro in the place & route */ -/* (method not finished yet in qflow), SRAM pins are brought out to */ -/* the openstriVe_soc I/O so that openstriVe_soc.v itself is fully synthesizable */ -/* and routable with qflow as-is. */ - -`define PICORV32_REGS openstriVe_soc_regs - -module striVe_soc ( -`ifdef LVS - inout vdd1v8, /* 1.8V domain */ - inout vss, -`endif - input pll_clk, - input ext_clk, - input ext_clk_sel, - /* - input ext_reset, - input reset, - */ - - input clk, - input resetn, - // Main SRAM, including clk and resetn above - // (Not used: RAM is synthesized in this version) - /* - output [3:0] ram_wenb, - output [9:0] ram_addr, - output [31:0] ram_wdata, - input [31:0] ram_rdata, - */ - - // Memory mapped I/O signals - output [15:0] gpio_out_pad, // Connect to out on gpio pad - input [15:0] gpio_in_pad, // Connect to in on gpio pad - output [15:0] gpio_mode0_pad, // Connect to dm[0] on gpio pad - output [15:0] gpio_mode1_pad, // Connect to dm[2] on gpio pad - output [15:0] gpio_outenb_pad, // Connect to oe_n on gpio pad - output [15:0] gpio_inenb_pad, // Connect to inp_dis on gpio pad - - output adc0_ena, - output adc0_convert, - input [9:0] adc0_data, - input adc0_done, - output adc0_clk, - output [1:0] adc0_inputsrc, - output adc1_ena, - output adc1_convert, - output adc1_clk, - output [1:0] adc1_inputsrc, - input [9:0] adc1_data, - input adc1_done, - - output dac_ena, - output [9:0] dac_value, - - output analog_out_sel, // Analog output select (DAC or bandgap) - output opamp_ena, // Op-amp enable for analog output - output opamp_bias_ena, // Op-amp bias enable for analog output - output bg_ena, // Bandgap enable - - output comp_ena, - output [1:0] comp_ninputsrc, - output [1:0] comp_pinputsrc, - output rcosc_ena, - - output overtemp_ena, - input overtemp, - input rcosc_in, // RC oscillator output - input xtal_in, // crystal oscillator output - input comp_in, // comparator output - input spi_sck, - - input [7:0] spi_ro_config, - input spi_ro_xtal_ena, - input spi_ro_reg_ena, - input spi_ro_pll_dco_ena, - input [4:0] spi_ro_pll_div, - input [2:0] spi_ro_pll_sel, - input [25:0] spi_ro_pll_trim, - - input [11:0] spi_ro_mfgr_id, - input [7:0] spi_ro_prod_id, - input [3:0] spi_ro_mask_rev, - - output ser_tx, - input ser_rx, - - // IRQ - input irq_pin, // dedicated IRQ pin - input irq_spi, // IRQ from standalone SPI - - // trap - output trap, - - // Flash memory control (SPI master) - output flash_csb, - output flash_clk, - - output flash_csb_oeb, - output flash_clk_oeb, - - output flash_io0_oeb, - output flash_io1_oeb, - output flash_io2_oeb, - output flash_io3_oeb, - - output flash_csb_ieb, - output flash_clk_ieb, - - output flash_io0_ieb, - output flash_io1_ieb, - output flash_io2_ieb, - output flash_io3_ieb, - - output flash_io0_do, - output flash_io1_do, - output flash_io2_do, - output flash_io3_do, - - input flash_io0_di, - input flash_io1_di, - input flash_io2_di, - input flash_io3_di -); - /* Increase scratchpad memory to 1K words */ - /* parameter integer MEM_WORDS = 1024; */ - /* Memory reverted back to 256 words while memory has to be synthesized */ - parameter integer MEM_WORDS = 256; - parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory - parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash - -// wire resetn; -// wire clk; - - wire iomem_valid; - reg iomem_ready; - wire [ 3:0] iomem_wstrb; - wire [31:0] iomem_addr; - wire [31:0] iomem_wdata; - reg [31:0] iomem_rdata; - - // memory-mapped I/O control registers - - wire [15:0] gpio_pullup; // Intermediate GPIO pullup - wire [15:0] gpio_pulldown; // Intermediate GPIO pulldown - wire [15:0] gpio_outenb; // Intermediate GPIO out enable (bar) - wire [15:0] gpio_out; // Intermediate GPIO output - - reg [15:0] gpio; // GPIO output data - reg [15:0] gpio_pu; // GPIO pull-up enable - reg [15:0] gpio_pd; // GPIO pull-down enable - reg [15:0] gpio_oeb; // GPIO output enable (sense negative) - reg adc0_ena; // ADC0 enable - reg adc0_convert; // ADC0 convert - reg [1:0] adc0_clksrc; // ADC0 clock source - reg [1:0] adc0_inputsrc; // ADC0 input source - reg adc1_ena; // ADC1 enable - reg adc1_convert; // ADC1 convert - reg [1:0] adc1_clksrc; // ADC1 clock source - reg [1:0] adc1_inputsrc; // ADC1 input source - reg dac_ena; // DAC enable - reg [9:0] dac_value; // DAC output value - reg comp_ena; // Comparator enable - reg [1:0] comp_ninputsrc; // Comparator negative input source - reg [1:0] comp_pinputsrc; // Comparator positive input source - reg rcosc_ena; // RC oscillator enable - reg overtemp_ena; // Over-temperature alarm enable - reg [1:0] comp_output_dest; // Comparator output destination - reg [1:0] rcosc_output_dest; // RC oscillator output destination - reg [1:0] overtemp_dest; // Over-temperature alarm destination - reg [1:0] pll_output_dest; // PLL clock output destination - reg [1:0] xtal_output_dest; // Crystal oscillator output destination - reg [1:0] trap_output_dest; // Trap signal output destination - reg [1:0] irq_7_inputsrc; // IRQ 5 source - reg [1:0] irq_8_inputsrc; // IRQ 6 source - reg analog_out_sel; // Analog output select - reg opamp_ena; // Analog output op-amp enable - reg opamp_bias_ena; // Analog output op-amp bias enable - reg bg_ena; // Bandgap enable - wire adc0_clk; // ADC0 clock (multiplexed) - wire adc1_clk; // ADC1 clock (multiplexed) - - wire [3:0] ram_wenb; - wire [9:0] ram_addr; - wire [31:0] ram_wdata; - -// // Clock assignment (to do: make this glitch-free) -// assign clk = (ext_clk_sel == 1'b1) ? ext_clk : pll_clk; -// -// // Reset assignment. "reset" comes from POR, while "ext_reset" -// // comes from standalone SPI (and is normally zero unless -// // activated from the SPI). -// -// // Staged-delay reset -// reg [2:0] reset_delay; -// -// always @(posedge clk or posedge reset) begin -// if (reset == 1'b1) begin -// reset_delay <= 3'b111; -// end else begin -// reset_delay <= {1'b0, reset_delay[2:1]}; -// end -// end -// -// assign resetn = ~(reset_delay[0] | ext_reset); - - // ADC clock assignments - - assign adc0_clk = (adc0_clksrc == 2'b00) ? rcosc_in : - (adc0_clksrc == 2'b01) ? spi_sck : - (adc0_clksrc == 2'b10) ? xtal_in : - ext_clk; - - assign adc1_clk = (adc1_clksrc == 2'b00) ? rcosc_in : - (adc1_clksrc == 2'b01) ? spi_sck : - (adc1_clksrc == 2'b10) ? xtal_in : - ext_clk; - - // GPIO assignments - - assign gpio_out[0] = (comp_output_dest == 2'b01) ? comp_in : gpio[0]; - assign gpio_out[1] = (comp_output_dest == 2'b10) ? comp_in : gpio[1]; - assign gpio_out[2] = (rcosc_output_dest == 2'b01) ? rcosc_in : gpio[2]; - assign gpio_out[3] = (rcosc_output_dest == 2'b10) ? rcosc_in : gpio[3]; - assign gpio_out[4] = (rcosc_output_dest == 2'b11) ? rcosc_in : gpio[4]; - assign gpio_out[5] = (xtal_output_dest == 2'b01) ? xtal_in : gpio[5]; - assign gpio_out[6] = (xtal_output_dest == 2'b10) ? xtal_in : gpio[6]; - assign gpio_out[7] = (xtal_output_dest == 2'b11) ? xtal_in : gpio[7]; - assign gpio_out[8] = (pll_output_dest == 2'b01) ? pll_clk : gpio[8]; - assign gpio_out[9] = (pll_output_dest == 2'b10) ? pll_clk : gpio[9]; - assign gpio_out[10] = (pll_output_dest == 2'b11) ? clk : gpio[10]; - assign gpio_out[11] = (trap_output_dest == 2'b01) ? trap : gpio[11]; - assign gpio_out[12] = (trap_output_dest == 2'b10) ? trap : gpio[12]; - assign gpio_out[13] = (trap_output_dest == 2'b11) ? trap : gpio[13]; - assign gpio_out[14] = (overtemp_dest == 2'b01) ? overtemp : gpio[14]; - assign gpio_out[15] = (overtemp_dest == 2'b10) ? overtemp : gpio[15]; - - assign gpio_outenb[0] = (comp_output_dest == 2'b00) ? gpio_oeb[0] : 1'b0; - assign gpio_outenb[1] = (comp_output_dest == 2'b00) ? gpio_oeb[1] : 1'b0; - assign gpio_outenb[2] = (rcosc_output_dest == 2'b00) ? gpio_oeb[2] : 1'b0; - assign gpio_outenb[3] = (rcosc_output_dest == 2'b00) ? gpio_oeb[3] : 1'b0; - assign gpio_outenb[4] = (rcosc_output_dest == 2'b00) ? gpio_oeb[4] : 1'b0; - assign gpio_outenb[5] = (xtal_output_dest == 2'b00) ? gpio_oeb[5] : 1'b0; - assign gpio_outenb[6] = (xtal_output_dest == 2'b00) ? gpio_oeb[6] : 1'b0; - assign gpio_outenb[7] = (xtal_output_dest == 2'b00) ? gpio_oeb[7] : 1'b0; - assign gpio_outenb[8] = (pll_output_dest == 2'b00) ? gpio_oeb[8] : 1'b0; - assign gpio_outenb[9] = (pll_output_dest == 2'b00) ? gpio_oeb[9] : 1'b0; - assign gpio_outenb[10] = (pll_output_dest == 2'b00) ? gpio_oeb[10] : 1'b0; - assign gpio_outenb[11] = (trap_output_dest == 2'b00) ? gpio_oeb[11] : 1'b0; - assign gpio_outenb[12] = (trap_output_dest == 2'b00) ? gpio_oeb[12] : 1'b0; - assign gpio_outenb[13] = (trap_output_dest == 2'b00) ? gpio_oeb[13] : 1'b0; - assign gpio_outenb[14] = (overtemp_dest == 2'b00) ? gpio_oeb[14] : 1'b0; - assign gpio_outenb[15] = (overtemp_dest == 2'b00) ? gpio_oeb[15] : 1'b0; - - assign gpio_pullup[0] = (comp_output_dest == 2'b00) ? gpio_pu[0] : 1'b0; - assign gpio_pullup[1] = (comp_output_dest == 2'b00) ? gpio_pu[1] : 1'b0; - assign gpio_pullup[2] = (rcosc_output_dest == 2'b00) ? gpio_pu[2] : 1'b0; - assign gpio_pullup[3] = (rcosc_output_dest == 2'b00) ? gpio_pu[3] : 1'b0; - assign gpio_pullup[4] = (rcosc_output_dest == 2'b00) ? gpio_pu[4] : 1'b0; - assign gpio_pullup[5] = (xtal_output_dest == 2'b00) ? gpio_pu[5] : 1'b0; - assign gpio_pullup[6] = (xtal_output_dest == 2'b00) ? gpio_pu[6] : 1'b0; - assign gpio_pullup[7] = (xtal_output_dest == 2'b00) ? gpio_pu[7] : 1'b0; - assign gpio_pullup[8] = (pll_output_dest == 2'b00) ? gpio_pu[8] : 1'b0; - assign gpio_pullup[9] = (pll_output_dest == 2'b00) ? gpio_pu[9] : 1'b0; - assign gpio_pullup[10] = (pll_output_dest == 2'b00) ? gpio_pu[10] : 1'b0; - assign gpio_pullup[11] = (trap_output_dest == 2'b00) ? gpio_pu[11] : 1'b0; - assign gpio_pullup[12] = (trap_output_dest == 2'b00) ? gpio_pu[12] : 1'b0; - assign gpio_pullup[13] = (trap_output_dest == 2'b00) ? gpio_pu[13] : 1'b0; - assign gpio_pullup[14] = (overtemp_dest == 2'b00) ? gpio_pu[14] : 1'b0; - assign gpio_pullup[15] = (overtemp_dest == 2'b00) ? gpio_pu[15] : 1'b0; - - assign gpio_pulldown[0] = (comp_output_dest == 2'b00) ? gpio_pd[0] : 1'b0; - assign gpio_pulldown[1] = (comp_output_dest == 2'b00) ? gpio_pd[1] : 1'b0; - assign gpio_pulldown[2] = (rcosc_output_dest == 2'b00) ? gpio_pd[2] : 1'b0; - assign gpio_pulldown[3] = (rcosc_output_dest == 2'b00) ? gpio_pd[3] : 1'b0; - assign gpio_pulldown[4] = (rcosc_output_dest == 2'b00) ? gpio_pd[4] : 1'b0; - assign gpio_pulldown[5] = (xtal_output_dest == 2'b00) ? gpio_pd[5] : 1'b0; - assign gpio_pulldown[6] = (xtal_output_dest == 2'b00) ? gpio_pd[6] : 1'b0; - assign gpio_pulldown[7] = (xtal_output_dest == 2'b00) ? gpio_pd[7] : 1'b0; - assign gpio_pulldown[8] = (pll_output_dest == 2'b00) ? gpio_pd[8] : 1'b0; - assign gpio_pulldown[9] = (pll_output_dest == 2'b00) ? gpio_pd[9] : 1'b0; - assign gpio_pulldown[10] = (pll_output_dest == 2'b00) ? gpio_pd[10] : 1'b0; - assign gpio_pulldown[11] = (trap_output_dest == 2'b00) ? gpio_pd[11] : 1'b0; - assign gpio_pulldown[12] = (trap_output_dest == 2'b00) ? gpio_pd[12] : 1'b0; - assign gpio_pulldown[13] = (trap_output_dest == 2'b00) ? gpio_pd[13] : 1'b0; - assign gpio_pulldown[14] = (overtemp_dest == 2'b00) ? gpio_pd[14] : 1'b0; - assign gpio_pulldown[15] = (overtemp_dest == 2'b00) ? gpio_pd[15] : 1'b0; - - // Convert GPIO signals to s8 pad signals - convert_gpio_sigs convert_gpio_bit [15:0] ( - .gpio_out(gpio_out), - .gpio_outenb(gpio_outenb), - .gpio_pu(gpio_pullup), - .gpio_pd(gpio_pulldown), - .gpio_out_pad(gpio_out_pad), - .gpio_outenb_pad(gpio_outenb_pad), - .gpio_inenb_pad(gpio_inenb_pad), - .gpio_mode1_pad(gpio_mode1_pad), - .gpio_mode0_pad(gpio_mode0_pad) - ); - - wire irq_7, irq_8; - - assign irq_7 = (irq_7_inputsrc == 2'b01) ? gpio_in_pad[0] : - (irq_7_inputsrc == 2'b10) ? gpio_in_pad[1] : - (irq_7_inputsrc == 2'b11) ? gpio_in_pad[2] : 1'b0; - assign irq_8 = (irq_8_inputsrc == 2'b01) ? gpio_in_pad[3] : - (irq_8_inputsrc == 2'b10) ? gpio_in_pad[4] : - (irq_8_inputsrc == 2'b11) ? gpio_in_pad[5] : 1'b0; - - assign ram_wenb = (mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? - {~mem_wstrb[3], ~mem_wstrb[2], ~mem_wstrb[1], ~mem_wstrb[0]} : 4'b1111; - assign ram_addr = mem_addr[11:2]; - assign ram_wdata = mem_wdata; // Just for naming conventions. - - reg [31:0] irq; - wire irq_stall = 0; - wire irq_uart = 0; - - always @* begin - irq = 0; - irq[3] = irq_stall; - irq[4] = irq_uart; - irq[5] = irq_pin; - irq[6] = irq_spi; - irq[7] = irq_7; - irq[8] = irq_8; - irq[9] = comp_output_dest[0] & comp_output_dest[1] & comp_in; - irq[10] = overtemp_dest[0] & overtemp_dest[1] & overtemp; - end - - wire mem_valid; - wire mem_instr; - wire mem_ready; - wire [31:0] mem_addr; - wire [31:0] mem_wdata; - wire [3:0] mem_wstrb; - wire [31:0] mem_rdata; - - wire spimem_ready; - wire [31:0] spimem_rdata; - - reg ram_ready; - wire [31:0] ram_rdata; - - assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01); - assign iomem_wstrb = mem_wstrb; - assign iomem_addr = mem_addr; - assign iomem_wdata = mem_wdata; - - wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000); - wire [31:0] spimemio_cfgreg_do; - - wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004); - wire [31:0] simpleuart_reg_div_do; - - wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008); - wire [31:0] simpleuart_reg_dat_do; - wire simpleuart_reg_dat_wait; - - assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel || - simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait); - - assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata : - spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do : - simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000; - - picorv32 #( - .STACKADDR(STACKADDR), - .PROGADDR_RESET(PROGADDR_RESET), - .PROGADDR_IRQ(32'h 0000_0000), - .BARREL_SHIFTER(1), - .COMPRESSED_ISA(1), - .ENABLE_MUL(1), - .ENABLE_DIV(1), - .ENABLE_IRQ(1), - .ENABLE_IRQ_QREGS(0) - ) cpu ( - .clk (clk ), - .resetn (resetn ), - .mem_valid (mem_valid ), - .mem_instr (mem_instr ), - .mem_ready (mem_ready ), - .mem_addr (mem_addr ), - .mem_wdata (mem_wdata ), - .mem_wstrb (mem_wstrb ), - .mem_rdata (mem_rdata ), - .irq (irq ), - .trap (trap ) - ); - - spimemio spimemio ( - .clk (clk), - .resetn (resetn), - .valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000), - .ready (spimem_ready), - .addr (mem_addr[23:0]), - .rdata (spimem_rdata), - - .flash_csb (flash_csb ), - .flash_clk (flash_clk ), - - .flash_csb_oeb (flash_csb_oeb), - .flash_clk_oeb (flash_clk_oeb), - - .flash_io0_oeb (flash_io0_oeb), - .flash_io1_oeb (flash_io1_oeb), - .flash_io2_oeb (flash_io2_oeb), - .flash_io3_oeb (flash_io3_oeb), - - .flash_csb_ieb (flash_csb_ieb), - .flash_clk_ieb (flash_clk_ieb), - - .flash_io0_ieb (flash_io0_ieb), - .flash_io1_ieb (flash_io1_ieb), - .flash_io2_ieb (flash_io2_ieb), - .flash_io3_ieb (flash_io3_ieb), - - .flash_io0_do (flash_io0_do), - .flash_io1_do (flash_io1_do), - .flash_io2_do (flash_io2_do), - .flash_io3_do (flash_io3_do), - - .flash_io0_di (flash_io0_di), - .flash_io1_di (flash_io1_di), - .flash_io2_di (flash_io2_di), - .flash_io3_di (flash_io3_di), - - .cfgreg_we(spimemio_cfgreg_sel ? mem_wstrb : 4'b 0000), - .cfgreg_di(mem_wdata), - .cfgreg_do(spimemio_cfgreg_do) - ); - - simpleuart simpleuart ( - .clk (clk ), - .resetn (resetn ), - - .ser_tx (ser_tx ), - .ser_rx (ser_rx ), - - .reg_div_we (simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000), - .reg_div_di (mem_wdata), - .reg_div_do (simpleuart_reg_div_do), - - .reg_dat_we (simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0), - .reg_dat_re (simpleuart_reg_dat_sel && !mem_wstrb), - .reg_dat_di (mem_wdata), - .reg_dat_do (simpleuart_reg_dat_do), - .reg_dat_wait(simpleuart_reg_dat_wait) - ); - - always @(posedge clk) - ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS; - - // PicoSoC memory mapped IP - // 2 ADCs (1 multiplexed from internal signals, including core 1.8V VDD, - // DAC output, comparator input, external input) - // 1 DAC - // 1 comparator (1 end tied to DAC, other could be shared w/ADC input) - // 1 RC oscillator (output can be tied to one or both ADC clocks) - // 1 crystal oscillator (output to level-shift-down = 3V buffer powered at 1.8V) - // 1 1.8V regulator (sets VDD on padframe) - // 1 bandgap - // 1 power-on-reset (POR) - // 1 temperature alarm - - // NOTE: Signals affecting critical core functions are controlled through - // an independent SPI having read-only access through the picorv32 core. - // SPI pins are independent of picorv32 SPI master. Signals controlled by - // the SPI are: - // 1) crystal oscillator enable (default on) - // 2) 1.8V regulator enable (default on) - // 3) bandgap enable (default on) - // 4) picorv32 internal debug signals (TBD) - // 5) additional picorv32 IRQ (TBD) - // 6) PLL enables (default on) - // 7) PLL trim (default TBD) - // NOTE: SPI should have a pass-through mode that configures SDO as a - // copy of a chosen signal for as long as CSB is held low. This can be - // an SPI command, allows other internal signals to be passed to the - // output and viewed, including the RC oscillator output, comparator output, - // and other edge-based signals. - - // Memory map: - // NOTE: - - // SPI master: 0x02000000 (control) - // UART: 0x02000004-8 (clock, data) - // GPIO: 0x03000000 (in/out, pu/pd, data) - // ADC0: 0x03000020 - // ADC1: 0x03000040 - // DAC: 0x03000060 - // comparator: 0x03000080 - // RC osc: 0x030000a0 - // SPI slave: 0x030000c0 (read-only) - - // Memory map details: - // GPIO: 32 channels total. - // addr 0x03000000 data (16 bits) - // addr 0x03000001 out (=1) or in (=0) (default 0) - // addr 0x03000002 pu (=1) or none (=0) (default 0) - // addr 0x03000003 pd (=1) or none (=0) (default 0) - // addr 0x03000004-f reserved (may be used for other pad I/O) - // - // ADC0: addr 0x03000020 enable - // addr 0x03000021 data (read-only) - // addr 0x03000022 done (read-only) - // addr 0x03000023 start conversion - // addr 0x03000024 clock source (RC osc, SPI clk, xtal, core) - // addr 0x03000025 input source (core VDD, ext, DAC, comp in) - // - // ADC1: addr 0x03000040 enable - // addr 0x03000041 data (read-only) - // addr 0x03000042 done (read-only) - // addr 0x03000043 start conversion - // addr 0x03000044 clock source (RC osc, SPI clk, xtal, core) - // addr 0x03000045 input source (bg, ext, I/O vdd, gnd) - // - // DAC: addr 0x03000060 enable - // addr 0x03000061 value - // - // comparator: addr 0x03000080 enable - // addr 0x03000081 value - // addr 0x03000082 input source (DAC, bg, core VDD, ext) - // addr 0x03000083 output dest (ext gpio pin 0-1, IRQ, none) - // - // bandgap: addr 0x03000090 enable - // - // RC osc: addr 0x030000a0 enable - // addr 0x030000a1 output dest (ext gpio pin 2-4) - // - // SPI slave: addr 0x030000c0 SPI configuration - // addr 0x030000c1 xtal osc, reg, bg enables - // addr 0x030000c2 PLL enables, trim - // addr 0x030000c3 manufacturer ID - // addr 0x030000c4 product ID - // addr 0x030000c5 product mask revision - // Xtal mon: addr 0x030000c6 xtal osc output dest (ext gpio pin 5-7) - // PLL mon: addr 0x030000c7 PLL output dest (ext gpio pin 8-10) - // trap mon: addr 0x030000c8 trap output dest (ext gpio pin 11-13) - // IRQ7 src: addr 0x030000c9 IRQ 7 source (ext gpio pin 0-3) - // IRQ8 src: addr 0x030000ca IRQ 8 source (ext gpio pin 4-7) - // Analog: addr 0x030000cb analog output select (DAC, bg) - // - // Overtemp: addr 0x030000e0 over-temperature alarm enable - // addr 0x030000e1 over-temperature alarm data - // addr 0x030000e2 output dest (ext gpio pin 14-15, IRQ) - - always @(posedge clk) begin - if (!resetn) begin - gpio <= 0; - gpio_oeb <= 16'hffff; - gpio_pu <= 0; - gpio_pd <= 0; - adc0_ena <= 0; - adc0_convert <= 0; - adc0_clksrc <= 0; - adc0_inputsrc <= 0; - adc1_ena <= 0; - adc1_convert <= 0; - adc1_clksrc <= 0; - adc1_inputsrc <= 0; - dac_ena <= 0; - dac_value <= 0; - comp_ena <= 0; - comp_ninputsrc <= 0; - comp_pinputsrc <= 0; - rcosc_ena <= 0; - comp_output_dest <= 0; - rcosc_output_dest <= 0; - overtemp_dest <= 0; - overtemp_ena <= 0; - pll_output_dest <= 0; - xtal_output_dest <= 0; - trap_output_dest <= 0; - irq_7_inputsrc <= 0; - irq_8_inputsrc <= 0; - analog_out_sel <= 0; - opamp_ena <= 0; - opamp_bias_ena <= 0; - bg_ena <= 0; - - end else begin - iomem_ready <= 0; - if (iomem_valid && !iomem_ready && iomem_addr[31:8] == 24'h030000) begin - iomem_ready <= 1; - if (iomem_addr[7:0] == 8'h00) begin - iomem_rdata <= {gpio_out, gpio_in_pad}; - if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0]; - if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8]; - end else if (iomem_addr[7:0] == 8'h04) begin - iomem_rdata <= {16'd0, gpio_oeb}; - if (iomem_wstrb[0]) gpio_oeb[ 7: 0] <= iomem_wdata[ 7: 0]; - if (iomem_wstrb[1]) gpio_oeb[15: 8] <= iomem_wdata[15: 8]; - end else if (iomem_addr[7:0] == 8'h08) begin - iomem_rdata <= {16'd0, gpio_pu}; - if (iomem_wstrb[0]) gpio_pu[ 7: 0] <= iomem_wdata[ 7: 0]; - if (iomem_wstrb[1]) gpio_pu[15: 8] <= iomem_wdata[15: 8]; - end else if (iomem_addr[7:0] == 8'h0c) begin - iomem_rdata <= {16'd0, gpio_pu}; - if (iomem_wstrb[0]) gpio_pd[ 7: 0] <= iomem_wdata[ 7: 0]; - if (iomem_wstrb[1]) gpio_pd[15: 8] <= iomem_wdata[15: 8]; - end else if (iomem_addr[7:0] == 8'h10) begin - iomem_rdata <= {31'd0, adc0_ena}; - if (iomem_wstrb[0]) adc0_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h14) begin - iomem_rdata <= {22'd0, adc0_data}; - end else if (iomem_addr[7:0] == 8'h18) begin - iomem_rdata <= {31'd0, adc0_done}; - end else if (iomem_addr[7:0] == 8'h1c) begin - iomem_rdata <= {31'd0, adc0_convert}; - if (iomem_wstrb[0]) adc0_convert <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h20) begin - iomem_rdata <= {30'd0, adc0_clksrc}; - if (iomem_wstrb[0]) adc0_clksrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h24) begin - iomem_rdata <= {30'd0, adc0_inputsrc}; - if (iomem_wstrb[0]) adc0_inputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h30) begin - iomem_rdata <= {31'd0, adc1_ena}; - if (iomem_wstrb[0]) adc1_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h34) begin - iomem_rdata <= {22'd0, adc1_data}; - end else if (iomem_addr[7:0] == 8'h38) begin - iomem_rdata <= {31'd0, adc1_done}; - end else if (iomem_addr[7:0] == 8'h3c) begin - iomem_rdata <= {31'd0, adc1_convert}; - if (iomem_wstrb[0]) adc1_convert <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h40) begin - iomem_rdata <= {30'd0, adc1_clksrc}; - if (iomem_wstrb[0]) adc1_clksrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h44) begin - iomem_rdata <= {30'd0, adc1_inputsrc}; - if (iomem_wstrb[0]) adc1_inputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h50) begin - iomem_rdata <= {31'd0, dac_ena}; - if (iomem_wstrb[0]) dac_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h54) begin - iomem_rdata <= {22'd0, dac_value}; - if (iomem_wstrb[0]) dac_value[7:0] <= iomem_wdata[7:0]; - if (iomem_wstrb[1]) dac_value[9:8] <= iomem_wdata[9:8]; - end else if (iomem_addr[7:0] == 8'h60) begin - iomem_rdata <= {31'd0, comp_ena}; - if (iomem_wstrb[0]) comp_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h64) begin - iomem_rdata <= {30'd0, comp_ninputsrc}; - if (iomem_wstrb[0]) comp_ninputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h68) begin - iomem_rdata <= {30'd0, comp_pinputsrc}; - if (iomem_wstrb[0]) comp_pinputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h6c) begin - iomem_rdata <= {30'd0, comp_output_dest}; - if (iomem_wstrb[0]) comp_output_dest <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h70) begin - iomem_rdata <= {31'd0, rcosc_ena}; - if (iomem_wstrb[0]) rcosc_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'h74) begin - iomem_rdata <= {30'd0, rcosc_output_dest}; - if (iomem_wstrb[0]) rcosc_output_dest <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'h80) begin - iomem_rdata <= {24'd0, spi_ro_config}; - end else if (iomem_addr[7:0] == 8'h84) begin - iomem_rdata <= {22'd0, spi_ro_pll_div, spi_ro_pll_sel, spi_ro_xtal_ena, spi_ro_reg_ena}; - end else if (iomem_addr[7:0] == 8'h88) begin - iomem_rdata <= {5'd0, spi_ro_pll_trim, spi_ro_pll_dco_ena}; - end else if (iomem_addr[7:0] == 8'h8c) begin - iomem_rdata <= {20'd0, spi_ro_mfgr_id}; - end else if (iomem_addr[7:0] == 8'h90) begin - iomem_rdata <= {24'd0, spi_ro_prod_id}; - end else if (iomem_addr[7:0] == 8'h94) begin - iomem_rdata <= {28'd0, spi_ro_mask_rev}; - end else if (iomem_addr[7:0] == 8'h98) begin - iomem_rdata <= {31'd0, ext_clk_sel}; - end else if (iomem_addr[7:0] == 8'ha0) begin - iomem_rdata <= {30'd0, xtal_output_dest}; - if (iomem_wstrb[0]) xtal_output_dest <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'ha4) begin - iomem_rdata <= {30'd0, pll_output_dest}; - if (iomem_wstrb[0]) pll_output_dest <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'ha8) begin - iomem_rdata <= {30'd0, trap_output_dest}; - if (iomem_wstrb[0]) trap_output_dest <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'hb0) begin - iomem_rdata <= {30'd0, irq_7_inputsrc}; - if (iomem_wstrb[0]) irq_7_inputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'hb4) begin - iomem_rdata <= {30'd0, irq_8_inputsrc}; - if (iomem_wstrb[0]) irq_8_inputsrc <= iomem_wdata[1:0]; - end else if (iomem_addr[7:0] == 8'hc0) begin - iomem_rdata <= {31'd0, analog_out_sel}; - if (iomem_wstrb[0]) analog_out_sel <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'hc4) begin - iomem_rdata <= {31'd0, opamp_bias_ena}; - if (iomem_wstrb[0]) opamp_bias_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'hc8) begin - iomem_rdata <= {31'd0, opamp_ena}; - if (iomem_wstrb[0]) opamp_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'hd0) begin - iomem_rdata <= {31'd0, bg_ena}; - if (iomem_wstrb[0]) bg_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'he0) begin - iomem_rdata <= {31'd0, overtemp_ena}; - if (iomem_wstrb[0]) overtemp_ena <= iomem_wdata[0]; - end else if (iomem_addr[7:0] == 8'he4) begin - iomem_rdata <= {31'd0, overtemp}; - end else if (iomem_addr[7:0] == 8'he8) begin - iomem_rdata <= {30'd0, overtemp_dest}; - if (iomem_wstrb[0]) overtemp_dest <= iomem_wdata[1:0]; - end - end - end - end - - openstriVe_soc_mem #(.WORDS(MEM_WORDS)) picomem ( - .clk(clk), - .ena(resetn), - .wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0), - .addr(mem_addr[23:2]), - .wdata(mem_wdata), - .rdata(ram_rdata) - ); -endmodule - -`include "picorv32.v" -`include "spimemio.v" -`include "simpleuart.v" - -// Implementation note: -// Replace the following two modules with wrappers for your SRAM cells. - -module openstriVe_soc_regs ( - input clk, wen, - input [5:0] waddr, - input [5:0] raddr1, - input [5:0] raddr2, - input [31:0] wdata, - output [31:0] rdata1, - output [31:0] rdata2 -); - reg [31:0] regs [0:31]; - - always @(posedge clk) - if (wen) regs[waddr[4:0]] <= wdata; - - assign rdata1 = regs[raddr1[4:0]]; - assign rdata2 = regs[raddr2[4:0]]; -endmodule - -module openstriVe_soc_mem #( - parameter integer WORDS = 256 -) ( - input clk, - input ena, - input [3:0] wen, - input [21:0] addr, - input [31:0] wdata, - output reg [31:0] rdata -); - reg [31:0] mem [0:WORDS-1]; - - always @(posedge clk) begin - if (ena == 1'b1) begin - rdata <= mem[addr]; - if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0]; - if (wen[1]) mem[addr][15: 8] <= wdata[15: 8]; - if (wen[2]) mem[addr][23:16] <= wdata[23:16]; - if (wen[3]) mem[addr][31:24] <= wdata[31:24]; - end - end -endmodule - -/* Convert the standard set of GPIO signals: input, output, output_enb, - * pullup, and pulldown into the set needed by the s8 GPIO pads: - * input, output, output_enb, input_enb, mode. Note that dm[2] on - * thepads is always equal to dm[1] in this setup, so mode is shown as - * only a 2-bit signal. - * - * This module is bit-sliced. Instantiate once for each GPIO pad. - */ - -module convert_gpio_sigs ( - input gpio_out, - input gpio_outenb, - input gpio_pu, - input gpio_pd, - output gpio_out_pad, - output gpio_outenb_pad, - output gpio_inenb_pad, - output gpio_mode1_pad, - output gpio_mode0_pad -); - - assign gpio_out_pad = (gpio_pu == 1'b0 && gpio_pd == 1'b0) ? gpio_out : - (gpio_pu == 1'b1) ? 1 : 0; - - assign gpio_outenb_pad = (gpio_outenb == 1'b0) ? 0 : - (gpio_pu == 1'b1 || gpio_pd == 1'b1) ? 0 : 1; - - assign gpio_inenb_pad = ~gpio_outenb; - - assign gpio_mode1_pad = ~gpio_outenb_pad; - assign gpio_mode0_pad = gpio_outenb; - -endmodule -
diff --git a/verilog/rtl/striVe_spi.v b/verilog/rtl/striVe_spi.v index 323ecf6..54643c3 100644 --- a/verilog/rtl/striVe_spi.v +++ b/verilog/rtl/striVe_spi.v
@@ -40,12 +40,12 @@ module striVe_spi( `ifdef LVS - vdd, vss, + vdd, vss, `endif - RSTB, SCK, SDI, CSB, SDO, sdo_enb, - xtal_ena, reg_ena, pll_dco_ena, pll_div, pll_sel, - pll_trim, pll_bypass, irq, reset, RST, trap, - mfgr_id, prod_id, mask_rev_in, mask_rev); + RSTB, SCK, SDI, CSB, SDO, sdo_enb, + xtal_ena, reg_ena, pll_dco_ena, pll_div, pll_sel, + pll_trim, pll_bypass, irq, reset, RST, trap, + mfgr_id, prod_id, mask_rev_in, mask_rev); `ifdef LVS inout vdd; // 3.3V supply @@ -97,16 +97,16 @@ // Instantiate the SPI slave module spi_slave U1 ( - .SCK(SCK), - .SDI(SDI), - .CSB(CSB), - .SDO(SDO), - .sdoenb(sdo_enb), - .idata(odata), - .odata(idata), - .oaddr(iaddr), - .rdstb(rdstb), - .wrstb(wrstb) + .SCK(SCK), + .SDI(SDI), + .CSB(CSB), + .SDO(SDO), + .sdoenb(sdo_enb), + .idata(odata), + .odata(idata), + .oaddr(iaddr), + .rdstb(rdstb), + .wrstb(wrstb) ); wire [11:0] mfgr_id; @@ -121,74 +121,74 @@ // All values are 1-4 bits and no shadow registers are required. assign odata = - (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed) - (iaddr == 8'h01) ? {mask_rev, mfgr_id[11:8]} : // Mask rev (metal programmed) - (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed) - (iaddr == 8'h03) ? prod_id : // Product ID (fixed) - (iaddr == 8'h04) ? {5'b00000, xtal_ena, reg_ena, pll_dco_ena} : - (iaddr == 8'h05) ? {7'b0000000, pll_bypass} : - (iaddr == 8'h06) ? {7'b0000000, irq} : - (iaddr == 8'h07) ? {7'b0000000, reset} : - (iaddr == 8'h08) ? {7'b0000000, trap} : - (iaddr == 8'h09) ? pll_trim[7:0] : - (iaddr == 8'h0a) ? pll_trim[15:8] : - (iaddr == 8'h0b) ? pll_trim[23:16] : - (iaddr == 8'h0c) ? {6'b000000, pll_trim[25:24]} : - (iaddr == 8'h0d) ? {5'b00000, pll_sel} : - (iaddr == 8'h0e) ? {3'b000, pll_div} : - 8'h00; // Default + (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed) + (iaddr == 8'h01) ? {mask_rev, mfgr_id[11:8]} : // Mask rev (metal programmed) + (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed) + (iaddr == 8'h03) ? prod_id : // Product ID (fixed) + (iaddr == 8'h04) ? {5'b00000, xtal_ena, reg_ena, pll_dco_ena} : + (iaddr == 8'h05) ? {7'b0000000, pll_bypass} : + (iaddr == 8'h06) ? {7'b0000000, irq} : + (iaddr == 8'h07) ? {7'b0000000, reset} : + (iaddr == 8'h08) ? {7'b0000000, trap} : + (iaddr == 8'h09) ? pll_trim[7:0] : + (iaddr == 8'h0a) ? pll_trim[15:8] : + (iaddr == 8'h0b) ? pll_trim[23:16] : + (iaddr == 8'h0c) ? {6'b000000, pll_trim[25:24]} : + (iaddr == 8'h0d) ? {5'b00000, pll_sel} : + (iaddr == 8'h0e) ? {3'b000, pll_div} : + 8'h00; // Default // Register mapping and I/O to slave module always @(posedge SCK or negedge RSTB) begin - if (RSTB == 1'b0) begin - // Set trim for PLL at (almost) slowest rate (~90MHz). However, - // pll_trim[12] must be set to zero for proper startup. - pll_trim <= 26'b11111111111110111111111111; - pll_sel <= 3'b000; - pll_div <= 5'b00100; // Default divide-by-8 - xtal_ena <= 1'b1; - reg_ena <= 1'b1; - pll_dco_ena <= 1'b1; // Default free-running PLL - pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL) - irq <= 1'b0; - reset <= 1'b0; - end else if (wrstb == 1'b1) begin - case (iaddr) - 8'h04: begin - pll_dco_ena <= idata[2]; - reg_ena <= idata[1]; - xtal_ena <= idata[0]; - end - 8'h05: begin - pll_bypass <= idata[0]; - end - 8'h06: begin - irq <= idata[0]; - end - 8'h07: begin - reset <= idata[0]; - end - // Register 8 is read-only - 8'h09: begin - pll_trim[7:0] <= idata; - end - 8'h0a: begin - pll_trim[15:8] <= idata; - end - 8'h0b: begin - pll_trim[23:16] <= idata; - end - 8'h0c: begin - pll_trim[25:24] <= idata[1:0]; - end - 8'h0d: begin - pll_sel <= idata[2:0]; - end - 8'h0e: begin - pll_div <= idata[4:0]; - end - endcase // (iaddr) - end + if (RSTB == 1'b0) begin + // Set trim for PLL at (almost) slowest rate (~90MHz). However, + // pll_trim[12] must be set to zero for proper startup. + pll_trim <= 26'b11111111111110111111111111; + pll_sel <= 3'b000; + pll_div <= 5'b00100; // Default divide-by-8 + xtal_ena <= 1'b1; + reg_ena <= 1'b1; + pll_dco_ena <= 1'b1; // Default free-running PLL + pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL) + irq <= 1'b0; + reset <= 1'b0; + end else if (wrstb == 1'b1) begin + case (iaddr) + 8'h04: begin + pll_dco_ena <= idata[2]; + reg_ena <= idata[1]; + xtal_ena <= idata[0]; + end + 8'h05: begin + pll_bypass <= idata[0]; + end + 8'h06: begin + irq <= idata[0]; + end + 8'h07: begin + reset <= idata[0]; + end + // Register 8 is read-only + 8'h09: begin + pll_trim[7:0] <= idata; + end + 8'h0a: begin + pll_trim[15:8] <= idata; + end + 8'h0b: begin + pll_trim[23:16] <= idata; + end + 8'h0c: begin + pll_trim[25:24] <= idata[1:0]; + end + 8'h0d: begin + pll_sel <= idata[2:0]; + end + 8'h0e: begin + pll_div <= idata[4:0]; + end + endcase // (iaddr) + end end endmodule // striVe_spi_orig
diff --git a/verilog/rtl/sysctrl.v b/verilog/rtl/sysctrl.v new file mode 100644 index 0000000..5daf5b3 --- /dev/null +++ b/verilog/rtl/sysctrl.v
@@ -0,0 +1,219 @@ +module sysctrl_wb #( + parameter BASE_ADR = 32'h2F00_0000, + parameter OSC_ENA = 8'h00, + parameter OSC_OUT = 8'h04, + parameter XTAL_OUT = 8'h08, + parameter PLL_OUT = 8'h0c, + parameter TRAP_OUT = 8'h10, + parameter IRQ7_SRC = 8'h14, + parameter IRQ8_SRC = 8'h18, + parameter OVERTEMP_ENA = 8'h1c, + parameter OVERTEMP_DATA = 8'h20, + parameter OVERTEMP_OUT = 8'h24 +) ( + input wb_clk_i, + input wb_rst_i, + + input [31:0] wb_dat_i, + input [31:0] wb_adr_i, + input [3:0] wb_sel_i, + input wb_cyc_i, + input wb_stb_i, + input wb_we_i, + + output [31:0] wb_dat_o, + output wb_ack_o, + + input overtemp, + + output rcosc_ena, + output [1:0] rcosc_output_dest, + output [1:0] xtal_output_dest, + output [1:0] pll_output_dest, + output [1:0] trap_output_dest, + output [1:0] irq_7_inputsrc, + output [1:0] irq_8_inputsrc, + output overtemp_ena, + output [1:0] overtemp_dest + +); + + wire resetn; + wire valid; + wire ready; + wire [3:0] iomem_we; + + assign resetn = ~wb_rst_i; + assign valid = wb_stb_i && wb_cyc_i; + + assign iomem_we = wb_sel_i & {4{wb_we_i}}; + assign wb_ack_o = ready; + + sysctrl #( + .BASE_ADR(BASE_ADR), + .OSC_ENA(OSC_ENA), + .OSC_OUT(OSC_OUT), + .XTAL_OUT(XTAL_OUT), + .PLL_OUT(PLL_OUT), + .TRAP_OUT(TRAP_OUT), + .IRQ7_SRC(IRQ7_SRC), + .IRQ8_SRC(IRQ8_SRC), + .OVERTEMP_ENA(OVERTEMP_ENA), + .OVERTEMP_DATA(OVERTEMP_DATA), + .OVERTEMP_OUT(OVERTEMP_OUT) + ) sysctrl ( + .clk(wb_clk_i), + .resetn(resetn), + + .overtemp(overtemp), + + .iomem_addr(wb_adr_i), + .iomem_valid(valid), + .iomem_wstrb(iomem_we), + .iomem_wdata(wb_dat_i), + .iomem_rdata(wb_dat_o), + .iomem_ready(ready), + + .rcosc_ena(rcosc_ena), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + .rcosc_output_dest(rcosc_output_dest), + .xtal_output_dest(xtal_output_dest), + .pll_output_dest(pll_output_dest), + .trap_output_dest(trap_output_dest), + + .irq_7_inputsrc(irq_7_inputsrc), + .irq_8_inputsrc(irq_8_inputsrc), + + .overtemp_ena(overtemp_ena), + .overtemp_dest(overtemp_dest) + ); + +endmodule + +module sysctrl #( + parameter BASE_ADR = 32'h2300_0000, + parameter OSC_ENA = 8'h00, + parameter OSC_OUT = 8'h04, + parameter XTAL_OUT = 8'h08, + parameter PLL_OUT = 8'h0c, + parameter TRAP_OUT = 8'h10, + parameter IRQ7_SRC = 8'h14, + parameter IRQ8_SRC = 8'h18, + parameter OVERTEMP_ENA = 8'h1c, + parameter OVERTEMP_DATA = 8'h20, + parameter OVERTEMP_OUT = 8'h24 +) ( + input clk, + input resetn, + + input overtemp, + + input [31:0] iomem_addr, + input iomem_valid, + input [3:0] iomem_wstrb, + input [31:0] iomem_wdata, + output reg [31:0] iomem_rdata, + output reg iomem_ready, + + output rcosc_ena, + output [1:0] rcosc_output_dest, + output [1:0] xtal_output_dest, + output [1:0] pll_output_dest, + output [1:0] trap_output_dest, + output [1:0] irq_7_inputsrc, + output [1:0] irq_8_inputsrc, + output overtemp_ena, + output [1:0] overtemp_dest +); + reg rcosc_ena; + reg [1:0] rcosc_output_dest; + reg [1:0] xtal_output_dest; + reg [1:0] pll_output_dest; + reg [1:0] trap_output_dest; + reg [1:0] irq_7_inputsrc; + reg [1:0] irq_8_inputsrc; + reg overtemp_ena; + reg [1:0] overtemp_dest; + + assign osc_ena_sel = (iomem_addr[7:0] == OSC_ENA); + assign osc_out_sel = (iomem_addr[7:0] == OSC_OUT); + assign pll_out_sel = (iomem_addr[7:0] == PLL_OUT); + assign trap_out_sel = (iomem_addr[7:0] == TRAP_OUT); + assign xtal_out_sel = (iomem_addr[7:0] == XTAL_OUT); + + assign irq7_sel = (iomem_addr[7:0] == IRQ7_SRC); + assign irq8_sel = (iomem_addr[7:0] == IRQ8_SRC); + + assign overtemp_sel = (iomem_addr[7:0] == OVERTEMP_DATA); + assign overtemp_ena_sel = (iomem_addr[7:0] == OVERTEMP_ENA); + assign overtemp_dest_sel = (iomem_addr[7:0] == OVERTEMP_OUT); + + always @(posedge clk) begin + if (!resetn) begin + rcosc_ena <= 0; + rcosc_output_dest <= 0; + pll_output_dest <= 0; + xtal_output_dest <= 0; + trap_output_dest <= 0; + irq_7_inputsrc <= 0; + irq_8_inputsrc <= 0; + overtemp_dest <= 0; + overtemp_ena <= 0; + end else begin + iomem_ready <= 0; + if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin + iomem_ready <= 1'b 1; + + if (osc_ena_sel) begin + iomem_rdata <= {31'd0, rcosc_ena}; + if (iomem_wstrb[0]) + rcosc_ena <= iomem_wdata[0]; + + end else if (osc_out_sel) begin + iomem_rdata <= {30'd0, rcosc_output_dest}; + if (iomem_wstrb[0]) + rcosc_output_dest <= iomem_wdata[1:0]; + + end else if (xtal_out_sel) begin + iomem_rdata <= {30'd0, xtal_output_dest}; + if (iomem_wstrb[0]) + xtal_output_dest <= iomem_wdata[1:0]; + + end else if (pll_out_sel) begin + iomem_rdata <= {30'd0, pll_output_dest}; + if (iomem_wstrb[0]) + pll_output_dest <= iomem_wdata[1:0]; + + end else if (trap_out_sel) begin + iomem_rdata <= {30'd0, trap_output_dest}; + if (iomem_wstrb[0]) + trap_output_dest <= iomem_wdata[1:0]; + + end else if (irq7_sel) begin + iomem_rdata <= {30'd0, irq_7_inputsrc}; + if (iomem_wstrb[0]) + irq_7_inputsrc <= iomem_wdata[1:0]; + + end else if (irq8_sel) begin + iomem_rdata <= {30'd0, irq_8_inputsrc}; + if (iomem_wstrb[0]) + irq_8_inputsrc <= iomem_wdata[1:0]; + + end else if (overtemp_ena_sel) begin + iomem_rdata <= {31'd0, overtemp_ena}; + if (iomem_wstrb[0]) + overtemp_ena <= iomem_wdata[0]; + + end else if (overtemp_sel) begin + iomem_rdata <= {31'd0, overtemp}; + + end else if (overtemp_dest_sel) begin + iomem_rdata <= {30'd0, overtemp_dest}; + if (iomem_wstrb[0]) + overtemp_dest <= iomem_wdata[1:0]; + + end + end + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/wb_intercon.v b/verilog/rtl/wb_intercon.v new file mode 100644 index 0000000..3a2c58f --- /dev/null +++ b/verilog/rtl/wb_intercon.v
@@ -0,0 +1,57 @@ +module wb_intercon #( + parameter DW = 32, // Data Width + parameter AW = 32, // Address Width + parameter NS = 6 // Number of Slaves +) ( + // Master Interface + input [AW-1:0] wbm_adr_i, + input wbm_stb_i, + + output reg [DW-1:0] wbm_dat_o, + output wbm_ack_o, + + // Slave Interface + input [NS*DW-1:0] wbs_dat_i, + input [NS-1:0] wbs_ack_i, + output [NS-1:0] wbs_stb_o +); + parameter [NS*AW-1:0] ADR_MASK = { // Page & Sub-page bits + {8'hFF, {24{1'b0}} }, + {8'hFF, {24{1'b0}} }, + {8'hFF, {24{1'b0}} }, + {8'hFF, {24{1'b0}} }, + {8'hFF, {24{1'b0}} }, + {8'hFF, {24{1'b0}} } + }; + parameter [NS*AW-1:0] SLAVE_ADR = { + {8'h28, {24{1'b0}} }, // Flash Configuration Register + {8'h23, {24{1'b0}} }, // System Control + {8'h21, {24{1'b0}} }, // GPIOs + {8'h20, {24{1'b0}} }, // UART + {8'h10, {24{1'b0}} }, // Flash + {8'h00, {24{1'b0}} } // RAM + }; + + wire [NS-1: 0] slave_sel; + + // Address decoder + genvar iS; + generate + for (iS = 0; iS < NS; iS = iS + 1) begin + assign slave_sel[iS] = + ((wbm_adr_i & ADR_MASK[(iS+1)*AW-1:iS*AW]) == SLAVE_ADR[(iS+1)*AW-1:iS*AW]); + end + endgenerate + + // Data-out Assignment + assign wbm_ack_o = |(wbs_ack_i & slave_sel); + assign wbs_stb_o = {NS{wbm_stb_i}} & slave_sel; + + integer i; + always @(*) begin + wbm_dat_o = {DW{1'b0}}; + for (i=0; i<(NS*DW); i=i+1) + wbm_dat_o[i%DW] = wbm_dat_o[i%DW] | (slave_sel[i/DW] & wbs_dat_i[i]); + end + +endmodule \ No newline at end of file