spi isp option added
diff --git a/openlane/pinmux/pin_order.cfg b/openlane/pinmux/pin_order.cfg
index b3273bf..baa31fd 100644
--- a/openlane/pinmux/pin_order.cfg
+++ b/openlane/pinmux/pin_order.cfg
@@ -58,6 +58,10 @@
usb_intr
uartm_rxd
uartm_txd
+spis_sck
+spis_ssn
+spis_miso
+spis_mosi
pinmux_debug\[0\] 0100 0 2
pinmux_debug\[1\]
diff --git a/openlane/user_project_wrapper/macro.cfg b/openlane/user_project_wrapper/macro.cfg
index 752b00b..7cc2709 100644
--- a/openlane/user_project_wrapper/macro.cfg
+++ b/openlane/user_project_wrapper/macro.cfg
@@ -12,4 +12,4 @@
u_intercon 1850 650 N
u_wb_host 1750 100 N
-u_pll 2200 100 N
+u_pll 2300 100 N
diff --git a/openlane/wb_host/config.tcl b/openlane/wb_host/config.tcl
index 170700c..559345a 100755
--- a/openlane/wb_host/config.tcl
+++ b/openlane/wb_host/config.tcl
@@ -58,6 +58,9 @@
$script_dir/../../verilog/rtl/uart2wb/src/uart2wb.sv \
$script_dir/../../verilog/rtl/uart2wb/src/uart2_core.sv \
$script_dir/../../verilog/rtl/uart2wb/src/uart_msg_handler.v \
+ $script_dir/../../verilog/rtl/sspis/src/sspis_top.sv \
+ $script_dir/../../verilog/rtl/sspis/src/sspis_if.sv \
+ $script_dir/../../verilog/rtl/sspis/src/spi2wb.sv \
"
set ::env(SYNTH_READ_BLACKBOX_LIB) 1
@@ -77,7 +80,7 @@
set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg
set ::env(FP_SIZING) absolute
-set ::env(DIE_AREA) "0 0 350 425"
+set ::env(DIE_AREA) "0 0 450 425"
# If you're going to use multiple power domains, then keep this disabled.
@@ -87,7 +90,7 @@
set ::env(PL_TIME_DRIVEN) 1
-set ::env(PL_TARGET_DENSITY) "0.40"
+set ::env(PL_TARGET_DENSITY) "0.45"
diff --git a/openlane/wb_host/pin_order.cfg b/openlane/wb_host/pin_order.cfg
index 17b3e01..d0a5a57 100644
--- a/openlane/wb_host/pin_order.cfg
+++ b/openlane/wb_host/pin_order.cfg
@@ -188,6 +188,12 @@
uartm_rxd 300 0 2
uartm_txd
+sclk
+ssn
+sdin
+sdout
+sdout_oen
+
dbg_clk_mon
diff --git a/signoff/user_project_wrapper/final_summary_report.csv b/signoff/user_project_wrapper/final_summary_report.csv
index 0c0a380..2ca05c4 100644
--- a/signoff/user_project_wrapper/final_summary_report.csv
+++ b/signoff/user_project_wrapper/final_summary_report.csv
@@ -1,2 +1,2 @@
,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY
-0,/home/dinesha/workarea/opencore/git/riscduino/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,0h44m39s0ms,0h3m47s0ms,-2.0,-1,-1,-1,573.63,12,0,0,0,0,0,0,-1,0,0,-1,-1,1384475,9219,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,4.78,5.62,1.36,2.43,0.0,345,3396,345,3396,0,0,0,12,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,90,0.55,0.3,sky130_fd_sc_hd,4,0
+0,/home/dinesha/workarea/opencore/git/riscduino/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,0h45m59s0ms,0h3m44s0ms,-2.0,-1,-1,-1,571.57,12,0,0,0,0,0,0,-1,0,0,-1,-1,1393564,9193,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,4.87,5.97,1.28,1.84,0.0,349,3400,349,3400,0,0,0,12,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,90,0.55,0.3,sky130_fd_sc_hd,4,0
diff --git a/verilog/dv/Makefile b/verilog/dv/Makefile
index 1d9627d..b0a4e39 100644
--- a/verilog/dv/Makefile
+++ b/verilog/dv/Makefile
@@ -19,7 +19,7 @@
.SUFFIXES:
.SILENT: clean all
-PATTERNS = wb_port risc_boot user_risc_boot user_uart user_uart1 user_qspi user_i2cm riscv_regress user_basic user_usb user_pwm user_timer user_uart_master uart_master user_sram_exec user_cache_bypass user_gpio arduino_risc_boot arduino_hello_world arduino_ascii_table arduino_multi_serial
+PATTERNS = wb_port risc_boot user_risc_boot user_uart user_uart1 user_qspi user_i2cm riscv_regress user_basic user_usb user_pwm user_timer user_uart_master uart_master user_sram_exec user_cache_bypass user_gpio arduino_risc_boot arduino_hello_world arduino_ascii_table arduino_multi_serial user_spi_isp
all: ${PATTERNS}
for i in ${PATTERNS}; do \
diff --git a/verilog/dv/bfm/bfm_spim.v b/verilog/dv/bfm/bfm_spim.v
new file mode 100644
index 0000000..f04f8b9
--- /dev/null
+++ b/verilog/dv/bfm/bfm_spim.v
@@ -0,0 +1,260 @@
+
+
+// SPI Master BFM
+// Command-1 : 0x10,
+// SI : <CMD[7:0]> <ADDR[31:0]><Dummy[7:0]>
+// SO : ------------------------------------<RDATA[31:0]>
+// Command-2 : 0x2F ,
+// SI : <CMD[7:0]> <ADDR[31:0]><WDATA[31:0]><Dummy[7:0]>
+// SO : ---------------------------------------------
+
+`timescale 1 ns / 1 ps
+`define TB_SPI_CLK_PW 100
+
+module bfm_spim (
+
+ // SPI
+ spi_clk,
+ spi_sel_n,
+ spi_din,
+ spi_dout
+
+ );
+
+output spi_clk;
+output spi_sel_n;
+output spi_din;
+input spi_dout;
+
+reg spi_clk;
+reg spi_sel_n;
+reg spi_din;
+reg error_ind;
+
+event error_detected;
+integer err_cnt;
+
+
+initial begin
+
+spi_clk = 0;
+spi_sel_n = 1;
+spi_din = 0;
+error_ind = 0;
+err_cnt = 0;
+
+end
+
+task init;
+begin
+ spi_clk=1;
+ spi_sel_n=1;
+ spi_din=1;
+end
+endtask
+
+
+always @error_detected begin
+ error_ind = 1;
+ err_cnt = err_cnt + 1;
+end
+
+
+
+task set_spi_sel_n;
+begin
+ #10;
+ spi_sel_n=0;
+ #100;
+end
+endtask
+
+task reset_spi_sel_n;
+begin
+ #10;
+ spi_sel_n=1;
+ #100;
+end
+endtask
+
+
+
+
+//-----------------------------
+// Reg Write 32 Bit
+//-----------------------------
+
+task reg_wr_dword;
+input [31:0] addr;
+input [31:0] dword;
+reg [31:0] addr;
+reg [31:0] dword;
+begin
+
+ set_spi_sel_n;
+ send_cmd(8'h2F);
+ send_dword(addr);
+ send_dword(dword);
+ send_byte(8'h0); // Dummy byte
+
+ $display("STATUS: At time %t: SPI WRITE : ADDR = %h DATA = %h ", $time, addr, dword);
+
+ reset_spi_sel_n;
+
+end
+endtask
+
+//-----------------------------
+// Reg Read 32 Bit
+//-----------------------------
+task reg_rd_dword;
+input [31:0] addr;
+output [31:0] dword;
+reg [31:0] addr;
+reg [31:0] dword;
+integer i;
+begin
+
+ set_spi_sel_n;
+ send_cmd(8'h10);
+ send_dword(addr);
+ send_byte(8'h0); // Dummy byte
+ receive_dword(dword);
+
+ $display("STATUS: At time %t: SPI READ :addr = %h data = %h ", $time, addr, dword);
+
+ reset_spi_sel_n;
+end
+endtask
+
+//-----------------------------
+// Reg Read 32 Bit compare
+//-----------------------------
+task reg_rd_dword_cmp;
+input [31:0] addr;
+input [31:0] exp_dword;
+reg [31:0] addr;
+reg [31:0] dword;
+integer i;
+begin
+
+ set_spi_sel_n;
+ send_cmd(8'h10);
+ send_dword(addr);
+ send_byte(8'h0); // Dummy byte
+ receive_dword(dword);
+
+ if (exp_dword !== dword)
+ begin
+ $display("ERROR: At time %t: SPI READ FAILED ADDR: %x EXP = %x RXD : %x ",$time,addr,exp_dword,dword);
+ -> error_detected;
+ end else begin
+ $display("STATUS: At time %t: SPI READ ADDR: %x RXD : %x ",$time,addr,dword);
+
+ end
+
+ reset_spi_sel_n;
+end
+endtask
+
+
+//-----------------------------
+// Command Byte
+//-----------------------------
+task send_cmd;
+input [7:0] data;
+begin
+begin
+ send_byte(data[7:0]);
+end
+
+end
+endtask
+// Write 4 Byte
+task send_dword;
+input dword;
+reg [31:0] dword;
+begin
+ send_word(dword[31:16]);
+ send_word(dword[15:0]);
+end
+endtask
+
+// Write 2 Byte
+task send_word;
+input word;
+reg [15:0] word;
+begin
+ send_byte(word[15:8]);
+ send_byte(word[7:0]);
+end
+endtask // spi_send_word
+
+
+
+// Write 1 Byte
+task send_byte;
+input data;
+reg [7:0] data;
+integer i;
+begin
+
+ for (i=7; i>=0; i=i-1)
+ begin
+ spi_clk=0;
+ spi_din = data[i];
+ #`TB_SPI_CLK_PW;
+ spi_clk=1;
+ // if (i != 0)
+ #`TB_SPI_CLK_PW;
+ end
+
+end
+endtask
+//----------------------------
+// READ TASK
+//----------------------------
+
+// READ 4 BYTE
+task receive_dword;
+output dword;
+reg [31:0] dword;
+begin
+ receive_word(dword[31:16]);
+ receive_word(dword[15:0]);
+end
+endtask
+
+// READ 2 BYTE
+task receive_word;
+output word;
+reg [15:0] word;
+begin
+ receive_byte(word[15:8]);
+ receive_byte(word[7:0]);
+end
+endtask
+
+
+
+// READ 1 BYTE
+task receive_byte;
+output data;
+reg [7:0] data;
+integer i;
+begin
+ for (i=7; i>=0; i=i-1)
+ begin
+ spi_clk=0;
+ #`TB_SPI_CLK_PW;
+ spi_clk=1;
+ data[i] = spi_dout;
+// if (i !=0)
+ #`TB_SPI_CLK_PW;
+ end
+
+end
+endtask
+
+endmodule
+
diff --git a/verilog/dv/user_basic/user_basic_tb.v b/verilog/dv/user_basic/user_basic_tb.v
index 27fd494..463ee91 100644
--- a/verilog/dv/user_basic/user_basic_tb.v
+++ b/verilog/dv/user_basic/user_basic_tb.v
@@ -278,8 +278,8 @@
wb_user_core_write(`ADDR_SPACE_WBHOST+`WBHOST_GLBL_CFG,'h1);
wb_user_core_read_check(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_1,read_data,32'h8273_8343);
- wb_user_core_read_check(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_2,read_data,32'h1306_2022);
- wb_user_core_read_check(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_3,read_data,32'h0004_6000);
+ wb_user_core_read_check(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_2,read_data,32'h2007_2022);
+ wb_user_core_read_check(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_3,read_data,32'h0004_8000);
end
diff --git a/verilog/dv/user_spi_isp/Makefile b/verilog/dv/user_spi_isp/Makefile
new file mode 100644
index 0000000..f655404
--- /dev/null
+++ b/verilog/dv/user_spi_isp/Makefile
@@ -0,0 +1,88 @@
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+
+
+# ---- Include Partitioned Makefiles ----
+
+CONFIG = caravel_user_project
+
+#######################################################################
+## Caravel Verilog for Integration Tests
+#######################################################################
+
+DESIGNS?=../../..
+
+export USER_PROJECT_VERILOG ?= $(DESIGNS)/verilog
+## YIFIVE FIRMWARE
+YIFIVE_FIRMWARE_PATH = $(USER_PROJECT_VERILOG)/dv/firmware
+GCC_PREFIX?=riscv32-unknown-elf
+
+
+## Simulation mode: RTL/GL
+SIM?=RTL
+DUMP?=OFF
+
+### To Enable IVERILOG FST DUMP
+export IVERILOG_DUMPER = fst
+
+
+.SUFFIXES:
+
+PATTERN = user_spi_isp
+
+all: ${PATTERN:=.vcd}
+
+
+vvp: ${PATTERN:=.vvp}
+
+%.vvp: %_tb.v
+ifeq ($(SIM),RTL)
+ ifeq ($(DUMP),OFF)
+ iverilog -g2012 -DFUNCTIONAL -DSIM -I $(PDK_PATH) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.rtl.$(CONFIG) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.rtl.lib \
+ $< -o $@
+ else
+ iverilog -g2012 -DWFDUMP -DFUNCTIONAL -DSIM -I $(PDK_PATH) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.rtl.$(CONFIG) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.rtl.lib \
+ $< -o $@
+ endif
+else
+ ifeq ($(DUMP),OFF)
+ iverilog -g2012 -DFUNCTIONAL -DUSE_POWER_PINS -DGL -I $(PDK_PATH) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.gl.$(CONFIG) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.gl.lib \
+ $< -o $@
+ else
+ iverilog -g2012 -DWFDUMP -DFUNCTIONAL -DUSE_POWER_PINS -DGL -I $(PDK_PATH) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.gl.$(CONFIG) \
+ -f$(USER_PROJECT_VERILOG)/includes/includes.gl.lib \
+ $< -o $@
+ endif
+endif
+
+%.vcd: %.vvp
+ vvp $<
+
+
+
+# ---- Clean ----
+
+clean:
+ rm -f *.elf *.hex *.bin *.vvp *.vcd *.log *.dump
+
+.PHONY: clean all
diff --git a/verilog/dv/user_spi_isp/run_iverilog b/verilog/dv/user_spi_isp/run_iverilog
new file mode 100755
index 0000000..e461fd1
--- /dev/null
+++ b/verilog/dv/user_spi_isp/run_iverilog
@@ -0,0 +1,42 @@
+# //////////////////////////////////////////////////////////////////////////////
+# // SPDX-FileCopyrightText: 2021, Dinesh Annayya
+# //
+# // Licensed under the Apache License, Version 2.0 (the "License");
+# // you may not use this file except in compliance with the License.
+# // You may obtain a copy of the License at
+# //
+# // http://www.apache.org/licenses/LICENSE-2.0
+# //
+# // Unless required by applicable law or agreed to in writing, software
+# // distributed under the License is distributed on an "AS IS" BASIS,
+# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# // See the License for the specific language governing permissions and
+# // limitations under the License.
+# // SPDX-License-Identifier: Apache-2.0
+# // SPDX-FileContributor: Dinesh Annayya <dinesha@opencores.org>
+# // //////////////////////////////////////////////////////////////////////////
+riscv64-unknown-elf-gcc -O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -D__RVC_EXT -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=1 -Wa,-march=rv32imc -march=rv32imc -mabi=ilp32 -DFLAGS_STR=\""-O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las "\" -c -I./ -I../../rtl/syntacore/scr1/sim/tests/common user_uart.c -o user_uart.o
+
+riscv64-unknown-elf-gcc -O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -D__RVC_EXT -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=1 -Wa,-march=rv32imc -march=rv32imc -mabi=ilp32 -DFLAGS_STR=\""-O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las "\" -D__ASSEMBLY__=1 -c -I./ -I../../rtl/syntacore/scr1/sim/tests/common/ ../../rtl/syntacore/scr1/sim/tests/common/crt_tcm.S -o crt_tcm.o
+
+riscv64-unknown-elf-gcc -o user_uart.elf -T ../../rtl/syntacore/scr1/sim/tests/common/link_tcm.ld user_uart.o crt_tcm.o -nostartfiles -nostdlib -lc -lgcc -march=rv32imc -mabi=ilp32
+
+riscv64-unknown-elf-objcopy -O verilog user_uart.elf user_uart.hex
+
+riscv64-unknown-elf-objdump -D user_uart.elf > user_uart.dump
+
+rm crt_tcm.o user_uart.o
+
+#iverilog with waveform dump
+iverilog -g2005-sv -DWFDUMP -DFUNCTIONAL -DSIM -I $PDK_PATH -I ../../../caravel/verilog/rtl -I ../ -I ../../../verilog/rtl -I ../ -I ../../../verilog -I ../../../verilog/rtl/syntacore/scr1/src/includes -I ../../../verilog/rtl/sdram_ctrl/src/defs -I ../../../verilog/rtl/i2cm/src/includes -I ../../../verilog/rtl/usb1_host/src/includes -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_uart_tb.v -o user_uart_tb.vvp
+
+
+#iverilog -g2005-sv -I $PDK_PATH -DFUNCTIONAL -DSIM -I ../../../caravel/verilog/rtl -I ../ -I ../../../verilog/rtl -I ../../../verilog -I ../../../verilog/rtl/syntacore/scr1/src/includes -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_uart_tb.v -o user_uart_tb.vvp
+
+# GLS
+#iverilog -g2005-sv -D GL -D FUNCTIONAL -I $PDK_PATH -I ../../../caravel/verilog/rtl -I ../ -I ../../../verilog/gl -I ../../../verilog -I /home/dinesha/workarea/pdk/sky130A -I ../../../verilog/rtl/syntacore/scr1/src/includes -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_uart_tb.v -o user_uart_tb.vvp
+#
+
+vvp user_uart_tb.vvp | tee test.log
+
+\rm -rf user_uart_tb.vvp
diff --git a/verilog/dv/user_spi_isp/user_spi_isp_tb.v b/verilog/dv/user_spi_isp/user_spi_isp_tb.v
new file mode 100644
index 0000000..a0e0fb5
--- /dev/null
+++ b/verilog/dv/user_spi_isp/user_spi_isp_tb.v
@@ -0,0 +1,254 @@
+////////////////////////////////////////////////////////////////////////////
+// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileContributor: Modified by Dinesh Annayya <dinesha@opencores.org>
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Standalone User validation Test bench ////
+//// ////
+//// This file is part of the Riscduino cores project ////
+//// https://github.com/dineshannayya/riscduino.git ////
+//// ////
+//// Description ////
+//// This is a standalone test bench to validate the ////
+//// Digital core using spi isp i/f. ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// 0.1 - 20th Feb 2022, Dinesh A ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`default_nettype wire
+
+`timescale 1 ns / 1 ps
+
+`include "sram_macros/sky130_sram_2kbyte_1rw1r_32x512_8.v"
+`include "bfm_spim.v"
+
+module user_spi_isp_tb;
+
+reg clock ;
+reg wb_rst_i ;
+reg power1, power2;
+reg power3, power4;
+
+reg wbd_ext_cyc_i; // strobe/request
+reg wbd_ext_stb_i; // strobe/request
+reg [31:0] wbd_ext_adr_i; // address
+reg wbd_ext_we_i; // write
+reg [31:0] wbd_ext_dat_i; // data output
+reg [3:0] wbd_ext_sel_i; // byte enable
+
+wire [31:0] wbd_ext_dat_o; // data input
+wire wbd_ext_ack_o; // acknowlegement
+wire wbd_ext_err_o; // error
+
+// User I/O
+wire [37:0] io_oeb ;
+wire [37:0] io_out ;
+wire [37:0] io_in ;
+
+wire [37:0] mprj_io ;
+wire [7:0] mprj_io_0 ;
+reg test_fail ;
+reg [31:0] read_data ;
+
+reg [127:0] la_data_in;
+reg flag;
+
+// SCLK
+wire sclk;
+wire ssn;
+wire sdi;
+wire sdo;
+wire sd_oen;
+
+integer i,j;
+
+ // 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 clock <= (clock === 1'b0);
+
+ initial begin
+ clock = 0;
+ la_data_in = 1;
+ end
+
+ `ifdef WFDUMP
+ initial begin
+ $dumpfile("simx.vcd");
+ $dumpvars(0, user_spi_isp_tb);
+ end
+ `endif
+
+ initial begin
+ clock = 0;
+ wbd_ext_cyc_i ='h0; // strobe/request
+ wbd_ext_stb_i ='h0; // strobe/request
+ wbd_ext_adr_i ='h0; // address
+ wbd_ext_we_i ='h0; // write
+ wbd_ext_dat_i ='h0; // data output
+ wbd_ext_sel_i ='h0; // byte enable
+ end
+initial
+begin
+ wb_rst_i <= 1'b1;
+
+ #100;
+ wb_rst_i <= 1'b0; // Release reset
+
+ $display("Monitor: Standalone User SPI ISP Test Started");
+
+
+ // Remove Wb Reset
+ u_spim.reg_wr_dword(`ADDR_SPACE_WBHOST+`WBHOST_GLBL_CFG,'h1);
+
+ repeat (2) @(posedge clock);
+ #1;
+
+ $display("Monitor: Writing expected value");
+
+ test_fail = 0;
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_1,32'h11223344);
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_2,32'h22334455);
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_3,32'h33445566);
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_4,32'h44556677);
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_5,32'h55667788);
+ u_spim.reg_wr_dword(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_6,32'h66778899);
+
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_1,32'h11223344);
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_2,32'h22334455);
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_3,32'h33445566);
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_4,32'h44556677);
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_5,32'h55667788);
+ u_spim.reg_rd_dword_cmp(`ADDR_SPACE_PINMUX+`PINMUX_SOFT_REG_6,32'h66778899);
+
+
+
+ $display("###################################################");
+ if(u_spim.err_cnt == 0) begin
+ `ifdef GL
+ $display("Monitor: Standalone User SPI ISP (GL) Passed");
+ `else
+ $display("Monitor: Standalone User SPI ISP (RTL) Passed");
+ `endif
+ end else begin
+ `ifdef GL
+ $display("Monitor: Standalone User SPI ISP (GL) Failed");
+ `else
+ $display("Monitor: Standalone User SPI ISP (RTL) Failed");
+ `endif
+ end
+ $display("###################################################");
+ #100
+ $finish;
+end
+
+
+wire USER_VDD1V8 = 1'b1;
+wire VSS = 1'b0;
+
+
+user_project_wrapper u_top(
+`ifdef USE_POWER_PINS
+ .vccd1(USER_VDD1V8), // User area 1 1.8V supply
+ .vssd1(VSS), // User area 1 digital ground
+`endif
+ .wb_clk_i (clock), // System clock
+ .user_clock2 (1'b1), // Real-time clock
+ .wb_rst_i (wb_rst_i), // Regular Reset signal
+
+ .wbs_cyc_i (wbd_ext_cyc_i), // strobe/request
+ .wbs_stb_i (wbd_ext_stb_i), // strobe/request
+ .wbs_adr_i (wbd_ext_adr_i), // address
+ .wbs_we_i (wbd_ext_we_i), // write
+ .wbs_dat_i (wbd_ext_dat_i), // data output
+ .wbs_sel_i (wbd_ext_sel_i), // byte enable
+
+ .wbs_dat_o (wbd_ext_dat_o), // data input
+ .wbs_ack_o (wbd_ext_ack_o), // acknowlegement
+
+
+ // Logic Analyzer Signals
+ .la_data_in (la_data_in) ,
+ .la_data_out (),
+ .la_oenb ('0),
+
+
+ // IOs
+ .io_in (io_in) ,
+ .io_out (io_out) ,
+ .io_oeb (io_oeb) ,
+
+ .user_irq ()
+
+);
+
+`ifndef GL // Drive Power for Hold Fix Buf
+ // All standard cell need power hook-up for functionality work
+ initial begin
+ end
+`endif
+
+assign io_in[0] = 1'b0;
+assign io_in[16] = sclk;
+assign io_in[15] = sdi;
+assign sdo = io_out[14];
+
+bfm_spim u_spim (
+ // SPI
+ .spi_clk (sclk ),
+ .spi_sel_n (ssn ),
+ .spi_din (sdi ),
+ .spi_dout (sdo )
+
+ );
+
+
+endmodule
+`default_nettype wire
diff --git a/verilog/dv/user_sspi/user_sspi_tb.v b/verilog/dv/user_sspi/user_sspi_tb.v
index 1e81542..c8e3f5c 100644
--- a/verilog/dv/user_sspi/user_sspi_tb.v
+++ b/verilog/dv/user_sspi/user_sspi_tb.v
@@ -140,7 +140,9 @@
wb_user_core_write(`ADDR_SPACE_WBHOST+`WBHOST_GLBL_CFG,'h1);
// Enable SPI Multi Functional Ports
- wb_user_core_write(`ADDR_SPACE_PINMUX+`PINMUX_GPIO_MULTI_FUNC,'h3C00);
+ // wire cfg_spim_enb = cfg_multi_func_sel[10];
+ // wire [3:0] cfg_spim_cs_enb = cfg_multi_func_sel[14:11];
+ wb_user_core_write(`ADDR_SPACE_PINMUX+`PINMUX_GPIO_MULTI_FUNC,'h7C00);
repeat (2) @(posedge clock);
#1;
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project
index 5802940..d803dab 100644
--- a/verilog/includes/includes.rtl.caravel_user_project
+++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -53,6 +53,9 @@
-v $(USER_PROJECT_VERILOG)/rtl/lib/ser_shift.sv
-v $(USER_PROJECT_VERILOG)/rtl/digital_core/src/glbl_cfg.sv
-v $(USER_PROJECT_VERILOG)/rtl/wb_host/src/wb_host.sv
+-v $(USER_PROJECT_VERILOG)/rtl/sspis/src/sspis_top.sv
+-v $(USER_PROJECT_VERILOG)/rtl/sspis/src/sspis_if.sv
+-v $(USER_PROJECT_VERILOG)/rtl/sspis/src/spi2wb.sv
-v $(USER_PROJECT_VERILOG)/rtl/lib/async_wb.sv
-v $(USER_PROJECT_VERILOG)/rtl/lib/sync_wbb.sv
-v $(USER_PROJECT_VERILOG)/rtl/lib/sync_fifo2.sv
diff --git a/verilog/rtl/pinmux/src/pinmux.sv b/verilog/rtl/pinmux/src/pinmux.sv
index b9949c5..e36556c 100755
--- a/verilog/rtl/pinmux/src/pinmux.sv
+++ b/verilog/rtl/pinmux/src/pinmux.sv
@@ -37,6 +37,14 @@
//// 0.2 - 6 April 2021, Dinesh A ////
//// 1. SSPI CS# increased from 1 to 4 ////
// 2. UART I/F increase from 1 to 2 ////
+//// 0.3 - 8 July 2022, Dinesh A ////
+//// In ardunio, SPI chip select are control through ////
+//// GPIO, So we have moved the Auto generated SPI CS ////
+//// different config bit. I2C config position moved from////
+//// bit[14] to bit [15] ////
+//// 0.4 - 20 July 2022, Dinesh A ////
+//// On Power On, If RESET* = 0, then system will enter ////
+//// in to SPIS slave mode to support boot ////
//////////////////////////////////////////////////////////////////////
module pinmux (
@@ -125,6 +133,12 @@
input logic [3:0] spim_ssn,
input logic spim_miso,
output logic spim_mosi,
+
+ // SPI SLAVE
+ output logic spis_sck,
+ output logic spis_ssn,
+ input logic spis_miso,
+ output logic spis_mosi,
// UART MASTER I/F
output logic uartm_rxd ,
@@ -548,8 +562,9 @@
assign cfg_pwm_enb = cfg_multi_func_sel[5:0];
wire [1:0] cfg_int_enb = cfg_multi_func_sel[7:6];
wire [1:0] cfg_uart_enb = cfg_multi_func_sel[9:8];
-wire [3:0] cfg_spim_enb = cfg_multi_func_sel[13:10];
-wire cfg_i2cm_enb = cfg_multi_func_sel[14];
+wire cfg_spim_enb = cfg_multi_func_sel[10];
+wire [3:0] cfg_spim_cs_enb = cfg_multi_func_sel[14:11];
+wire cfg_i2cm_enb = cfg_multi_func_sel[15];
wire [7:0] cfg_port_a_dir_sel = cfg_gpio_dir_sel[7:0];
wire [7:0] cfg_port_b_dir_sel = cfg_gpio_dir_sel[15:8];
@@ -557,6 +572,14 @@
wire [7:0] cfg_port_d_dir_sel = cfg_gpio_dir_sel[31:24];
+// This logic to create spi slave interface
+logic pin_resetn,spis_boot;
+
+// On Reset internal SPI Master is disabled, If pin_reset = 0, then we are in
+// SPIS Boot Mode
+assign spis_boot = (cfg_spim_enb ) ? 1'b0: !pin_resetn;
+assign spis_ssn = (spis_boot ) ? pin_resetn : 1'b1;
+
// datain selection
always_comb begin
port_a_in = 'h0;
@@ -571,6 +594,7 @@
//Pin-1 PC6/RESET* digital_io[0]
port_c_in[6] = digital_io_in[0];
+ pin_resetn = digital_io_in[0];
//Pin-2 PD0/RXD[0] digital_io[1]
port_d_in[0] = digital_io_in[1];
@@ -618,13 +642,15 @@
//Pin-17 PB3/MOSI/OC2A(PWM5) digital_io[14]
port_b_in[3] = digital_io_in[14];
- if(cfg_spim_enb[0]) spim_mosi = digital_io_in[14];
+ if(cfg_spim_enb) spim_mosi = digital_io_in[14]; // SPIM MOSI (Input) = SPIS MISO (Output)
//Pin-18 PB4/MISO digital_io[15]
port_b_in[4] = digital_io_in[15];
+ spis_mosi = (spis_boot) ? digital_io_in[15] : 1'b0; // SPIM MISO (Output) = SPIS MOSI (Input)
//Pin-19 PB5/SCK digital_io[16]
port_b_in[5]= digital_io_in[16];
+ spis_sck = (spis_boot) ? digital_io_in[16] : 1'b1; // SPIM SCK (Output) = SPIS SCK (Input)
//Pin-23 PC0/ADC0 digital_io[18]/analog_io[11]
port_c_in[0] = digital_io_in[18];
@@ -692,12 +718,12 @@
//Pin-11 PD5/SS[3]/OC0B(PWM1)/T1 digital_io[8]
if(cfg_pwm_enb[1]) digital_io_out[8] = pwm_wfm[1];
- else if(cfg_spim_enb[3]) digital_io_out[8] = spim_ssn[3];
+ else if(cfg_spim_cs_enb[3]) digital_io_out[8] = spim_ssn[3];
else if(cfg_port_d_dir_sel[5]) digital_io_out[8] = port_d_out[5];
//Pin-12 PD6/SS[2]/OC0A(PWM2)/AIN0 digital_io[9] /analog_io[2]
if(cfg_pwm_enb[2]) digital_io_out[9] = pwm_wfm[2];
- else if(cfg_spim_enb[2]) digital_io_out[9] = spim_ssn[2];
+ else if(cfg_spim_cs_enb[2]) digital_io_out[9] = spim_ssn[2];
else if(cfg_port_d_dir_sel[6]) digital_io_out[9] = port_d_out[6];
@@ -709,24 +735,25 @@
//Pin-15 PB1/SS[1]/OC1A(PWM3) digital_io[12]
if(cfg_pwm_enb[3]) digital_io_out[12] = pwm_wfm[3];
- else if(cfg_spim_enb[1]) digital_io_out[12] = spim_ssn[1];
+ else if(cfg_spim_cs_enb[1]) digital_io_out[12] = spim_ssn[1];
else if(cfg_port_b_dir_sel[1]) digital_io_out[12] = port_b_out[1];
//Pin-16 PB2/SS[0]/OC1B(PWM4) digital_io[13]
if(cfg_pwm_enb[4]) digital_io_out[13] = pwm_wfm[4];
- else if(cfg_spim_enb[0]) digital_io_out[13] = spim_ssn[0];
+ else if(cfg_spim_cs_enb[0]) digital_io_out[13] = spim_ssn[0];
else if(cfg_port_b_dir_sel[2]) digital_io_out[13] = port_b_out[2];
//Pin-17 PB3/MOSI/OC2A(PWM5) digital_io[14]
if(cfg_pwm_enb[5]) digital_io_out[14] = pwm_wfm[5];
else if(cfg_port_b_dir_sel[3]) digital_io_out[14] = port_b_out[3];
+ else if(spis_boot) digital_io_out[14] = spis_miso; // SPIM MOSI (Input) = SPIS MISO (Output)
//Pin-18 PB4/MISO digital_io[15]
- if(cfg_spim_enb[0]) digital_io_out[15] = spim_miso;
+ if(cfg_spim_enb) digital_io_out[15] = spim_miso; // SPIM MISO (Output) = SPIS MOSI (Input)
else if(cfg_port_b_dir_sel[4]) digital_io_out[15] = port_b_out[4];
//Pin-19 PB5/SCK digital_io[16]
- if(cfg_spim_enb[0]) digital_io_out[16] = spim_sck;
+ if(cfg_spim_enb) digital_io_out[16] = spim_sck; // SPIM SCK (Output) = SPIS SCK (Input)
else if(cfg_port_b_dir_sel[5]) digital_io_out[16] = port_b_out[5];
//Pin-23 PC0/ADC0 digital_io[18]/analog_io[11]
@@ -808,12 +835,12 @@
//Pin-11 PD5/SS[3]/OC0B(PWM1)/T1 digital_io[8]
if(cfg_pwm_enb[1]) digital_io_oen[8] = 1'b0;
- else if(cfg_spim_enb[3]) digital_io_oen[8] = 1'b0;
+ else if(cfg_spim_cs_enb[3]) digital_io_oen[8] = 1'b0;
else if(cfg_port_d_dir_sel[5]) digital_io_oen[8] = 1'b0;
//Pin-12 PD6/SS[2]/OC0A(PWM2)/AIN0 digital_io[9] /analog_io[2]
if(cfg_pwm_enb[2]) digital_io_oen[9] = 1'b0;
- else if(cfg_spim_enb[2]) digital_io_oen[9] = 1'b0;
+ else if(cfg_spim_cs_enb[2]) digital_io_oen[9] = 1'b0;
else if(cfg_port_d_dir_sel[6]) digital_io_oen[9] = 1'b0;
//Pin-13 PD7/A1N1 digital_io[10]/analog_io[3]
@@ -824,26 +851,29 @@
//Pin-15 PB1/SS[1]/OC1A(PWM3) digital_io[12]
if(cfg_pwm_enb[3]) digital_io_oen[12] = 1'b0;
- else if(cfg_spim_enb[1]) digital_io_oen[12] = 1'b0;
+ else if(cfg_spim_cs_enb[1]) digital_io_oen[12] = 1'b0;
else if(cfg_port_b_dir_sel[1]) digital_io_oen[12] = 1'b0;
//Pin-16 PB2/SS[0]/OC1B(PWM4) digital_io[13]
if(cfg_pwm_enb[4]) digital_io_oen[13] = 1'b0;
- else if(cfg_spim_enb[0]) digital_io_oen[13] = 1'b0;
+ else if(cfg_spim_cs_enb[0]) digital_io_oen[13] = 1'b0;
else if(cfg_port_b_dir_sel[2]) digital_io_oen[13] = 1'b0;
//Pin-17 PB3/MOSI/OC2A(PWM5) digital_io[14]
- if(cfg_spim_enb[0]) digital_io_oen[14] = 1'b1;
+ if(cfg_spim_enb) digital_io_oen[14] = 1'b1; // SPIM MOSI (Input)
else if(cfg_pwm_enb[5]) digital_io_oen[14] = 1'b0;
else if(cfg_port_b_dir_sel[3]) digital_io_oen[14] = 1'b0;
+ else if(spis_boot) digital_io_oen[14] = 1'b0; // SPIS MISO (Output)
//Pin-18 PB4/MISO digital_io[15]
- if(cfg_spim_enb[0]) digital_io_oen[15] = 1'b0;
+ if(cfg_spim_enb) digital_io_oen[15] = 1'b0; // SPIM MISO (Output)
else if(cfg_port_b_dir_sel[4]) digital_io_oen[15] = 1'b0;
+ else if(spis_boot) digital_io_oen[15] = 1'b1; // SPIS MOSI (Input)
//Pin-19 PB5/SCK digital_io[16]
- if(cfg_spim_enb[0]) digital_io_oen[16] = 1'b0;
+ if(cfg_spim_enb) digital_io_oen[16] = 1'b0; // SPIM SCK (Output)
else if(cfg_port_b_dir_sel[5]) digital_io_oen[16] = 1'b0;
+ else if(spis_boot) digital_io_oen[16] = 1'b1; // SPIS SCK (Input)
//Pin-23 PC0/ADC0 digital_io[18]/analog_io[11]
if(cfg_port_c_dir_sel[0]) digital_io_oen[18] = 1'b0;
diff --git a/verilog/rtl/pinmux/src/pinmux_reg.sv b/verilog/rtl/pinmux/src/pinmux_reg.sv
index 2d972d8..32b812a 100644
--- a/verilog/rtl/pinmux/src/pinmux_reg.sv
+++ b/verilog/rtl/pinmux/src/pinmux_reg.sv
@@ -716,7 +716,7 @@
//-----------------------------------------
// Software Reg-2, Release date: <DAY><MONTH><YEAR>
// ----------------------------------------
-gen_32b_reg #(32'h1306_2022) u_reg_23 (
+gen_32b_reg #(32'h2007_2022) u_reg_23 (
//List of Inputs
.reset_n (h_reset_n ),
.clk (mclk ),
@@ -729,9 +729,9 @@
);
//-----------------------------------------
-// Software Reg-3: Poject Revison 4.6 = 0004600
+// Software Reg-3: Poject Revison 4.7 = 0004800
// ----------------------------------------
-gen_32b_reg #(32'h0004_6000) u_reg_24 (
+gen_32b_reg #(32'h0004_8000) u_reg_24 (
//List of Inputs
.reset_n (h_reset_n ),
.clk (mclk ),
diff --git a/verilog/rtl/sspis/src/spi2wb.sv b/verilog/rtl/sspis/src/spi2wb.sv
new file mode 100644
index 0000000..76f52d6
--- /dev/null
+++ b/verilog/rtl/sspis/src/spi2wb.sv
@@ -0,0 +1,76 @@
+//////////////////////////////////////////////////////////////////////////////
+// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
+//
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Reg2WB Interface ////
+//// ////
+//// This file is part of the riscduino cores project ////
+//// https://github.com/dineshannayya/riscduino.git ////
+//// ////
+//// Description : This module contains Register To Wishbone ////
+//// Translation ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesh.annayya@gmail.com ////
+//// ////
+//// Revision : ////
+//// 0.1 - 20th July 2022, Dinesh A ////
+//// Initial version ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module spi2wb(
+
+ //spis_if Interface
+ input logic reg_wr , // write request
+ input logic reg_rd , // read request
+ input logic [31:0] reg_addr , // address
+ input logic [3:0] reg_be , // Byte enable
+ input logic [31:0] reg_wdata , // write data
+ output logic [31:0] reg_rdata , // read data
+ output logic reg_ack , // read valid
+
+ // WB Master Port
+ output logic wbm_cyc_o , // strobe/request
+ output logic wbm_stb_o , // strobe/request
+ output logic [31:0] wbm_adr_o , // address
+ output logic wbm_we_o , // write
+ output logic [31:0] wbm_dat_o , // data output
+ output logic [3:0] wbm_sel_o , // byte enable
+ input logic [31:0] wbm_dat_i , // data input
+ input logic wbm_ack_i , // acknowlegement
+ input logic wbm_err_i // error
+
+);
+
+
+
+assign wbm_cyc_o = reg_wr | reg_rd;
+assign wbm_stb_o = reg_wr | reg_rd;
+assign wbm_adr_o = reg_addr;
+assign wbm_we_o = reg_wr;
+assign wbm_sel_o = reg_be;
+assign wbm_dat_o = reg_wdata;
+assign reg_rdata = wbm_dat_i;
+assign reg_ack = wbm_ack_i;
+
+
+endmodule
diff --git a/verilog/rtl/sspis/src/sspis_if.sv b/verilog/rtl/sspis/src/sspis_if.sv
new file mode 100644
index 0000000..10a5d1d
--- /dev/null
+++ b/verilog/rtl/sspis/src/sspis_if.sv
@@ -0,0 +1,310 @@
+//////////////////////////////////////////////////////////////////////////////
+// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
+//
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// SPI Interface ////
+//// ////
+//// This file is part of the riscduino cores project ////
+//// https://github.com/dineshannayya/riscduino.git ////
+//// ////
+//// Description : This module contains SPI interface ////
+//// state machine ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesh.annayya@gmail.com ////
+//// ////
+//// Revision : ////
+//// 0.1 - 20th July 2022, Dinesh A ////
+//// Initial version ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+/*********************************************************************
+ CMD Decoding [7:0]
+ [7:4] = 4'b1 - READ REGISTER
+ = 4'b2 - WRITE REGISTER
+ [3:0] = Byte Enable valid only during Write Command
+*********************************************************************/
+
+module sspis_if (
+
+ input logic sys_clk ,
+ input logic rst_n ,
+
+ input logic sclk ,
+ input logic ssn ,
+ input logic sdin ,
+ output logic sdout ,
+ output logic sdout_oen ,
+
+ //spi_sm Interface
+ output logic reg_wr , // write request
+ output logic reg_rd , // read request
+ output logic [31:0] reg_addr , // address
+ output logic [3:0] reg_be , // Byte enable
+ output logic [31:0] reg_wdata , // write data
+ input logic [31:0] reg_rdata , // read data
+ input logic reg_ack // read valid
+ );
+
+
+//--------------------------------------------------------
+// Wire and reg definitions
+// -------------------------------------------------------
+
+reg [5:0] bitcnt ;
+reg [7:0] cmd_reg ;
+reg [31:0] RegSdOut ;
+reg [2:0] spi_if_st ;
+
+parameter idle_st = 3'b000,
+ cmd_st = 3'b001,
+ adr_st = 3'b010,
+ wr_st = 3'b011,
+ wwait_st = 3'b100,
+ rwait_st = 3'b101,
+ rd_st = 3'b110;
+
+parameter READ_CMD = 4'h1,
+ WRITE_CMD = 4'h2;
+
+
+wire adr_phase = (spi_if_st == adr_st);
+wire cmd_phase = (spi_if_st == cmd_st);
+wire wr_phase = (spi_if_st == wr_st);
+wire rd_phase = (spi_if_st == rd_st);
+wire cnt_phase = (spi_if_st != wwait_st) && (spi_if_st != rwait_st);
+wire wwait_phase = (spi_if_st == wwait_st);
+wire rwait_phase = (spi_if_st == rwait_st);
+
+
+
+
+// sclk pos and ned edge generation
+logic sck_l0,sck_l1,sck_l2;
+
+assign sck_pdetect = (!sck_l2 && sck_l1) ? 1'b1: 1'b0;
+assign sck_ndetect = (sck_l2 && !sck_l1) ? 1'b1: 1'b0;
+
+always @ (posedge sys_clk or negedge rst_n) begin
+if (!rst_n) begin
+ sck_l0 <= 1'b1;
+ sck_l1 <= 1'b1;
+ sck_l2 <= 1'b1;
+ end
+ else begin
+ sck_l0 <= sclk;
+ sck_l1 <= sck_l0; // double sync
+ sck_l2 <= sck_l1;
+ end
+end
+
+// SSN double sync
+logic ssn_l0,ssn_l1, ssn_ss;
+
+assign ssn_ss = ssn_l1;
+
+always @ (posedge sys_clk or negedge rst_n) begin
+if (!rst_n) begin
+ ssn_l0 <= 1'b1;
+ ssn_l1 <= 1'b1;
+ end
+ else begin
+ ssn_l0 <= ssn;
+ ssn_l1 <= ssn_l0; // double sync
+ end
+end
+
+
+//command register accumation
+assign reg_be = cmd_reg[3:0];
+
+always @(negedge rst_n or posedge sys_clk)
+begin
+ if (!rst_n)
+ cmd_reg[7:0] <= 8'b0;
+ else if (cmd_phase & (sck_pdetect))
+ cmd_reg[7:0] <= {cmd_reg[6:0], sdin};
+end
+
+
+// address accumation at posedge sclk
+always @(negedge rst_n or posedge sys_clk)
+begin
+ if (!rst_n)
+ reg_addr[31:0] <= 32'b0;
+ else if (adr_phase & (sck_pdetect))
+ reg_addr[31:0] <= {reg_addr[30:0], sdin};
+end
+
+// write data accumation at posedge sclk
+always @(negedge rst_n or posedge sys_clk)
+begin
+ if (!rst_n)
+ reg_wdata[31:0] <= 32'b0;
+ else if (wr_phase & (sck_pdetect))
+ reg_wdata[31:0] <= {reg_wdata[30:0], sdin};
+end
+
+
+
+// drive sdout at negedge sclk
+always @(negedge rst_n or posedge sys_clk)
+begin
+ if (!rst_n) begin
+ RegSdOut[31:0] <= 32'b0;
+ sdout <= 1'b0;
+ end else begin
+ if (reg_ack)
+ RegSdOut <= reg_rdata[31:0];
+ else if (rd_phase && sck_ndetect)
+ RegSdOut <= {RegSdOut[30:0], 1'b0};
+
+ sdout <= (rd_phase && sck_ndetect) ? RegSdOut[31] : sdout;
+ end
+end
+
+
+// SPI State Machine
+always @(negedge rst_n or posedge sys_clk)
+begin
+ if (!rst_n) begin
+ reg_wr <= 1'b0;
+ reg_rd <= 1'b0;
+ sdout_oen <= 1'b1;
+ bitcnt <= 6'b0;
+ spi_if_st <= idle_st;
+ end else if(ssn_ss) begin
+ reg_wr <= 1'b0;
+ reg_rd <= 1'b0;
+ sdout_oen <= 1'b1;
+ bitcnt <= 6'b0;
+ spi_if_st <= idle_st;
+ end else begin
+ case (spi_if_st)
+ idle_st : begin // Idle State
+ reg_wr <= 1'b0;
+ reg_rd <= 1'b0;
+ sdout_oen <= 1'b1;
+ bitcnt <= 6'b0;
+ if (ssn_ss == 1'b0) begin
+ spi_if_st <= cmd_st;
+ end
+ end
+
+ cmd_st : begin // Command State
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if(bitcnt == 6'b000111) begin
+ bitcnt <= 6'b0;
+ spi_if_st <= adr_st;
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+
+ adr_st : begin // Address Phase
+ reg_wr <= 1'b0;
+ reg_rd <= 1'b0;
+ sdout_oen <= 1'b1;
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if (bitcnt == 6'b011111) begin
+ bitcnt <= 6'b0;
+ if(cmd_reg[7:4] == READ_CMD) begin
+ spi_if_st <= rwait_st;
+ reg_rd <= 1'b1;
+ end else if(cmd_reg[7:4] == WRITE_CMD) begin
+ spi_if_st <= wr_st;
+ end else begin
+ spi_if_st <= cmd_st;
+ end
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+
+ wr_st : begin // Write State
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if (bitcnt == 6'b011111) begin
+ bitcnt <= 6'b0;
+ spi_if_st <= wwait_st;
+ reg_wr <= 1;
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+ wwait_st : begin // Register Bus Busy Check State
+ if(reg_ack) reg_wr <= 0;
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if (bitcnt == 6'b000111) begin
+ bitcnt <= 6'b0;
+ spi_if_st <= cmd_st;
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+
+ rwait_st : begin // Read Wait State
+ if(reg_ack) reg_rd <= 1'b0;
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if (bitcnt == 6'b000111) begin
+ reg_rd <= 1'b0;
+ bitcnt <= 6'b0;
+ sdout_oen <= 1'b0;
+ spi_if_st <= rd_st;
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+
+ rd_st : begin // Send Data to SPI
+ if (ssn_ss == 1'b1) begin
+ spi_if_st <= idle_st;
+ end else if (sck_pdetect) begin
+ if (bitcnt == 6'b011111) begin
+ bitcnt <= 6'b0;
+ sdout_oen <= 1'b1;
+ spi_if_st <= cmd_st;
+ end else begin
+ bitcnt <= bitcnt +1;
+ end
+ end
+ end
+
+ default : spi_if_st <= idle_st;
+ endcase
+ end
+end
+
+endmodule
diff --git a/verilog/rtl/sspis/src/sspis_top.sv b/verilog/rtl/sspis/src/sspis_top.sv
new file mode 100644
index 0000000..e42d630
--- /dev/null
+++ b/verilog/rtl/sspis/src/sspis_top.sv
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////
+// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
+//
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// SPI With Wishbone ////
+//// ////
+//// This file is part of the riscduino cores project ////
+//// https://github.com/dineshannayya/riscduino.git ////
+//// ////
+//// Description : This module contains SPI interface + WB Master////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesh.annayya@gmail.com ////
+//// ////
+//// Revision : ////
+//// 0.1 - 20th July 2022, Dinesh A ////
+//// Initial version ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module sspis_top (
+
+ input logic sys_clk ,
+ input logic rst_n ,
+
+ input logic sclk ,
+ input logic ssn ,
+ input logic sdin ,
+ output logic sdout ,
+ output logic sdout_oen ,
+
+ // WB Master Port
+ output logic wbm_cyc_o , // strobe/request
+ output logic wbm_stb_o , // strobe/request
+ output logic [31:0] wbm_adr_o , // address
+ output logic wbm_we_o , // write
+ output logic [31:0] wbm_dat_o , // data output
+ output logic [3:0] wbm_sel_o , // byte enable
+ input logic [31:0] wbm_dat_i , // data input
+ input logic wbm_ack_i , // acknowlegement
+ input logic wbm_err_i // error
+ );
+
+//-----------------------------------
+// Register I/F
+//-----------------------------------
+
+logic reg_wr ; // write request
+logic reg_rd ; // read request
+logic [31:0] reg_addr ; // address
+logic [3:0] reg_be ; // Byte enable
+logic [31:0] reg_wdata ; // write data
+logic [31:0] reg_rdata ; // read data
+logic reg_ack ; // read valid
+
+sspis_if u_if (
+
+ .sys_clk (sys_clk ),
+ .rst_n (rst_n ),
+
+ .sclk (sclk ),
+ .ssn (ssn ),
+ .sdin (sdin ),
+ .sdout (sdout ),
+ .sdout_oen (sdout_oen ),
+
+ //spi_sm Interface
+ .reg_wr (reg_wr ), // write request
+ .reg_rd (reg_rd ), // read request
+ .reg_addr (reg_addr ), // address
+ .reg_be (reg_be ), // Byte enable
+ .reg_wdata (reg_wdata ), // write data
+ .reg_rdata (reg_rdata ), // read data
+ .reg_ack (reg_ack ) // read valid
+ );
+
+spi2wb u_spi2wb (
+
+ //spis_if Interface
+ .reg_wr (reg_wr ), // write request
+ .reg_rd (reg_rd ), // read request
+ .reg_addr (reg_addr ), // address
+ .reg_be (reg_be ), // Byte enable
+ .reg_wdata (reg_wdata ), // write data
+ .reg_rdata (reg_rdata ), // read data
+ .reg_ack (reg_ack ), // read valid
+
+ // WB Master Port
+ .wbm_cyc_o (wbm_cyc_o ), // strobe/request
+ .wbm_stb_o (wbm_stb_o ), // strobe/request
+ .wbm_adr_o (wbm_adr_o ), // address
+ .wbm_we_o (wbm_we_o ), // write
+ .wbm_dat_o (wbm_dat_o ), // data output
+ .wbm_sel_o (wbm_sel_o ), // byte enable
+ .wbm_dat_i (wbm_dat_i ), // data input
+ .wbm_ack_i (wbm_ack_i ), // acknowlegement
+ .wbm_err_i (wbm_err_i ) // error
+
+);
+
+endmodule
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v
index f8c579f..0800fb9 100644
--- a/verilog/rtl/user_project_wrapper.v
+++ b/verilog/rtl/user_project_wrapper.v
@@ -40,7 +40,7 @@
//// nothing ////
//// ////
//// Author(s): ////
-//// - Dinesh Annayya, dinesha@opencores.org ////
+//// - Dinesh Annayya, dinesh.annayya@gmail.com ////
//// ////
//// Revision : ////
//// 0.1 - 16th Feb 2021, Dinesh A ////
@@ -214,6 +214,13 @@
//// 1. DFFRAM Replaced by SRAM ////
//// 4.6 June 13 2022, Dinesh A ////
//// 1. icache and dcache bypass config addded ////
+//// 4.7 July 08 2022, Dinesh A ////
+//// Pinmux changes to support SPI CS port matching to ////
+//// arduino ////
+//// 4.8 July 20 2022, Dinesh A ////
+//// SPI ISP boot option added in wb_host, spi slave uses ////
+//// same spi master interface, but will be active only ////
+//// when internal SPI config disabled + RESET PIN = 0 ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
@@ -590,6 +597,12 @@
wire sspim_si ; // serial data in
wire [3:0] sspim_ssn ; // cs_n
+// SPIS I/F
+wire sspis_sck ; // clock out
+wire sspis_so ; // serial data out
+wire sspis_si ; // serial data in
+wire sspis_ssn ; // cs_n
+
wire usb_intr_o ;
wire i2cm_intr_o ;
@@ -698,6 +711,12 @@
.uartm_rxd (uartm_rxd ),
.uartm_txd (uartm_txd ),
+ .sclk (sspis_sck ),
+ .ssn (sspis_ssn ),
+ .sdin (sspis_si ),
+ .sdout (sspis_so ),
+ .sdout_oen ( ),
+
.dbg_clk_mon (dbg_clk_mon )
@@ -1281,6 +1300,12 @@
.spim_ssn (sspim_ssn ),
.spim_miso (sspim_so ),
.spim_mosi (sspim_si ),
+
+ // SPI SLAVE
+ .spis_sck (sspis_sck ),
+ .spis_ssn (sspis_ssn ),
+ .spis_miso (sspis_so ),
+ .spis_mosi (sspis_si ),
// UART MASTER I/F
.uartm_rxd (uartm_rxd ),
diff --git a/verilog/rtl/wb_host/src/wb_host.sv b/verilog/rtl/wb_host/src/wb_host.sv
index 8256742..26029c2 100644
--- a/verilog/rtl/wb_host/src/wb_host.sv
+++ b/verilog/rtl/wb_host/src/wb_host.sv
@@ -139,6 +139,12 @@
input logic uartm_rxd ,
output logic uartm_txd ,
+ input logic sclk ,
+ input logic ssn ,
+ input logic sdin ,
+ output logic sdout ,
+ output logic sdout_oen ,
+
output logic dbg_clk_mon
);
@@ -188,6 +194,17 @@
logic wbm_uart_ack_o ; // acknowlegement
logic wbm_uart_err_o ; // error
+// SPI SLAVE Port
+logic wbm_spi_cyc_i ; // strobe/request
+logic wbm_spi_stb_i ; // strobe/request
+logic [31:0] wbm_spi_adr_i ; // address
+logic wbm_spi_we_i ; // write
+logic [31:0] wbm_spi_dat_i ; // data output
+logic [3:0] wbm_spi_sel_i ; // byte enable
+logic [31:0] wbm_spi_dat_o ; // data input
+logic wbm_spi_ack_o ; // acknowlegement
+logic wbm_spi_err_o ; // error
+
// Selected Master Port
logic wb_cyc_i ; // strobe/request
logic wb_stb_i ; // strobe/request
@@ -292,33 +309,57 @@
);
+sspis_top u_spi2wb(
+
+ .sys_clk (wbm_clk_i ),
+ .rst_n (wbm_rst_n ),
+
+ .sclk (sclk ),
+ .ssn (ssn ),
+ .sdin (sdin ),
+ .sdout (sdout ),
+ .sdout_oen (sdout_oen ),
+
+ // WB Master Port
+ .wbm_cyc_o (wbm_spi_cyc_i ), // strobe/request
+ .wbm_stb_o (wbm_spi_stb_i ), // strobe/request
+ .wbm_adr_o (wbm_spi_adr_i ), // address
+ .wbm_we_o (wbm_spi_we_i ), // write
+ .wbm_dat_o (wbm_spi_dat_i ), // data output
+ .wbm_sel_o (wbm_spi_sel_i ), // byte enable
+ .wbm_dat_i (wbm_spi_dat_o ), // data input
+ .wbm_ack_i (wbm_spi_ack_o ), // acknowlegement
+ .wbm_err_i (wbm_spi_err_o ) // error
+ );
// Arbitor to select between external wb vs uart wb
wire [1:0] grnt;
wb_arb u_arb(
.clk (wbm_clk_i),
.rstn (wbm_rst_n),
- .req ({2'b0,wbm_uart_stb_i,(wbm_stb_i & wbm_cyc_i)}),
+ .req ({1'b0,wbm_spi_stb_i,wbm_uart_stb_i,(wbm_stb_i & wbm_cyc_i)}),
.gnt (grnt)
);
// Select the master based on the grant
-assign wb_cyc_i = (grnt == 2'b00) ? wbm_cyc_i : wbm_uart_cyc_i;
-assign wb_stb_i = (grnt == 2'b00) ? (wbm_cyc_i & wbm_stb_i) : wbm_uart_stb_i;
-assign wb_adr_i = (grnt == 2'b00) ? wbm_adr_i : wbm_uart_adr_i;
-assign wb_we_i = (grnt == 2'b00) ? wbm_we_i : wbm_uart_we_i;
-assign wb_dat_i = (grnt == 2'b00) ? wbm_dat_i : wbm_uart_dat_i;
-assign wb_sel_i = (grnt == 2'b00) ? wbm_sel_i : wbm_uart_sel_i;
+assign wb_cyc_i = (grnt == 2'b00) ? wbm_cyc_i :(grnt == 2'b01) ? wbm_uart_cyc_i :wbm_spi_cyc_i;
+assign wb_stb_i = (grnt == 2'b00) ? (wbm_cyc_i & wbm_stb_i) :(grnt == 2'b01) ? wbm_uart_stb_i :wbm_spi_stb_i;
+assign wb_adr_i = (grnt == 2'b00) ? wbm_adr_i :(grnt == 2'b01) ? wbm_uart_adr_i :wbm_spi_adr_i;
+assign wb_we_i = (grnt == 2'b00) ? wbm_we_i :(grnt == 2'b01) ? wbm_uart_we_i :wbm_spi_we_i ;
+assign wb_dat_i = (grnt == 2'b00) ? wbm_dat_i :(grnt == 2'b01) ? wbm_uart_dat_i :wbm_spi_dat_i;
+assign wb_sel_i = (grnt == 2'b00) ? wbm_sel_i :(grnt == 2'b01) ? wbm_uart_sel_i :wbm_spi_sel_i;
assign wbm_dat_o = (grnt == 2'b00) ? wb_dat_o : 'h0;
assign wbm_ack_o = (grnt == 2'b00) ? wb_ack_o : 'h0;
assign wbm_err_o = (grnt == 2'b00) ? wb_err_o : 'h0;
-
assign wbm_uart_dat_o = (grnt == 2'b01) ? wb_dat_o : 'h0;
assign wbm_uart_ack_o = (grnt == 2'b01) ? wb_ack_o : 'h0;
assign wbm_uart_err_o = (grnt == 2'b01) ? wb_err_o : 'h0;
+assign wbm_spi_dat_o = (grnt == 2'b10) ? wb_dat_o : 'h0;
+assign wbm_spi_ack_o = (grnt == 2'b10) ? wb_ack_o : 'h0;
+assign wbm_spi_err_o = (grnt == 2'b10) ? wb_err_o : 'h0;