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;