sram blockage for magic drc fix
diff --git a/openlane/pinmux/config.tcl b/openlane/pinmux/config.tcl
index 9e226cd..692bbaf 100755
--- a/openlane/pinmux/config.tcl
+++ b/openlane/pinmux/config.tcl
@@ -92,3 +92,7 @@
set ::env(DIODE_INSERTION_STRATEGY) 4
+set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
+set ::env(QUIT_ON_MAGIC_DRC) "0"
+set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/qspim/base.sdc b/openlane/qspim/base.sdc
index e69de29..35f2f48 100644
--- a/openlane/qspim/base.sdc
+++ b/openlane/qspim/base.sdc
@@ -0,0 +1,93 @@
+# 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>
+
+
+set_units -time ns
+set ::env(WB_CLOCK_PERIOD) "10"
+set ::env(WB_CLOCK_PORT) "mclk"
+
+set ::env(SPI_CLOCK_PORT) "spiclk"
+set ::env(SPI_CLOCK_PERIOD) "20"
+
+######################################
+# WB Clock domain input output
+######################################
+create_clock [get_ports $::env(WB_CLOCK_PORT)] -name $::env(WB_CLOCK_PORT) -period $::env(WB_CLOCK_PERIOD)
+
+create_generated_clock -name $::env(SPI_CLOCK_PORT) -source [get_ports $::env(WB_CLOCK_PORT)] -master_clock $::env(WB_CLOCK_PORT) -divide_by 2 -add -comment "SPI Clock Out" [get_port spi_clk]
+
+set wb_input_delay_value [expr $::env(WB_CLOCK_PERIOD) * 0.6]
+set wb_output_delay_value [expr $::env(WB_CLOCK_PERIOD) * 0.6]
+puts "\[INFO\]: Setting wb output delay to:$wb_output_delay_value"
+puts "\[INFO\]: Setting wb input delay to: $wb_input_delay_value"
+
+
+set_input_delay 2.0 -clock [get_clocks $::env(WB_CLOCK_PORT)] {rst_n}
+
+set_input_delay $wb_input_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_stb_i*]
+set_input_delay $wb_input_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_adr_i*]
+set_input_delay $wb_input_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_we_i*]
+set_input_delay $wb_input_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_dat_i*]
+set_input_delay $wb_input_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_sel_i*]
+
+
+set_output_delay $wb_output_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_dat_o*]
+set_output_delay $wb_output_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_ack_o*]
+set_output_delay $wb_output_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port wbd_err_o*]
+set_output_delay $wb_output_delay_value -clock [get_clocks $::env(WB_CLOCK_PORT)] [get_port spi_debug*]
+
+### SPI I/F constaints
+set spi_input_delay_value [expr $::env(SPI_CLOCK_PERIOD) * 0.6]
+set spi_output_delay_value [expr $::env(SPI_CLOCK_PERIOD) * 0.6]
+
+set_input_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[3]]
+set_input_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[2]]
+set_input_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[1]]
+set_input_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[0]]
+
+set_input_delay 0 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[3]]
+set_input_delay 0 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[2]]
+set_input_delay 0 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[1]]
+set_input_delay 0 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdi[0]]
+
+#io_out[0] is spiclcok
+#set_output_delay $wb_output_delay_value -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port io_out[0]]
+set_output_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_csn0]
+set_output_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[3]]
+set_output_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[2]]
+set_output_delay 6 -max -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[1]]
+
+
+set_output_delay -0.5 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_csn0]
+set_output_delay -0.5 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[3]]
+set_output_delay -0.5 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[2]]
+set_output_delay -0.5 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[1]]
+set_output_delay -0.5 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_sdo[0]]
+
+# Chip select asserted multiple cycle eariler than spi clock
+set_output_delay 0 -min -clock [get_clocks $::env(SPI_CLOCK_PORT)] [get_port spi_csn0]
+
+
+set_clock_uncertainty -from $::env(SPI_CLOCK_PORT) -to $::env(SPI_CLOCK_PORT) -setup 0.800
+set_clock_uncertainty -from $::env(WB_CLOCK_PORT) -to $::env(WB_CLOCK_PORT) -setup 0.800
+set_clock_uncertainty -from $::env(SPI_CLOCK_PORT) -to $::env(SPI_CLOCK_PORT) -hold 0.050
+set_clock_uncertainty -from $::env(WB_CLOCK_PORT) -to $::env(WB_CLOCK_PORT) -hold 0.050
+
+# TODO set this as parameter
+set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) [all_inputs]
+set cap_load [expr $::env(SYNTH_CAP_LOAD) / 1000.0]
+puts "\[INFO\]: Setting load to: $cap_load"
+set_load $cap_load [all_outputs]
diff --git a/openlane/qspim/config.tcl b/openlane/qspim/config.tcl
index e69de29..9666942 100755
--- a/openlane/qspim/config.tcl
+++ b/openlane/qspim/config.tcl
@@ -0,0 +1,98 @@
+# 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>
+
+# Global
+# ------
+
+set script_dir [file dirname [file normalize [info script]]]
+# Name
+
+set ::env(DESIGN_NAME) qspim_top
+
+set ::env(DESIGN_IS_CORE) "0"
+set ::env(FP_PDN_CORE_RING) "0"
+
+# Timing configuration
+set ::env(CLOCK_PERIOD) "10"
+set ::env(CLOCK_PORT) "mclk"
+
+set ::env(SYNTH_MAX_FANOUT) 4
+
+# Sources
+# -------
+
+# Local sources + no2usb sources
+set ::env(VERILOG_FILES) "\
+ $script_dir/../../verilog/rtl/qspim/src/qspim_top.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_if.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_regs.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_fifo.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_clkgen.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_ctrl.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_rx.sv \
+ $script_dir/../../verilog/rtl/qspim/src/qspim_tx.sv \
+ "
+
+set ::env(SYNTH_READ_BLACKBOX_LIB) 1
+set ::env(SDC_FILE) "$script_dir/base.sdc"
+set ::env(BASE_SDC_FILE) "$script_dir/base.sdc"
+
+set ::env(LEC_ENABLE) 0
+
+set ::env(VDD_PIN) [list {vccd1}]
+set ::env(GND_PIN) [list {vssd1}]
+
+
+# Floorplanning
+# -------------
+
+set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg
+
+set ::env(FP_SIZING) absolute
+set ::env(DIE_AREA) "0 0 400 650"
+
+set ::env(PL_TIME_DRIVEN) 1
+set ::env(PL_TARGET_DENSITY) "0.40"
+
+
+# If you're going to use multiple power domains, then keep this disabled.
+set ::env(RUN_CVC) 0
+
+#set ::env(PDN_CFG) $script_dir/pdn.tcl
+
+
+set ::env(PL_ROUTABILITY_DRIVEN) 1
+
+# helps in anteena fix
+set ::env(USE_ARC_ANTENNA_CHECK) "0"
+
+set ::env(FP_IO_VEXTEND) 4
+set ::env(FP_IO_HEXTEND) 4
+
+set ::env(FP_PDN_VPITCH) 100
+set ::env(FP_PDN_HPITCH) 100
+set ::env(FP_PDN_VWIDTH) 5
+set ::env(FP_PDN_HWIDTH) 5
+
+set ::env(GLB_RT_MAXLAYER) 4
+set ::env(GLB_RT_MAX_DIODE_INS_ITERS) 10
+set ::env(DIODE_INSERTION_STRATEGY) 4
+
+
+set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
+set ::env(QUIT_ON_MAGIC_DRC) "0"
+set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/qspim/pdn.tcl b/openlane/qspim/pdn.tcl
index e69de29..1fe689b 100644
--- a/openlane/qspim/pdn.tcl
+++ b/openlane/qspim/pdn.tcl
@@ -0,0 +1,49 @@
+# 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
+
+# Power nets
+set ::power_nets $::env(VDD_PIN)
+set ::ground_nets $::env(GND_PIN)
+
+set ::macro_blockage_layer_list "li1 met1 met2 met3 met4 met5"
+
+pdngen::specify_grid stdcell {
+ name grid
+ rails {
+ met1 {width 0.48 pitch $::env(PLACE_SITE_HEIGHT) offset 0}
+ }
+ straps {
+ met4 {width 1.6 pitch $::env(FP_PDN_VPITCH) offset $::env(FP_PDN_VOFFSET)}
+ met5 {width 1.6 pitch $::env(FP_PDN_HPITCH) offset $::env(FP_PDN_HOFFSET)}
+ }
+ connect {{met1 met4} {met4 met5}}
+}
+
+pdngen::specify_grid macro {
+ power_pins "VPWR"
+ ground_pins "VGND"
+ blockages "li1 met1 met2 met3 met4"
+ straps {
+ }
+ connect {{met4_PIN_ver met5}}
+}
+
+set ::halo 5
+
+# POWER or GROUND #Std. cell rails starting with power or ground rails at the bottom of the core area
+set ::rails_start_with "POWER" ;
+
+# POWER or GROUND #Upper metal stripes starting with power or ground rails at the left/bottom of the core area
+set ::stripes_start_with "POWER" ;
diff --git a/openlane/qspim/pin_order.cfg b/openlane/qspim/pin_order.cfg
index e69de29..5a26f7d 100644
--- a/openlane/qspim/pin_order.cfg
+++ b/openlane/qspim/pin_order.cfg
@@ -0,0 +1,161 @@
+#BUS_SORT
+#MANUAL_PLACE
+
+#W
+mclk 0000 0
+rst_n
+
+#E
+spi_debug\[0\] 0000 0
+spi_debug\[1\]
+spi_debug\[2\]
+spi_debug\[3\]
+spi_debug\[4\]
+spi_debug\[5\]
+spi_debug\[6\]
+spi_debug\[7\]
+spi_debug\[8\]
+spi_debug\[9\]
+spi_debug\[10\]
+spi_debug\[11\]
+spi_debug\[12\]
+spi_debug\[13\]
+spi_debug\[14\]
+spi_debug\[15\]
+spi_debug\[16\]
+spi_debug\[17\]
+spi_debug\[18\]
+spi_debug\[19\]
+spi_debug\[20\]
+spi_debug\[21\]
+spi_debug\[22\]
+spi_debug\[23\]
+spi_debug\[24\]
+spi_debug\[25\]
+spi_debug\[26\]
+spi_debug\[27\]
+spi_debug\[28\]
+spi_debug\[29\]
+spi_debug\[30\]
+spi_debug\[31\]
+
+spi_sdi\[3\] 0200 0
+spi_sdi\[2\]
+spi_sdi\[1\]
+spi_sdi\[0\]
+spi_sdo\[3\]
+spi_sdo\[2\]
+spi_sdo\[1\]
+spi_sdo\[0\]
+spi_clk
+spi_csn0
+spi_oen\[3\]
+spi_oen\[2\]
+spi_oen\[1\]
+spi_oen\[0\]
+
+#S
+wbd_stb_i 0000 0
+wbd_we_i 0000 1
+wbd_adr_i\[31\] 0000 2
+wbd_adr_i\[30\] 0000 3
+wbd_adr_i\[29\] 0000 4
+wbd_adr_i\[28\] 0000 5
+wbd_adr_i\[27\] 0000 6
+wbd_adr_i\[26\] 0000 7
+wbd_adr_i\[25\] 0000 8
+wbd_adr_i\[24\] 0000 9
+wbd_adr_i\[23\] 0000 10
+wbd_adr_i\[22\] 0000 11
+wbd_adr_i\[21\] 0000 12
+wbd_adr_i\[20\] 0000 13
+wbd_adr_i\[19\] 0000 14
+wbd_adr_i\[18\] 0000 15
+wbd_adr_i\[17\] 0000 16
+wbd_adr_i\[16\] 0000 17
+wbd_adr_i\[15\] 0000 18
+wbd_adr_i\[14\] 0000 19
+wbd_adr_i\[13\] 0000 20
+wbd_adr_i\[12\] 0000 21
+wbd_adr_i\[11\] 0000 22
+wbd_adr_i\[10\] 0000 23
+wbd_adr_i\[9\] 0000 24
+wbd_adr_i\[8\] 0000 25
+wbd_adr_i\[7\] 0000 26
+wbd_adr_i\[6\] 0000 27
+wbd_adr_i\[5\] 0000 28
+wbd_adr_i\[4\] 0000 29
+wbd_adr_i\[3\] 0000 30
+wbd_adr_i\[2\] 0000 31
+wbd_adr_i\[1\] 0000 32
+wbd_adr_i\[0\] 0000 33
+wbd_sel_i\[3\] 0000 34
+wbd_sel_i\[2\] 0000 35
+wbd_sel_i\[1\] 0000 36
+wbd_sel_i\[0\] 0000 37
+wbd_dat_i\[31\] 0000 38
+wbd_dat_i\[30\] 0000 39
+wbd_dat_i\[29\] 0000 40
+wbd_dat_i\[28\] 0000 41
+wbd_dat_i\[27\] 0000 42
+wbd_dat_i\[26\] 0000 43
+wbd_dat_i\[25\] 0000 44
+wbd_dat_i\[24\] 0000 45
+wbd_dat_i\[23\] 0000 46
+wbd_dat_i\[22\] 0000 47
+wbd_dat_i\[21\] 0000 48
+wbd_dat_i\[20\] 0000 49
+wbd_dat_i\[19\] 0000 50
+wbd_dat_i\[18\] 0000 51
+wbd_dat_i\[17\] 0000 52
+wbd_dat_i\[16\] 0000 53
+wbd_dat_i\[15\] 0000 54
+wbd_dat_i\[14\] 0000 55
+wbd_dat_i\[13\] 0000 56
+wbd_dat_i\[12\] 0000 57
+wbd_dat_i\[11\] 0000 58
+wbd_dat_i\[10\] 0000 59
+wbd_dat_i\[9\] 0000 60
+wbd_dat_i\[8\] 0000 61
+wbd_dat_i\[7\] 0000 62
+wbd_dat_i\[6\] 0000 63
+wbd_dat_i\[5\] 0000 64
+wbd_dat_i\[4\] 0000 65
+wbd_dat_i\[3\] 0000 66
+wbd_dat_i\[2\] 0000 67
+wbd_dat_i\[1\] 0000 68
+wbd_dat_i\[0\] 0000 69
+wbd_dat_o\[31\] 0000 70
+wbd_dat_o\[30\] 0000 71
+wbd_dat_o\[29\] 0000 72
+wbd_dat_o\[28\] 0000 73
+wbd_dat_o\[27\] 0000 74
+wbd_dat_o\[26\] 0000 75
+wbd_dat_o\[25\] 0000 76
+wbd_dat_o\[24\] 0000 77
+wbd_dat_o\[23\] 0000 78
+wbd_dat_o\[22\] 0000 79
+wbd_dat_o\[21\] 0000 80
+wbd_dat_o\[20\] 0000 81
+wbd_dat_o\[19\] 0000 82
+wbd_dat_o\[18\] 0000 83
+wbd_dat_o\[17\] 0000 84
+wbd_dat_o\[16\] 0000 85
+wbd_dat_o\[15\] 0000 86
+wbd_dat_o\[14\] 0000 87
+wbd_dat_o\[13\] 0000 88
+wbd_dat_o\[12\] 0000 89
+wbd_dat_o\[11\] 0000 90
+wbd_dat_o\[10\] 0000 91
+wbd_dat_o\[9\] 0000 92
+wbd_dat_o\[8\] 0000 93
+wbd_dat_o\[7\] 0000 94
+wbd_dat_o\[6\] 0000 95
+wbd_dat_o\[5\] 0000 96
+wbd_dat_o\[4\] 0000 97
+wbd_dat_o\[3\] 0000 98
+wbd_dat_o\[2\] 0000 99
+wbd_dat_o\[1\] 0000 100
+wbd_dat_o\[0\] 0000 101
+wbd_ack_o 0000 102
+wbd_err_o 0000 103
diff --git a/openlane/qspim/sta.tcl b/openlane/qspim/sta.tcl
index e69de29..af91726 100644
--- a/openlane/qspim/sta.tcl
+++ b/openlane/qspim/sta.tcl
@@ -0,0 +1,88 @@
+# 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>
+
+
+set ::env(LIB_FASTEST) "/home/dinesha/workarea/pdk/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__ff_n40C_1v95.lib"
+set ::env(LIB_SLOWEST) "/home/dinesha/workarea/pdk/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__ss_100C_1v60.lib"
+set ::env(CURRENT_NETLIST) /project/openlane/spi_master/runs/spi_master/results/lvs/spim_top.lvs.powered.v
+set ::env(DESIGN_NAME) "spim_top"
+set ::env(CURRENT_SPEF) /project/openlane/spi_master/runs/spi_master/results/routing/spim_top.spef
+set ::env(BASE_SDC_FILE) "/project/openlane/spi_master/base.sdc"
+set ::env(SYNTH_DRIVING_CELL) "sky130_fd_sc_hd__inv_8"
+set ::env(SYNTH_DRIVING_CELL_PIN) "Y"
+set ::env(SYNTH_CAP_LOAD) "17.65"
+set ::env(WIRE_RC_LAYER) "met1"
+
+
+set_cmd_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm -distance um
+read_liberty -min $::env(LIB_FASTEST)
+read_liberty -max $::env(LIB_SLOWEST)
+read_verilog $::env(CURRENT_NETLIST)
+link_design $::env(DESIGN_NAME)
+
+read_spef $::env(CURRENT_SPEF)
+
+read_sdc -echo $::env(BASE_SDC_FILE)
+
+# check for missing constraints
+check_setup -verbose > unconstraints.rpt
+
+set_operating_conditions -analysis_type single
+# Propgate the clock
+set_propagated_clock [all_clocks]
+
+report_tns
+report_wns
+report_power
+report_checks -unique -slack_max -0.0 -group_count 100
+report_checks -unique -slack_min -0.0 -group_count 100
+report_checks -path_delay min_max
+report_checks -group_count 100 -slack_max -0.01 > timing.rpt
+
+report_checks -group_count 100 -slack_min -0.01 >> timing.rpt
+
+
+report_checks -to [get_port io_out[5]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_out[4]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_out[3]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_out[2]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_out[1]] -path_delay min >> timing.rpt
+
+report_checks -to [get_port io_out[5]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_out[4]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_out[3]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_out[2]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_out[1]] -path_delay max >> timing.rpt
+
+report_checks -to [get_port io_oeb[5]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_oeb[4]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_oeb[3]] -path_delay min >> timing.rpt
+report_checks -to [get_port io_oeb[2]] -path_delay min >> timing.rpt
+
+report_checks -to [get_port io_oeb[5]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_oeb[4]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_oeb[3]] -path_delay max >> timing.rpt
+report_checks -to [get_port io_oeb[2]] -path_delay max >> timing.rpt
+
+report_checks -from [get_port io_in[5]] -path_delay min >> timing.rpt
+report_checks -from [get_port io_in[4]] -path_delay min >> timing.rpt
+report_checks -from [get_port io_in[3]] -path_delay min >> timing.rpt
+report_checks -from [get_port io_in[2]] -path_delay min >> timing.rpt
+
+report_checks -from [get_port io_in[5]] -path_delay max >> timing.rpt
+report_checks -from [get_port io_in[4]] -path_delay max >> timing.rpt
+report_checks -from [get_port io_in[3]] -path_delay max >> timing.rpt
+report_checks -from [get_port io_in[2]] -path_delay max >> timing.rpt
diff --git a/openlane/user_project_wrapper/config.tcl b/openlane/user_project_wrapper/config.tcl
index ef01dc5..99d6096 100644
--- a/openlane/user_project_wrapper/config.tcl
+++ b/openlane/user_project_wrapper/config.tcl
@@ -55,8 +55,8 @@
set ::env(PDN_CFG) $proj_dir/pdn.tcl
-#set ::env(SDC_FILE) "$proj_dir/base.sdc"
-#set ::env(BASE_SDC_FILE) "$proj_dir/base.sdc"
+set ::env(SDC_FILE) "$proj_dir/base.sdc"
+set ::env(BASE_SDC_FILE) "$proj_dir/base.sdc"
set ::env(SYNTH_READ_BLACKBOX_LIB) 1
@@ -104,49 +104,55 @@
set ::env(FP_PDN_CHECK_NODES) 0
-set ::env(RUN_KLAYOUT_DRC) 0
## Internal Macros
### Macro PDN Connections
-set ::env(FP_PDN_ENABLE_MACROS_GRID) "0"
-set ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) "1"
+#set ::env(FP_PDN_ENABLE_MACROS_GRID) "0"
+#set ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) "1"
set ::env(VDD_NETS) "vccd1 vccd2 vdda1 vdda2"
set ::env(GND_NETS) "vssd1 vssd2 vssa1 vssa2"
-set ::env(FP_PDN_ENABLE_RAILS) 0
+set ::env(GLB_RT_OBS) "li1 2200.00 1200.00 2883.10 1616.54, \
+ met1 2200.00 1200.00 2883.10 1616.54, \
+ met2 2200.00 1200.00 2883.10 1616.54, \
+ met3 2200.00 1200.00 2883.10 1616.54, \
+ met5 0 0 2920 3520"
+
+set ::env(FP_PDN_MACROS) "\
+ u_adc vccd1 vssd1 \
+ u_adc vccd2 vssd2 \
+ u_intercon vccd1 vssd1 \
+ u_pinmux vccd1 vssd1 \
+ u_qspi_master vccd1 vssd1 \
+ u_riscv_top vccd1 vssd1 \
+ u_sram_2kb vccd1 vssd1 \
+ u_uart_i2c_usb_spi vccd1 vssd1 \
+ u_wb_host vccd1 vssd1 \
+ "
# The following is because there are no std cells in the example wrapper project.
-#set ::env(SYNTH_TOP_LEVEL) 1
-#set ::env(PL_RANDOM_GLB_PLACEMENT) 1
+set ::env(SYNTH_TOP_LEVEL) 1
+set ::env(PL_RANDOM_GLB_PLACEMENT) 1
set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0
set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0
set ::env(PL_RESIZER_BUFFER_INPUT_PORTS) 0
set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0
-set ::env(TAP_DECAP_INSERTION) "0"
+set ::env(FP_PDN_ENABLE_RAILS) 0
+
set ::env(DIODE_INSERTION_STRATEGY) 0
set ::env(FILL_INSERTION) 0
+set ::env(TAP_DECAP_INSERTION) 0
set ::env(CLOCK_TREE_SYNTH) 0
-#set ::env(MAGIC_EXT_USE_GDS) "1"
-set ::env(QUIT_ON_LVS_ERROR) "1"
-
-set ::env(PL_DIAMOND_SEARCH_HEIGHT) "250"
+set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_MAGIC_DRC) "0"
+set ::env(QUIT_ON_NEGATIVE_WNS) "0"
+set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
+set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
+set ::env(QUIT_ON_TR_DRC) "0"
-set ::env(FP_PDN_HOFFSET) "5"
-set ::env(FP_PDN_HPITCH) "120"
-set ::env(FP_PDN_HSPACING) "15"
-set ::env(FP_PDN_HWIDTH) "3"
-set ::env(FP_PDN_LOWER_LAYER) "met4"
-set ::env(FP_PDN_RAILS_LAYER) "met1"
-set ::env(FP_PDN_RAIL_OFFSET) "0"
-set ::env(FP_PDN_RAIL_WIDTH) "0.48"
-set ::env(FP_PDN_UPPER_LAYER) "met5"
-set ::env(FP_PDN_VOFFSET) "5"
-set ::env(FP_PDN_VPITCH) "120"
-set ::env(FP_PDN_VSPACING) "15"
-set ::env(FP_PDN_VWIDTH) "3"
diff --git a/openlane/user_project_wrapper/interactive.tcl b/openlane/user_project_wrapper/interactive.tcl
index baf999e..beab1b9 100644
--- a/openlane/user_project_wrapper/interactive.tcl
+++ b/openlane/user_project_wrapper/interactive.tcl
@@ -136,9 +136,9 @@
prep {*}$args
- set LVS_ENABLED 0
+ set LVS_ENABLED 1
set DRC_ENABLED 0
- set ANTENNACHECK_ENABLED 0
+ set ANTENNACHECK_ENABLED 1
set steps [dict create "synthesis" {run_synthesis "" } \
"floorplan" {run_floorplan ""} \
diff --git a/signoff/pinmux/OPENLANE_VERSION b/signoff/pinmux/OPENLANE_VERSION
index ba96224..bb2743d 100644
--- a/signoff/pinmux/OPENLANE_VERSION
+++ b/signoff/pinmux/OPENLANE_VERSION
@@ -1 +1 @@
-openlane 2021.09.19_20.25.16
+openlane 2021.10.08_02.00.18-4-gd052a91
diff --git a/signoff/pinmux/PDK_SOURCES b/signoff/pinmux/PDK_SOURCES
index 4c20ce4..1bf005a 100644
--- a/signoff/pinmux/PDK_SOURCES
+++ b/signoff/pinmux/PDK_SOURCES
@@ -1,6 +1,6 @@
-ne openlane
-27752ec11a12afa3214f64401662683f081e2644
+d052a918f4a46ddbae0ad09812f6cd0b8eb4a1e5
-ne skywater-pdk
c094b6e83a4f9298e47f696ec5a7fd53535ec5eb
-ne open_pdks
-6c05bc48dc88784f9d98b89d6791cdfd91526676
+5cad4f87435ae7f4e17e50d9c66cd79ecc14e663
diff --git a/signoff/pinmux/final_summary_report.csv b/signoff/pinmux/final_summary_report.csv
index f7bae69..2244e63 100644
--- a/signoff/pinmux/final_summary_report.csv
+++ b/signoff/pinmux/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,/project/openlane/pinmux,pinmux,pinmux,flow_completed,0h13m20s,0h10m28s,41992.0,0.25,20996.0,24.54,687.7,5249,0,0,0,0,0,0,0,1,0,-1,-1,356411,53685,-1.51,-2.91,0.0,-2.58,-1.51,-707.01,-1833.63,0.0,-128.81,-376.98,280858451.0,6.67,34.96,29.98,5.61,0.5,-1,3127,7858,443,5174,0,0,0,3793,0,0,0,0,0,0,0,4,1147,1169,11,350,3274,0,3624,86.88097306689835,11.51,10,AREA 0,4,50,1,100,100,0.35,0.0,sky130_fd_sc_hd,4,4
+0,/project/openlane/pinmux,pinmux,pinmux,flow_completed,0h13m6s,0h10m18s,41992.0,0.25,20996.0,24.54,687.96,5249,0,0,0,0,0,0,0,1,0,-1,-1,359665,53587,-1.51,-3.72,-0.77,-2.06,-3.83,-707.01,-3465.58,-26.11,-112.5,-256.78,281861115.0,1.92,35.04,30.5,5.79,0.83,-1,3127,7858,443,5174,0,0,0,3793,0,0,0,0,0,0,0,4,1147,1169,11,350,3274,0,3624,72.30657989877079,13.83,10,AREA 0,4,50,1,100,100,0.35,0.0,sky130_fd_sc_hd,4,4
diff --git a/signoff/qspim/OPENLANE_VERSION b/signoff/qspim/OPENLANE_VERSION
index 326b88d..bb2743d 100644
--- a/signoff/qspim/OPENLANE_VERSION
+++ b/signoff/qspim/OPENLANE_VERSION
@@ -1 +1 @@
-openlane v0.21-10-gb10884a
+openlane 2021.10.08_02.00.18-4-gd052a91
diff --git a/signoff/qspim/PDK_SOURCES b/signoff/qspim/PDK_SOURCES
index 8b58bd5..1bf005a 100644
--- a/signoff/qspim/PDK_SOURCES
+++ b/signoff/qspim/PDK_SOURCES
@@ -1,6 +1,6 @@
-ne openlane
-a68c95289612a361870acedb7f6478fcfae32e49
+d052a918f4a46ddbae0ad09812f6cd0b8eb4a1e5
-ne skywater-pdk
-f6f76f3dc99526c6fc2cfede19b5b1227d4ebde7
+c094b6e83a4f9298e47f696ec5a7fd53535ec5eb
-ne open_pdks
-522a373441a865fee9d6e3783015b4445f11afe6
+5cad4f87435ae7f4e17e50d9c66cd79ecc14e663
diff --git a/signoff/qspim/final_summary_report.csv b/signoff/qspim/final_summary_report.csv
index 69addab..806f445 100644
--- a/signoff/qspim/final_summary_report.csv
+++ b/signoff/qspim/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,/project/openlane/qspim,qspim_top,qspim,Flow_completed,0h18m21s,0h9m9s,58438.46153846153,0.26,29219.230769230766,47,661.77,7597,0,0,0,0,0,0,0,0,3,-1,0,384228,67124,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,294776771,0.0,31.33,39.79,0.04,-1,-1,7537,7673,1268,1404,0,0,0,7597,245,0,169,100,1051,210,32,2443,1353,1292,24,460,3132,0,3592,100.0,10.0,10,AREA 0,4,50,1,100,100,0.45,0,sky130_fd_sc_hd,4,5
+0,/project/openlane/qspim,qspim_top,qspim,flow_completed,0h19m11s,0h15m54s,54669.23076923077,0.26,27334.615384615387,31.48,711.84,7107,0,0,0,0,0,0,0,1,0,-1,-1,341039,66217,-8.22,-8.65,-5.57,-7.03,-9.22,-379.27,-712.99,-470.98,-807.92,-1999.86,231043777.0,8.61,28.55,33.92,0.78,-1,23.3,5724,8664,385,3324,0,0,0,6822,0,0,0,0,0,0,0,4,1765,2184,20,460,3480,0,3940,52.02913631633715,19.22,10,AREA 0,4,50,1,100,100,0.4,0.0,sky130_fd_sc_hd,4,4
diff --git a/signoff/user_project_wrapper/OPENLANE_VERSION b/signoff/user_project_wrapper/OPENLANE_VERSION
index ba96224..80c7664 100644
--- a/signoff/user_project_wrapper/OPENLANE_VERSION
+++ b/signoff/user_project_wrapper/OPENLANE_VERSION
@@ -1 +1 @@
-openlane 2021.09.19_20.25.16
+openlane N/A
diff --git a/signoff/user_project_wrapper/PDK_SOURCES b/signoff/user_project_wrapper/PDK_SOURCES
index 4c20ce4..ca3684a 100644
--- a/signoff/user_project_wrapper/PDK_SOURCES
+++ b/signoff/user_project_wrapper/PDK_SOURCES
@@ -1,6 +1,6 @@
-ne openlane
-27752ec11a12afa3214f64401662683f081e2644
+8d686c081c2c9aefa16dbbd8ccf5bc8f4dcabc4b
-ne skywater-pdk
c094b6e83a4f9298e47f696ec5a7fd53535ec5eb
-ne open_pdks
-6c05bc48dc88784f9d98b89d6791cdfd91526676
+14db32aa8ba330e88632ff3ad2ff52f4f4dae1ad
diff --git a/signoff/user_project_wrapper/final_summary_report.csv b/signoff/user_project_wrapper/final_summary_report.csv
index f8f2aae..94dcd17 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,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow_completed,0h15m50s,0h3m45s,1.5566625155666252,10.2784,0.7783312577833126,-1,520.01,8,0,0,0,0,0,0,-1,-1,-1,-1,-1,1369644,5587,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,53026.4,1.9,5.04,1.02,2.11,-1,152,1776,151,1773,0,0,0,8,0,0,0,0,0,0,0,4,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,120,120,0.55,0.0,sky130_fd_sc_hd,4,0
+0,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow_completed,0h17m9s,-1,1.5566625155666252,10.2784,0.7783312577833126,-1,515.2,8,0,0,0,0,0,0,-1,0,2,-1,-1,1370232,5772,0.0,-1,-1,0.0,-1,0.0,-1,-1,0.0,-1,-1,40150.48,1.9,5.04,1.03,2.01,-1,173,1812,172,1809,0,0,0,8,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,90.9090909090909,11,10,AREA 0,5,50,1,180,180,0.55,0.0,sky130_fd_sc_hd,4,0
diff --git a/verilog/rtl/qspim/src/filelist.f b/verilog/rtl/qspim/src/filelist.f
index e69de29..971ad9f 100644
--- a/verilog/rtl/qspim/src/filelist.f
+++ b/verilog/rtl/qspim/src/filelist.f
@@ -0,0 +1,24 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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>
+// //////////////////////////////////////////////////////////////////////////
+
+qspim_top.sv
+qspim_regs.sv
+qspim_clkgen.sv
+qspim_ctrl.sv
+qspim_rx.sv
+qspim_tx.sv
diff --git a/verilog/rtl/qspim/src/qspim_clkgen.sv b/verilog/rtl/qspim/src/qspim_clkgen.sv
index e69de29..f163c95 100644
--- a/verilog/rtl/qspim/src/qspim_clkgen.sv
+++ b/verilog/rtl/qspim/src/qspim_clkgen.sv
@@ -0,0 +1,146 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 Clkgen Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// This is SPI Master Clock Generation control logic. ////
+//// This logic also generate spi clock rise and fall pulse ////
+//// Basis assumption is master clock is 2x time spi clock ////
+//// 1. spi fall pulse is used to transmit spi data ////
+//// 2. spi rise pulse is used to received spi data ////
+//// SPI Master Top module ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision: ////
+//// 0.1 - 16th Feb 2021, Dinesh A ////
+//// Initial version ////
+//// 0.2 - 24th Mar 2021, Dinesh A ////
+//// 1. Comments are added ////
+//// 2. RTL clean-up done and the output are registred ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module qspim_clkgen
+(
+ input logic clk,
+ input logic rstn,
+ input logic en,
+ input logic [5:0] cfg_sck_period,
+ output logic spi_clk,
+ output logic spi_fall,
+ output logic spi_rise
+);
+
+ logic [5:0] sck_half_period;
+ logic [5:0] clk_cnt;
+
+ assign sck_half_period = {1'b0, cfg_sck_period[5:1]};
+
+ // The first transition on the sck_toggle happens one SCK period
+ // after en is asserted
+ always @(posedge clk or negedge rstn) begin
+ if(!rstn) begin
+ spi_clk <= 1'b1;
+ end // if (!reset_n)
+ else
+ begin
+ if(en)
+ begin
+ if(clk_cnt == sck_half_period)
+ begin
+ spi_clk <= 1'b0;
+ end // if (clk_cnt == sck_half_period)
+ else if(clk_cnt == cfg_sck_period) begin
+ spi_clk <= 1'b1;
+ end
+ end else begin
+ spi_clk <= 1'b1;
+ end // else: !if(en)
+ end // else: !if(!reset_n)
+ end // always @ (posedge clk or negedge reset_n)
+
+ // Generate Free runnng spi_fall and rise pulse
+ // after en is asserted
+ always @(posedge clk or negedge rstn) begin
+ if(!rstn) begin
+ clk_cnt <= 'h1;
+ spi_fall <= 1'b0;
+ spi_rise <= 1'b0;
+ end // if (!reset_n)
+ else
+ begin
+ if(clk_cnt == sck_half_period)
+ begin
+ spi_fall <= 1'b0;
+ spi_rise <= 1'b1;
+ clk_cnt <= clk_cnt + 1'b1;
+ end // if (clk_cnt == sck_half_period)
+ else begin
+ if(clk_cnt == cfg_sck_period)
+ begin
+ spi_fall <= 1'b1;
+ spi_rise <= 1'b0;
+ clk_cnt <= 'h1;
+ end // if (clk_cnt == cfg_sck_period)
+ else
+ begin
+ clk_cnt <= clk_cnt + 1'b1;
+ spi_fall <= 1'b0;
+ spi_rise <= 1'b0;
+ end // else: !if(clk_cnt == cfg_sck_period)
+ end // else: !if(clk_cnt == sck_half_period)
+ end // else: !if(!reset_n)
+ end // always @ (posedge clk or negedge reset_n)
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_ctrl.sv b/verilog/rtl/qspim/src/qspim_ctrl.sv
index e69de29..7cd6909 100644
--- a/verilog/rtl/qspim/src/qspim_ctrl.sv
+++ b/verilog/rtl/qspim/src/qspim_ctrl.sv
@@ -0,0 +1,720 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 CTRL I/F Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// V.0 - June 8, 2021 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+module qspim_ctrl #(
+ parameter ENDIEAN = 0 // 0 - Little, 1 - Big endian, since RISV is Little indian default set 0
+ )
+
+(
+ input logic clk,
+ input logic rstn,
+
+ input logic [7:0] spi_clk_div,
+ output logic [8:0] spi_status,
+
+ // Master 0 Configuration
+ input logic [3:0] cfg_m0_cs_reg , // Chip select
+ input logic [1:0] cfg_m0_spi_mode , // Final SPI Mode
+ input logic [1:0] cfg_m0_spi_switch, // SPI Mode Switching Place
+
+ input logic [3:0] cfg_m1_cs_reg , // Chip select
+ input logic [1:0] cfg_m1_spi_mode , // Final SPI Mode
+ input logic [1:0] cfg_m1_spi_switch, // SPI Mode Switching Place
+
+ input logic [1:0] cfg_cs_early , // Amount of cycle early CS asserted
+ input logic [1:0] cfg_cs_late , // Amount of cycle late CS de-asserted
+
+ // Master 0 Command FIFO Interface
+ input logic m0_cmd_fifo_empty,
+ output logic m0_cmd_fifo_rd,
+ input logic [33:0] m0_cmd_fifo_rdata,
+
+ // Master 0 response FIFO Interface
+ output logic m0_res_fifo_flush,
+ input logic m0_res_fifo_empty,
+ input logic m0_res_fifo_full,
+ output logic m0_res_fifo_wr,
+ output logic [31:0] m0_res_fifo_wdata,
+
+ // Master 1 Command FIFO Interface
+ output logic m1_res_fifo_flush,
+ input logic m1_cmd_fifo_empty,
+ output logic m1_cmd_fifo_rd,
+ input logic [33:0] m1_cmd_fifo_rdata,
+
+ // Master 1 response FIFO Interface
+ input logic m1_res_fifo_empty,
+ input logic m1_res_fifo_full,
+ output logic m1_res_fifo_wr,
+ output logic [31:0] m1_res_fifo_wdata,
+
+ output logic [3:0] ctrl_state,
+
+ output logic spi_clk,
+ output logic spi_csn0,
+ output logic spi_csn1,
+ output logic spi_csn2,
+ output logic spi_csn3,
+ output logic [1:0] spi_mode,
+ output logic spi_sdo0,
+ output logic spi_sdo1,
+ output logic spi_sdo2,
+ output logic spi_sdo3,
+ input logic spi_sdi0,
+ input logic spi_sdi1,
+ input logic spi_sdi2,
+ input logic spi_sdi3,
+ output logic spi_en_tx_out // Spi Direction control
+);
+
+//--------------------------------------
+// Parameter
+// --------------------------------------
+parameter P_SINGLE = 2'b00;
+parameter P_DOUBLE = 2'b01;
+parameter P_QUAD = 2'b10;
+parameter P_QDDR = 2'b11;
+
+
+/*************************************************************
+* SPI FSM State Control
+*
+* OPERATION COMMAND SEQUENCE
+*
+* ERASE P4E(0x20) -> COMMAND + ADDRESS
+* ERASE P8E(0x40) -> COMMAND + ADDRESS
+* ERASE SE(0xD8) -> COMMAND + ADDRESS
+* ERASE BE(0x60) -> COMMAND + ADDRESS
+* ERASE BE(0xC7) -> COMMAND
+* PROGRAM PP(0x02) -> COMMAND + ADDRESS + Write DATA
+* PROGRAM QPP(0x32) -> COMMAND + ADDRESS + Write DATA
+* READ READ(0x3) -> COMMAND + ADDRESS + READ DATA
+* READ FAST_READ(0xB) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DOR (0x3B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ QOR (0x6B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DIOR (0xBB) -> COMMAND + ADDRESS + MODE + READ DATA
+* READ QIOR (0xEB) -> COMMAND + ADDRESS + MODE + DUMMY + READ DATA
+* READ RDID (0x9F) -> COMMAND + READ DATA
+* READ READ_ID (0x90) -> COMMAND + ADDRESS + READ DATA
+* WRITE WREN(0x6) -> COMMAND
+* WRITE WRDI -> COMMAND
+* STATUS RDSR(0x05) -> COMMAND + READ DATA
+* STATUS RCR(0x35) -> COMMAND + READ DATA
+* CONFIG WRR(0x01) -> COMMAND + WRITE DATA
+* CONFIG CLSR(0x30) -> COMMAND
+* Power Saving DP(0xB9) -> COMMAND
+* Power Saving RES(0xAB) -> COMMAND + READ DATA
+* OTP OTPP(0x42) -> COMMAND + ADDR+ WRITE DATA
+* OTP OTPR(0x4B) -> COMMAND + ADDR + DUMMY + READ DATA
+* ********************************************************************/
+parameter P_FSM_C = 4'b0000; // Command Phase Only
+parameter P_FSM_CW = 4'b0001; // Command + Write DATA Phase Only
+parameter P_FSM_CA = 4'b0010; // Command -> Address Phase Only
+
+parameter P_FSM_CAR = 4'b0011; // Command -> Address -> Read Data
+parameter P_FSM_CADR = 4'b0100; // Command -> Address -> Dummy -> Read Data
+parameter P_FSM_CAMR = 4'b0101; // Command -> Address -> Mode -> Read Data
+parameter P_FSM_CAMDR = 4'b0110; // Command -> Address -> Mode -> Dummy -> Read Data
+
+parameter P_FSM_CAW = 4'b0111; // Command -> Address ->Write Data
+parameter P_FSM_CADW = 4'b1000; // Command -> Address -> DUMMY + Write Data
+
+parameter P_FSM_CDR = 4'b1001; // COMMAND -> DUMMY -> READ
+parameter P_FSM_CDW = 4'b1010; // COMMAND -> DUMMY -> WRITE
+parameter P_FSM_CR = 4'b1011; // COMMAND -> READ
+
+//---------------------
+ parameter P_8BIT = 2'b00;
+ parameter P_16BIT = 2'b01;
+ parameter P_24BIT = 2'b10;
+ parameter P_32BIT = 2'b11;
+
+//---- Phase where to switch the SPI Mode
+//---- This need to decided based on command
+ parameter P_MODE_SWITCH_IDLE = 2'b00;
+ parameter P_MODE_SWITCH_AT_ADDR = 2'b01;
+ parameter P_MODE_SWITCH_AT_DATA = 2'b10;
+//----------------------------------------
+// Local Variable
+// ---------------------------------------
+ logic spi_rise;
+ logic spi_fall;
+
+ logic spi_clock_en;
+
+ logic spi_en_rx;
+ logic spi_en_tx;
+
+
+ logic [15:0] counter_tx;
+ logic counter_tx_valid;
+ logic [15:0] counter_rx;
+ logic counter_rx_valid;
+
+ logic dummy_phase;
+ logic [31:0] data_to_tx;
+ logic data_to_tx_valid;
+ logic data_to_tx_ready;
+ logic tx_data_ready;
+
+
+ logic tx_done;
+ logic rx_done;
+
+ logic [1:0] s_spi_mode;
+
+ logic ctrl_data_valid;
+
+ logic spi_cs;
+
+ logic tx_clk_en;
+ logic rx_clk_en;
+ logic [1:0] cnt; // counter for cs assertion and de-assertion
+ logic [1:0] nxt_cnt;
+ logic [1:0] gnt;
+
+ logic [7:0] cfg_data_cnt ;
+ logic [1:0] cfg_dummy_cnt ;
+ logic [1:0] cfg_addr_cnt ;
+ logic [3:0] cfg_spi_seq ;
+ logic [7:0] spi_mode_cmd ;
+
+
+ enum logic [2:0] {DATA_NULL,DATA_EMPTY,DATA_CMD,DATA_ADDR,DATA_MODE,DATA_FIFO} ctrl_data_mux;
+
+ enum logic [4:0] {FSM_IDLE,FSM_CS_ASSERT,FSM_CMD_PHASE,FSM_ADR_PHASE,FSM_DUMMY_PHASE,FSM_MODE_PHASE,FSM_WRITE_CMD,FSM_WRITE_PHASE,
+ FSM_READ_WAIT,FSM_READ_PHASE,FSM_TX_DONE,FSM_FLUSH,FSM_CS_DEASEERT} state,next_state;
+
+
+ assign ctrl_state = state[3:0];
+
+ assign spi_mode = s_spi_mode;
+
+ //----------------------------
+ // Configuration
+ //----------------------------
+ logic [3:0] cfg_cs_reg ; // Chip select
+ logic [1:0] cfg_spi_mode ; // Final SPI Mode
+ logic [1:0] cfg_spi_switch; // SPI Mode Switching Place
+
+
+ assign cfg_cs_reg = (gnt == 2'b01) ? cfg_m0_cs_reg : cfg_m1_cs_reg;
+ assign cfg_spi_mode = (gnt == 2'b01) ? cfg_m0_spi_mode : cfg_m1_spi_mode; // Final SPI Mode
+ assign cfg_spi_switch = (gnt == 2'b01) ? cfg_m0_spi_switch: cfg_m1_spi_switch; // SPI Mode Switching Place
+
+ //----------------------------
+ // Command FIFO
+ //----------------------------
+ logic cmd_fifo_empty;
+ logic cmd_fifo_rd;
+ logic [33:0] cmd_fifo_rdata;
+
+ assign cmd_fifo_empty = (gnt == 2'b01) ? m0_cmd_fifo_empty : m1_cmd_fifo_empty;
+ assign cmd_fifo_rdata = (gnt == 2'b01) ? m0_cmd_fifo_rdata : m1_cmd_fifo_rdata;
+
+ assign m0_cmd_fifo_rd = (gnt == 2'b01) ? cmd_fifo_rd : 1'b0;
+ assign m1_cmd_fifo_rd = (gnt == 2'b10) ? cmd_fifo_rd : 1'b0;
+
+ //----------------------------
+ // Response FIFO
+ //----------------------------
+ logic res_fifo_empty;
+ logic res_fifo_full;
+ logic res_fifo_wr;
+ logic [31:0] res_fifo_wdata;
+
+ assign res_fifo_empty = (gnt == 2'b01) ? m0_res_fifo_empty : m1_res_fifo_empty;
+ assign res_fifo_full = (gnt == 2'b01) ? m0_res_fifo_full : m1_res_fifo_full;
+
+ assign m0_res_fifo_wr = (gnt == 2'b01) ? res_fifo_wr : 1'b0;
+ assign m1_res_fifo_wr = (gnt == 2'b10) ? res_fifo_wr : 1'b0;
+
+ assign m0_res_fifo_wdata = (gnt == 2'b01) ? res_fifo_wdata : 1'b0;
+ assign m1_res_fifo_wdata = (gnt == 2'b10) ? res_fifo_wdata : 1'b0;
+
+ //---------------------------------------------------------------------------
+ // To take care of partial/stall data in response fifo
+ // we are flushing the content
+ //
+ // WARNING: This will work well for burst size 4,
+ // If User given 6 Word Burst and Read only one location
+ // Read Path will hang waiting for Response FIFO to empty, User need to take
+ // care of partial reading case.
+ //---------------------------------------------------------------------------
+
+ logic fsm_flush;
+ logic spi_dummy;
+ assign m0_res_fifo_flush = (gnt == 2'b01) ? fsm_flush : 1'b0;
+ assign m1_res_fifo_flush = (gnt == 2'b10) ? fsm_flush : 1'b0;
+
+ assign spi_clock_en = tx_clk_en | rx_clk_en;
+
+ assign spi_en_tx_out = (spi_en_tx) && (spi_dummy ==0); // Don't Drive Tx On Dummy Phase
+
+ qspim_clkgen u_clkgen
+ (
+ .clk ( clk ),
+ .rstn ( rstn ),
+ .en ( spi_clock_en ),
+ .cfg_sck_period ( spi_clk_div [5:0] ),
+ .spi_clk ( spi_clk ),
+ .spi_fall ( spi_fall ),
+ .spi_rise ( spi_rise )
+ );
+ qspim_tx u_txreg
+ (
+ .clk ( clk ),
+ .rstn ( rstn ),
+ .flush ( fsm_flush ),
+ .en ( spi_en_tx ),
+ .tx_edge ( spi_fall ),
+ .tx_done ( tx_done ),
+ .sdo0 ( spi_sdo0 ),
+ .sdo1 ( spi_sdo1 ),
+ .sdo2 ( spi_sdo2 ),
+ .sdo3 ( spi_sdo3 ),
+ .s_spi_mode ( s_spi_mode ),
+ .counter_in ( counter_tx ),
+ .counter_in_upd ( counter_tx_valid ),
+ .dummy_phase ( dummy_phase ),
+ .txdata ( data_to_tx ),
+ .data_valid ( data_to_tx_valid ),
+ .data_ready ( tx_data_ready ),
+ .spi_dummy ( spi_dummy ),
+ .clk_en_o ( tx_clk_en )
+ );
+ qspim_rx #(.ENDIEAN(ENDIEAN)) u_rxreg
+ (
+ .clk ( clk ),
+ .rstn ( rstn ),
+ .flush ( fsm_flush ),
+ .en ( spi_en_rx ),
+ .rx_edge ( spi_rise ),
+ .rx_done ( rx_done ),
+ .sdi0 ( spi_sdi0 ),
+ .sdi1 ( spi_sdi1 ),
+ .sdi2 ( spi_sdi2 ),
+ .sdi3 ( spi_sdi3 ),
+ .s_spi_mode ( s_spi_mode ),
+ .counter_in ( counter_rx ),
+ .counter_in_upd ( counter_rx_valid ),
+ .data ( res_fifo_wdata ),
+ .data_valid ( res_fifo_wr ),
+ .data_ready ( !res_fifo_full ),
+ .clk_en_o ( rx_clk_en )
+ );
+
+ always_comb
+ begin
+ data_to_tx = 'h0;
+ data_to_tx_valid = 1'b0;
+ dummy_phase = 1'b0;
+
+ case(ctrl_data_mux)
+ DATA_NULL:
+ begin
+ data_to_tx = '0;
+ data_to_tx_valid = 1'b0;
+ end
+
+ DATA_EMPTY:
+ begin
+ dummy_phase = 1'b1;
+ data_to_tx = '0;
+ data_to_tx_valid = 1'b1;
+ end
+
+ DATA_CMD:
+ begin
+ data_to_tx = {cmd_fifo_rdata[7:0],24'h0};
+ data_to_tx_valid = ctrl_data_valid;
+ end
+ DATA_MODE:
+ begin
+ data_to_tx = {spi_mode_cmd,24'h0};
+ data_to_tx_valid = ctrl_data_valid;
+ end
+
+ DATA_ADDR:
+ begin
+ data_to_tx = (cfg_addr_cnt == P_8BIT) ? {cmd_fifo_rdata[7:0],24'h0} :
+ (cfg_addr_cnt == P_16BIT) ? {cmd_fifo_rdata[15:0],16'h0} :
+ (cfg_addr_cnt == P_24BIT) ? {cmd_fifo_rdata[23:0],8'h0} : {cmd_fifo_rdata[31:0]};
+ data_to_tx_valid = ctrl_data_valid;
+ end
+
+ // RISV is little endian, so data is converted to little endian format
+ DATA_FIFO: begin
+ data_to_tx = (ENDIEAN) ? cmd_fifo_rdata[31:0] :
+ {cmd_fifo_rdata[7:0],cmd_fifo_rdata[15:8],cmd_fifo_rdata[23:16],cmd_fifo_rdata[31:24]};
+ data_to_tx_valid = !cmd_fifo_empty;
+ end
+ endcase
+ end
+
+ always_comb
+ begin
+ fsm_flush = 0;
+ counter_tx = '0;
+ counter_tx_valid = 1'b0;
+ counter_rx = '0;
+ counter_rx_valid = 1'b0;
+ next_state = state;
+ ctrl_data_mux = DATA_NULL;
+ ctrl_data_valid = 1'b0;
+ spi_en_rx = 1'b0;
+ spi_en_tx = 1'b0;
+ spi_status = '0;
+ cmd_fifo_rd = 1'b0;
+ nxt_cnt = cnt;
+ case(state)
+ FSM_IDLE:
+ begin
+ spi_status[0] = 1'b1;
+ nxt_cnt = 0;
+ if(!m0_cmd_fifo_empty || !m1_cmd_fifo_empty ) begin
+ next_state = FSM_CS_ASSERT;
+ end
+ end
+
+ // Asserted CS# low
+ FSM_CS_ASSERT: begin
+ fsm_flush=1; // Flush stale data in response fifo
+ if(cfg_cs_early == cnt) begin
+ next_state = FSM_CMD_PHASE;
+ end else begin
+ nxt_cnt = nxt_cnt+1;
+ end
+ end
+
+ // WAIT for COMMAND Phase Completed
+ FSM_CMD_PHASE: begin
+ counter_tx = 8'h8;
+ ctrl_data_mux = DATA_CMD;
+ ctrl_data_valid = 1'b1;
+ counter_tx = 'd8;
+ counter_tx_valid = 1'b1;
+ spi_en_tx = 1'b1;
+ if (tx_data_ready) begin
+ cmd_fifo_rd = 1'b1;
+ case(cfg_spi_seq)
+ P_FSM_C: next_state = FSM_TX_DONE;
+ P_FSM_CW: next_state = FSM_WRITE_CMD;
+ P_FSM_CA: next_state = FSM_ADR_PHASE;
+ P_FSM_CAR: next_state = FSM_ADR_PHASE;
+ P_FSM_CADR: next_state = FSM_ADR_PHASE;
+ P_FSM_CAMR: next_state = FSM_ADR_PHASE;
+ P_FSM_CAMDR: next_state = FSM_ADR_PHASE;
+ P_FSM_CAW: next_state = FSM_ADR_PHASE;
+ P_FSM_CADW: next_state = FSM_ADR_PHASE;
+ P_FSM_CDR: next_state = FSM_DUMMY_PHASE;
+ P_FSM_CDW: next_state = FSM_DUMMY_PHASE;
+ P_FSM_CR: next_state = FSM_READ_WAIT;
+ default : next_state = FSM_TX_DONE;
+ endcase
+ end
+ end
+
+ // WAIT for ADDR Command Accepted
+ FSM_ADR_PHASE: begin
+ nxt_cnt = 0;
+ ctrl_data_mux = DATA_ADDR;
+ ctrl_data_valid = 1'b1;
+ counter_tx = (cfg_addr_cnt == P_8BIT) ? 'd8 :
+ (cfg_addr_cnt == P_16BIT) ? 'd16 :
+ (cfg_addr_cnt == P_24BIT) ? 'd24 : 'd32;
+ counter_tx_valid = 1'b1;
+ spi_en_tx = 1'b1;
+ if (tx_data_ready) begin
+ ctrl_data_valid = 1'b0;
+ cmd_fifo_rd = 1'b1;
+ case(cfg_spi_seq)
+ P_FSM_CA: next_state = FSM_TX_DONE;
+ P_FSM_CAR: next_state = FSM_READ_WAIT;
+ P_FSM_CADR: next_state = FSM_DUMMY_PHASE;
+ P_FSM_CAMR: next_state = FSM_MODE_PHASE;
+ P_FSM_CAMDR: next_state = FSM_MODE_PHASE;
+ P_FSM_CAW: next_state = FSM_WRITE_CMD;
+ P_FSM_CADW: next_state = FSM_DUMMY_PHASE;
+ default : next_state = FSM_TX_DONE;
+ endcase
+ end
+ end
+
+ // WAIT for DUMMY command Accepted
+ FSM_DUMMY_PHASE: begin
+ nxt_cnt = 0;
+ ctrl_data_mux = DATA_EMPTY;
+ ctrl_data_valid = 1'b1;
+ counter_tx_valid = 1'b1;
+ if(s_spi_mode == P_QDDR ) begin
+ // QDDR Mode, change the Dummy cycle values to 32,40,48,56
+ counter_tx = (cfg_dummy_cnt == 2'b00) ? 'd32 :
+ (cfg_dummy_cnt == 2'b01) ? 'd40 :
+ (cfg_dummy_cnt == 2'b10) ? 'd48 : 'd56;
+ end else begin
+ counter_tx = (cfg_dummy_cnt == P_8BIT) ? 'd8 :
+ (cfg_dummy_cnt == P_16BIT) ? 'd16 :
+ (cfg_dummy_cnt == P_24BIT) ? 'd24 : 'd32;
+ end
+ spi_en_tx = 1'b1;
+ if (tx_data_ready) begin
+ ctrl_data_valid = 1'b0;
+ case(cfg_spi_seq)
+ P_FSM_CADR: next_state = FSM_READ_WAIT;
+ P_FSM_CAMDR: next_state = FSM_READ_WAIT;
+ P_FSM_CADW: next_state = FSM_WRITE_CMD;
+ P_FSM_CDR: next_state = FSM_READ_WAIT;
+ P_FSM_CDW: next_state = FSM_WRITE_CMD;
+ default : next_state = FSM_CS_DEASEERT;
+ endcase
+ end
+ end
+ // WAIT for MODE command accepted
+ FSM_MODE_PHASE: begin
+ nxt_cnt = 0;
+ ctrl_data_mux = DATA_MODE;
+ ctrl_data_valid = 1'b1;
+ counter_tx_valid = 1'b1;
+ counter_tx = 'd8;
+ spi_en_tx = 1'b1;
+ if (tx_data_ready) begin
+ case(cfg_spi_seq)
+ P_FSM_CAMR: next_state = FSM_READ_WAIT;
+ P_FSM_CAMDR: next_state = FSM_DUMMY_PHASE;
+ default : next_state = FSM_CS_DEASEERT;
+ endcase
+ end
+ end
+
+ // Wait for WRITE COMMAND ACCEPTED
+ FSM_WRITE_CMD: begin
+ nxt_cnt = 0;
+ ctrl_data_mux = DATA_FIFO;
+ ctrl_data_valid = 1'b1;
+ counter_tx_valid = 1'b1;
+ counter_tx = {5'b0,cfg_data_cnt[7:0],3'b000}; // Convert Byte to Bit Count
+ spi_en_tx = 1'b1;
+ if (tx_data_ready) begin
+ cmd_fifo_rd = 1'b1;
+ next_state = FSM_WRITE_PHASE;
+ end
+ end
+
+ // Wait for ALL WRITE DATA ACCEPTED
+ FSM_WRITE_PHASE: begin
+ nxt_cnt = 0;
+ ctrl_data_mux = DATA_FIFO;
+ ctrl_data_valid = 1'b1;
+ spi_en_tx = 1'b1;
+ if (tx_done) begin
+ next_state = FSM_CS_DEASEERT;
+ end else if(tx_data_ready && cmd_fifo_empty == 0) begin
+ // Once Current Data is accepted by TX FSM, check FIFO not empty
+ // and read next location
+ cmd_fifo_rd = 1'b1;
+ end
+ end
+
+ // Wait for Previous TX Completeion
+ FSM_READ_WAIT: begin
+ spi_en_tx = 1'b1;
+ if (tx_done) begin
+ next_state = FSM_READ_PHASE;
+ end
+ end
+
+ FSM_READ_PHASE: begin
+ nxt_cnt = 0;
+ counter_rx_valid = 1'b1;
+ counter_rx = {5'b0,cfg_data_cnt[7:0],3'b000}; // Convert Byte to Bit Count
+ spi_en_rx = 1'b1;
+ if(!cmd_fifo_empty) begin
+ // If you see new command request, then abort the current request
+ next_state = FSM_FLUSH;
+ end else begin
+ if (rx_done) begin
+ next_state = FSM_CS_DEASEERT;
+ end
+ end
+ end
+
+ FSM_FLUSH: begin
+ fsm_flush = 1;
+ // Wait for safe SPI-clock de-assertion phase
+ if(spi_clock_en ==0) begin
+ next_state = FSM_CS_DEASEERT;
+ end
+ end
+ // Wait for TX Done
+ FSM_TX_DONE: begin
+ spi_en_tx = 1'b1;
+ if(tx_done) next_state = FSM_CS_DEASEERT;
+ end
+
+ // De-assert CS#
+ FSM_CS_DEASEERT: begin
+ if(cfg_cs_late == cnt) begin
+ next_state = FSM_IDLE;
+ end else begin
+ nxt_cnt = nxt_cnt+1;
+ end
+ end
+ endcase
+end
+
+
+
+
+ always @(posedge clk or negedge rstn) begin
+ if (rstn == 1'b0) begin
+ state <= FSM_IDLE;
+ cnt <= 'h0;
+ end else begin
+ state <= next_state;
+ cnt <= nxt_cnt;
+ end
+ end
+
+ //---------------------------------------------------------------------
+ // Grant Generation Based on FIFO empty, priority given to Master 0
+ // Grant switch happens only at FSM IDLE State
+ // ---------------------------------------------------------------------
+
+ always @(posedge clk or negedge rstn) begin
+ if (rstn == 1'b0) begin
+ gnt <= 0;
+ spi_mode_cmd <= 'h0;
+ cfg_spi_seq <= 'h0;
+ cfg_addr_cnt <= 'h0;
+ cfg_dummy_cnt <= 'h0;
+ cfg_data_cnt <= 'h0;
+ end else begin
+ if(state == FSM_IDLE) begin
+ if(!m0_cmd_fifo_empty) begin
+ cfg_data_cnt <= m0_cmd_fifo_rdata[31:24];
+ cfg_dummy_cnt <= m0_cmd_fifo_rdata[23:22];
+ cfg_addr_cnt <= m0_cmd_fifo_rdata[21:20];
+ cfg_spi_seq <= m0_cmd_fifo_rdata[19:16];
+ spi_mode_cmd <= m0_cmd_fifo_rdata[15:8];
+ gnt <= 2'b01;
+ end
+ else if(!m1_cmd_fifo_empty ) begin
+ cfg_data_cnt <= m1_cmd_fifo_rdata[31:24];
+ cfg_dummy_cnt <= m1_cmd_fifo_rdata[23:22];
+ cfg_addr_cnt <= m1_cmd_fifo_rdata[21:20];
+ cfg_spi_seq <= m1_cmd_fifo_rdata[19:16];
+ spi_mode_cmd <= m1_cmd_fifo_rdata[15:8];
+ gnt <= 2'b10;
+ end
+ end
+ end
+ end
+
+
+ //-----------------------------------------------------------------------
+ // SPI Mode Switch Control Logic
+ // Note: SPI Protocl Start with SPI_STD Mode (Sigle Bit Mode) Base on the
+ // Command, Type it Switch the mode at ADDRESS/DUMMY/DATA Phase
+ // QIOR(0xEB) -> Mode switch at Address Phase
+ // DIOR(0xBB) -> Mode Switch at Address Phase
+ // QOR (0x6B) -> Mode Switch at Data Phase
+ // DOR (0x3B) -> Mode Switch at Data Phase
+ // QPP (0x32) -> Mode Switch at Data Phase
+ // ----------------------------------------------------------------------
+ always @(posedge clk or negedge rstn) begin
+ if (rstn == 1'b0) begin
+ s_spi_mode <= P_SINGLE;
+ end else begin
+ if(state == FSM_IDLE) begin // Reset the Mode at IDLE State
+ s_spi_mode <= P_SINGLE;
+ end else if(state == FSM_ADR_PHASE && cfg_spi_switch == P_MODE_SWITCH_AT_ADDR) begin
+ s_spi_mode <= cfg_spi_mode;
+ end else if(((state == FSM_READ_PHASE) || state == FSM_WRITE_CMD ) && cfg_spi_switch == P_MODE_SWITCH_AT_DATA) begin
+ s_spi_mode <= cfg_spi_mode;
+ end
+ end
+ end
+
+ // SPI Chip Select Logic
+ always @(posedge clk or negedge rstn) begin
+ if (rstn == 1'b0) begin
+ spi_csn0 <= 1'b1;
+ spi_csn1 <= 1'b1;
+ spi_csn2 <= 1'b1;
+ spi_csn3 <= 1'b1;
+ end else begin
+ if(state != FSM_IDLE) begin
+ spi_csn0 <= ~cfg_cs_reg[0];
+ spi_csn1 <= ~cfg_cs_reg[1];
+ spi_csn2 <= ~cfg_cs_reg[2];
+ spi_csn3 <= ~cfg_cs_reg[3];
+ end else begin
+ spi_csn0 <= 1'b1;
+ spi_csn1 <= 1'b1;
+ spi_csn2 <= 1'b1;
+ spi_csn3 <= 1'b1;
+ end
+ end
+ end
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_fifo.sv b/verilog/rtl/qspim/src/qspim_fifo.sv
index e69de29..2b8bf73 100644
--- a/verilog/rtl/qspim/src/qspim_fifo.sv
+++ b/verilog/rtl/qspim/src/qspim_fifo.sv
@@ -0,0 +1,227 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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>
+//
+/*********************************************************************
+
+ SYNC FIFO
+
+ This file is part of the yifive project
+ https://github.com/dineshannayya/yifive_r0.git
+
+ Description: SYNC FIFO
+
+ To Do:
+ nothing
+
+ Author(s): Dinesh Annayya, dinesha@opencores.org
+
+ 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
+
+*******************************************************************/
+
+//-------------------------------------------
+// sync FIFO
+//-----------------------------------------------
+//`timescale 1ns/1ps
+
+module qspim_fifo (clk,
+ reset_n,
+ flush,
+ wr_en,
+ wr_data,
+ full,
+ afull,
+ rd_en,
+ empty,
+ aempty,
+ rd_data);
+
+ parameter W = 4'd8;
+ parameter DP = 3'd4;
+ parameter WR_FAST = 1'b1;
+ parameter RD_FAST = 1'b1;
+ parameter FULL_DP = DP;
+ parameter EMPTY_DP = 1'b0;
+
+ parameter AW = (DP == 2) ? 1 :
+ (DP == 4) ? 2 :
+ (DP == 8) ? 3 :
+ (DP == 16) ? 4 :
+ (DP == 32) ? 5 :
+ (DP == 64) ? 6 :
+ (DP == 128) ? 7 :
+ (DP == 256) ? 8 : 0;
+
+ output [W-1 : 0] rd_data;
+ input [W-1 : 0] wr_data;
+ input clk, reset_n, wr_en,flush,
+ rd_en;
+ output full, empty;
+ output afull, aempty; // about full and about to empty
+
+
+ // synopsys translate_off
+
+ initial begin
+ if (AW == 0) begin
+ $display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);
+ end // if (AW == 0)
+ end // initial begin
+
+ // synopsys translate_on
+
+ reg [W-1 : 0] mem[DP-1 : 0];
+
+ /*********************** write side ************************/
+ reg [AW:0] wr_ptr;
+ reg full_q;
+ wire full_c;
+ wire afull_c;
+ wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1;
+ wire [AW:0] wr_cnt = get_cnt(wr_ptr, rd_ptr);
+
+ assign full_c = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0;
+ assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0;
+
+
+ always @(posedge clk or negedge reset_n) begin
+ if (!reset_n) begin
+ wr_ptr <= 0;
+ full_q <= 0;
+ end
+ else begin
+ if(flush) begin
+ wr_ptr <= 0;
+ full_q <= 0;
+ end else if (wr_en) begin
+ wr_ptr <= wr_ptr_inc;
+ if (wr_cnt == (FULL_DP-1)) begin
+ full_q <= 1'b1;
+ end
+ end else begin
+ if (full_q && (wr_cnt<FULL_DP)) begin
+ full_q <= 1'b0;
+ end
+ end
+ end
+ end
+
+ assign full = (WR_FAST == 1) ? full_c : full_q;
+ assign afull = afull_c;
+
+ always @(posedge clk) begin
+ if (wr_en) begin
+ mem[wr_ptr[AW-1:0]] <= wr_data;
+ end
+ end
+
+
+ /************************ read side *****************************/
+ reg [AW:0] rd_ptr;
+ reg empty_q;
+ wire empty_c;
+ wire aempty_c;
+ wire [AW:0] rd_ptr_inc = rd_ptr + 1'b1;
+ wire [AW:0] rd_cnt = get_cnt(wr_ptr, rd_ptr);
+
+ assign empty_c = (rd_cnt == 0) ? 1'b1 : 1'b0;
+ assign aempty_c = (rd_cnt == 1) ? 1'b1 : 1'b0;
+
+ always @(posedge clk or negedge reset_n) begin
+ if (!reset_n) begin
+ rd_ptr <= 0;
+ empty_q <= 1'b1;
+ end
+ else begin
+ if(flush) begin
+ rd_ptr <= 0;
+ empty_q <= 1'b1;
+ end else if (rd_en) begin
+ rd_ptr <= rd_ptr_inc;
+ if (rd_cnt==(EMPTY_DP+1)) begin
+ empty_q <= 1'b1;
+ end
+ end else begin
+ if (empty_q && (rd_cnt!=EMPTY_DP)) begin
+ empty_q <= 1'b0;
+ end
+ end
+ end
+ end
+
+ assign empty = (RD_FAST == 1) ? empty_c : empty_q;
+ assign aempty = aempty_c;
+
+ reg [W-1 : 0] rd_data_q;
+
+ wire [W-1 : 0] rd_data_c = mem[rd_ptr[AW-1:0]];
+ always @(posedge clk) begin
+ rd_data_q <= rd_data_c;
+ end
+ assign rd_data = (RD_FAST == 1) ? rd_data_c : rd_data_q;
+
+
+function [AW:0] get_cnt;
+input [AW:0] wr_ptr, rd_ptr;
+begin
+ if (wr_ptr >= rd_ptr) begin
+ get_cnt = (wr_ptr - rd_ptr);
+ end
+ else begin
+ get_cnt = DP*2 - (rd_ptr - wr_ptr);
+ end
+end
+endfunction
+
+// synopsys translate_off
+always @(posedge clk) begin
+ if (wr_en && full) begin
+ $display($time, "%m Error! afifo overflow!");
+ $stop;
+ end
+end
+
+always @(posedge clk) begin
+ if (rd_en && empty) begin
+ $display($time, "%m error! afifo underflow!");
+ $stop;
+ end
+end
+// synopsys translate_on
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_if.sv b/verilog/rtl/qspim/src/qspim_if.sv
index e69de29..7d7d7ab 100644
--- a/verilog/rtl/qspim/src/qspim_if.sv
+++ b/verilog/rtl/qspim/src/qspim_if.sv
@@ -0,0 +1,335 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 WishBone I/F Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// SPI WishBone I/F module ////
+//// This block support following functionality ////
+//// 1. This block Response to Direct Memory Read and ////
+//// Register Write and Read Command ////
+//// 2. In case of Direct Memory Read, It check send the ////
+//// SPI Read command to SPI Ctrl logic and wait for ////
+//// Read data through Response ////
+//// ////
+//// To Do: ////
+//// 1. Add 4 Word Memory Fetch for better Through Put ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// V.0 - June 30, 2021 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+
+module qspim_if #( parameter WB_WIDTH = 32) (
+ input logic mclk,
+ input logic rst_n,
+
+ input logic wbd_stb_i, // strobe/request
+ input logic [WB_WIDTH-1:0] wbd_adr_i, // address
+ input logic wbd_we_i, // write
+ input logic [WB_WIDTH-1:0] wbd_dat_i, // data output
+ input logic [3:0] wbd_sel_i, // byte enable
+ output logic [WB_WIDTH-1:0] wbd_dat_o, // data input
+ output logic wbd_ack_o, // acknowlegement
+ output logic wbd_err_o, // error
+
+
+ // Configuration
+ input logic cfg_fsm_reset,
+ input logic [3:0] cfg_mem_seq, // SPI MEM SEQUENCE
+ input logic [1:0] cfg_addr_cnt, // SPI Addr Count
+ input logic [1:0] cfg_dummy_cnt, // SPI Dummy Count
+ input logic [7:0] cfg_data_cnt, // SPI Read Count
+ input logic [7:0] cfg_cmd_reg, // SPI MEM COMMAND
+ input logic [7:0] cfg_mode_reg, // SPI MODE REG
+ input logic spi_init_done, // SPI internal Init completed
+
+ // Towards Reg I/F
+ output logic spim_reg_req, // Reg Request
+ output logic [3:0] spim_reg_addr, // Reg Address
+ output logic spim_reg_we, // Reg Write/Read Command
+ output logic [3:0] spim_reg_be, // Reg Byte Enable
+ output logic [31:0] spim_reg_wdata, // Reg Write Data
+ input logic spim_reg_ack, // Read Ack
+ input logic [31:0] spim_reg_rdata, // Read Read Data
+
+ // Towards Command FIFO
+ input logic cmd_fifo_empty, // Command FIFO empty
+ output logic cmd_fifo_wr, // Command FIFO Write
+ output logic [33:0] cmd_fifo_wdata, // Command FIFO WData
+
+ // Towards Response FIFO
+ input logic res_fifo_empty, // Response FIFO Empty
+ output logic res_fifo_rd, // Response FIFO Read
+ input logic [31:0] res_fifo_rdata, // Response FIFO Data
+
+ output logic [3:0] state
+ );
+
+//------------------------------------------------
+// Parameter Decleration
+// -----------------------------------------------
+parameter SOC = 1'b1; // START of COMMAND
+parameter EOC = 1'b1; // END of COMMAND
+parameter NOC = 1'b0; // NORMAL COMMAND
+
+// State Machine state
+parameter IDLE = 4'b000;
+parameter ADR_PHASE = 4'b001;
+parameter CMD_WAIT = 4'b010;
+parameter READ_DATA = 4'b011;
+
+/*************************************************************
+* SPI FSM State Control
+*
+* OPERATION COMMAND SEQUENCE
+*
+* ERASE P4E(0x20) -> COMMAND + ADDRESS
+* ERASE P8E(0x40) -> COMMAND + ADDRESS
+* ERASE SE(0xD8) -> COMMAND + ADDRESS
+* ERASE BE(0x60) -> COMMAND + ADDRESS
+* ERASE BE(0xC7) -> COMMAND
+* PROGRAM PP(0x02) -> COMMAND + ADDRESS + Write DATA
+* PROGRAM QPP(0x32) -> COMMAND + ADDRESS + Write DATA
+* READ READ(0x3) -> COMMAND + ADDRESS + READ DATA
+* READ FAST_READ(0xB) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DOR (0x3B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ QOR (0x6B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DIOR (0xBB) -> COMMAND + ADDRESS + MODE + READ DATA
+* READ QIOR (0xEB) -> COMMAND + ADDRESS + MODE + DUMMY + READ DATA
+* READ RDID (0x9F) -> COMMAND + READ DATA
+* READ READ_ID (0x90) -> COMMAND + ADDRESS + READ DATA
+* WRITE WREN(0x6) -> COMMAND
+* WRITE WRDI -> COMMAND
+* STATUS RDSR(0x05) -> COMMAND + READ DATA
+* STATUS RCR(0x35) -> COMMAND + READ DATA
+* CONFIG WRR(0x01) -> COMMAND + WRITE DATA
+* CONFIG CLSR(0x30) -> COMMAND
+* Power Saving DP(0xB9) -> COMMAND
+* Power Saving RES(0xAB) -> COMMAND + READ DATA
+* OTP OTPP(0x42) -> COMMAND + ADDR+ WRITE DATA
+* OTP OTPR(0x4B) -> COMMAND + ADDR + DUMMY + READ DATA
+* ********************************************************************/
+
+parameter P_FSM_C = 4'b0000; // Command Phase Only
+parameter P_FSM_CA = 4'b0001; // Command -> Address Phase Only
+
+parameter P_FSM_CAR = 4'b0010; // Command -> Address -> Read Data
+parameter P_FSM_CADR = 4'b0011; // Command -> Address -> Dummy -> Read Data
+parameter P_FSM_CAMR = 4'b0100; // Command -> Address -> Mode -> Read Data
+parameter P_FSM_CAMDR = 4'b0101; // Command -> Address -> Mode -> Dummy -> Read Data
+
+parameter P_FSM_CAW = 4'b0110; // Command -> Address ->Write Data
+parameter P_FSM_CADW = 4'b0111; // Command -> Address -> DUMMY + Write Data
+//---------------------------------------------------------
+// Variable declartion
+// -------------------------------------------------------
+logic spim_mem_req ; // Current Request is Direct Memory Read
+
+
+logic spim_wb_req ;
+logic [WB_WIDTH-1:0] spim_wb_wdata ;
+logic [WB_WIDTH-1:0] spim_wb_addr ;
+logic spim_wb_ack ;
+logic spim_wb_we ;
+logic [3:0] spim_wb_be ;
+logic [WB_WIDTH-1:0] spi_mem_rdata ;
+logic [WB_WIDTH-1:0] spim_wb_rdata ;
+
+logic spim_mem_ack ;
+logic [3:0] next_state ;
+
+logic NextPreDVal ;
+logic [7:0] NextPreDCnt ;
+logic [31:0] NextPreAddr ;
+
+
+ //---------------------------------------------------------------
+ // Address Decoding
+ // 0x0000_0000 - 0x0FFF_FFFF - SPI FLASH MEMORY ACCESS - 256MB
+ // 0x1000_0000 - - SPI Register Access
+ //
+ //
+ // Note: Only Bit[28] is decoding done here, other Bit decoding
+ // will be done inside the wishbone inter-connect
+ // --------------------------------------------------------------
+
+ assign spim_mem_req = ((spim_wb_req) && spim_wb_addr[28] == 1'b0);
+ assign spim_reg_req = ((spim_wb_req) && spim_wb_addr[28] == 1'b1);
+
+ assign spim_reg_addr = spim_wb_addr[5:2];
+ assign spim_reg_wdata = spim_wb_wdata;
+ assign spim_reg_we = spim_wb_we;
+ assign spim_reg_be = spim_wb_be;
+
+ assign wbd_dat_o = spim_wb_rdata;
+ assign wbd_ack_o = spim_wb_ack;
+ assign wbd_err_o = 1'b0;
+
+ // To reduce the load/Timing Wishbone I/F, all the variable are registered
+always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ spim_wb_req <= '0;
+ spim_wb_wdata <= '0;
+ spim_wb_rdata <= '0;
+ spim_wb_addr <= '0;
+ spim_wb_be <= '0;
+ spim_wb_we <= '0;
+ spim_wb_ack <= '0;
+ end else begin
+ if(spi_init_done) begin // Wait for internal SPI Init Done
+ spim_wb_req <= wbd_stb_i && ((spim_wb_ack == 0) && (spim_mem_ack ==0) && (spim_reg_ack == 0));
+ spim_wb_wdata <= wbd_dat_i;
+ spim_wb_addr <= wbd_adr_i;
+ spim_wb_be <= wbd_sel_i;
+ spim_wb_we <= wbd_we_i;
+
+
+ if(!spim_wb_we && spim_mem_req && spim_mem_ack)
+ spim_wb_rdata <= spi_mem_rdata;
+ else if (spim_reg_req && spim_reg_ack)
+ spim_wb_rdata <= spim_reg_rdata;
+
+ spim_wb_ack <= (spim_mem_req) ? spim_mem_ack :
+ (spim_reg_req) ? spim_reg_ack : 1'b0;
+ end
+ end
+end
+
+
+always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ state <= IDLE;
+ end else begin
+ if(cfg_fsm_reset) state <= IDLE;
+ else state <= next_state;
+ end
+end
+
+/***********************************************************************************
+* This block interface with WishBone Request and Write Command & Read Response FIFO
+* **********************************************************************************/
+
+always_comb
+begin
+ cmd_fifo_wr = '0;
+ cmd_fifo_wdata = '0;
+ res_fifo_rd = 0;
+ spi_mem_rdata = '0;
+
+ spim_mem_ack = 0;
+ next_state = state;
+ case(state)
+ IDLE: begin
+ // Check If any prefetch data available and if see it matched with WB
+ // address, If yes, the move to data reading from response fifo, else
+ // generate command request
+ if(spim_mem_req && NextPreDVal && (spim_wb_addr == NextPreAddr)) begin
+ next_state = READ_DATA;
+ end else if(spim_mem_req && cmd_fifo_empty) begin
+ cmd_fifo_wdata = {SOC,NOC,cfg_data_cnt[7:0],cfg_dummy_cnt[1:0],cfg_addr_cnt[1:0],cfg_mem_seq[3:0],cfg_mode_reg[7:0],cfg_cmd_reg[7:0]};
+ cmd_fifo_wr = 1;
+ next_state = ADR_PHASE;
+ end
+ end
+ ADR_PHASE: begin
+ cmd_fifo_wdata = {NOC,EOC,spim_wb_addr[31:0]};
+ cmd_fifo_wr = 1;
+ next_state = CMD_WAIT;
+ end
+ CMD_WAIT: begin
+ // Wait for Command Accepted, before reading data
+ // to take care of staled data being read due to pre-fetch logic
+ if(cmd_fifo_empty) next_state = READ_DATA;
+ end
+
+
+ READ_DATA: begin
+ if(res_fifo_empty != 1) begin
+ spi_mem_rdata = res_fifo_rdata;
+ res_fifo_rd = 1;
+ spim_mem_ack = 1;
+ next_state = IDLE;
+ end
+ end
+ endcase
+end
+
+/*****************************************************************
+* This logic help to find any pre-fetch data available inside the response
+* FIFO and if the next data read request address matches with NextPreAddr, The read
+* the data from Response FIFO, else generate new request
+* Note: Basic Assumption is cmd_fifo_wr & res_fifo_rd does not occur in same
+* time as it's generation control through FSM
+* **********************************************************/
+
+always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ NextPreDVal <= 1'b0;
+ NextPreDCnt <= 'h0;
+ NextPreAddr <= 'h0;
+ end else if(cmd_fifo_wr) begin
+ NextPreDVal <= 1'b1;
+ NextPreDCnt <= cfg_data_cnt;
+ NextPreAddr <= spim_wb_addr;
+ end else if (res_fifo_rd) begin
+ if(NextPreDCnt == 4) begin
+ NextPreDVal <= 1'b0;
+ end else begin
+ NextPreDCnt <= NextPreDCnt-4;
+ NextPreAddr <= NextPreAddr+4;
+ end
+ end
+end
+
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_regs.sv b/verilog/rtl/qspim/src/qspim_regs.sv
index e69de29..d110ffb 100644
--- a/verilog/rtl/qspim/src/qspim_regs.sv
+++ b/verilog/rtl/qspim/src/qspim_regs.sv
@@ -0,0 +1,753 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 WishBone Register I/F Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// SPI WishBone I/F module ////
+//// This block support following functionality ////
+//// 1. Direct SPI Read memory support for address rang ////
+//// 0x0000 to 0x0FFF_FFFF - Use full for Instruction ////
+//// Data Memory fetch ////
+//// 2. SPI Local Register Access ////
+//// 3. Indirect register way to access SPI Memory ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// V.0 - June 8, 2021 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+
+module qspim_regs #( parameter WB_WIDTH = 32) (
+ input logic mclk ,
+ input logic rst_n ,
+ input logic fast_sim_mode , // Set 1 for simulation
+
+ output logic [7:0] spi_clk_div ,
+ output logic spi_init_done , // SPI internal Init completed
+
+ // Status Monitoring
+ input logic [31:0] spi_debug ,
+
+ // Master 0 Configuration
+ output logic cfg_m0_fsm_reset ,
+ output logic [3:0] cfg_m0_cs_reg , // Chip select
+ output logic [1:0] cfg_m0_spi_mode , // Final SPI Mode
+ output logic [1:0] cfg_m0_spi_switch, // SPI Mode Switching Place
+ output logic [3:0] cfg_m0_spi_seq , // SPI SEQUENCE
+ output logic [1:0] cfg_m0_addr_cnt , // SPI Addr Count
+ output logic [1:0] cfg_m0_dummy_cnt , // SPI Dummy Count
+ output logic [7:0] cfg_m0_data_cnt , // SPI Read Count
+ output logic [7:0] cfg_m0_cmd_reg , // SPI MEM COMMAND
+ output logic [7:0] cfg_m0_mode_reg , // SPI MODE REG
+
+ output logic [3:0] cfg_m1_cs_reg , // Chip select
+ output logic [1:0] cfg_m1_spi_mode , // Final SPI Mode
+ output logic [1:0] cfg_m1_spi_switch, // SPI Mode Switching Place
+
+ output logic [1:0] cfg_cs_early , // Amount of cycle early CS asserted
+ output logic [1:0] cfg_cs_late , // Amount of cycle late CS de-asserted
+
+ // Towards Reg I/F
+ input logic spim_reg_req , // Reg Request
+ input logic [3:0] spim_reg_addr , // Reg Address
+ input logic spim_reg_we , // Reg Write/Read Command
+ input logic [3:0] spim_reg_be , // Reg Byte Enable
+ input logic [31:0] spim_reg_wdata , // Reg Write Data
+ output logic spim_reg_ack , // Read Ack
+ output logic [31:0] spim_reg_rdata , // Read Read Data
+
+ // Towards Command FIFO
+ input logic cmd_fifo_full , // Command FIFO full
+ input logic cmd_fifo_empty , // Command FIFO empty
+ output logic cmd_fifo_wr , // Command FIFO Write
+ output logic [33:0] cmd_fifo_wdata , // Command FIFO WData
+
+ // Towards Response FIFO
+ input logic res_fifo_full , // Response FIFO Empty
+ input logic res_fifo_empty , // Response FIFO Empty
+ output logic res_fifo_rd , // Response FIFO Read
+ input logic [31:0] res_fifo_rdata , // Response FIFO Data
+
+ output logic [3:0] state
+ );
+//------------------------------------------------
+// Parameter Decleration
+// -----------------------------------------------
+parameter SOC = 1'b1; // START of COMMAND
+parameter EOC = 1'b1; // END of COMMAND
+parameter NOC = 1'b0; // NORMAL COMMAND
+
+parameter BTYPE = 1'b0; // Count is Byte Type
+parameter WTYPE = 1'b1; // Count is Word Type
+
+parameter CNT1 = 2'b00; // BYTE/WORD Count1
+parameter CNT2 = 2'b01; // BYTE/WORD Count2
+parameter CNT3 = 2'b10; // BYTE/WORD Count3
+parameter CNT4 = 2'b11; // BYTE/WORD Count4
+
+
+// Type of command
+parameter NWRITE = 2'b00; // Normal Write
+parameter NREAD = 2'b01; // Normal Read
+parameter DWRITE = 2'b10; // Dummy Write
+parameter DREAD = 2'b11; // Dummy Read
+
+// State Machine state
+parameter FSM_IDLE = 3'b000;
+parameter FSM_ADR_PHASE = 3'b001;
+parameter FSM_WRITE_PHASE = 3'b010;
+parameter FSM_READ_PHASE = 3'b011;
+parameter FSM_READ_BUSY = 3'b100;
+parameter FSM_WRITE_BUSY = 3'b101;
+parameter FSM_ACK_PHASE = 3'b110;
+
+//----------------------------
+// Register Decoding
+// ---------------------------
+parameter GLBL_CTRL = 4'b0000;
+parameter DMEM_CTRL1 = 4'b0001;
+parameter DMEM_CTRL2 = 4'b0010;
+parameter IMEM_CTRL1 = 4'b0011;
+parameter IMEM_CTRL2 = 4'b0100;
+parameter IMEM_ADDR = 4'b0101;
+parameter IMEM_WDATA = 4'b0110;
+parameter IMEM_RDATA = 4'b0111;
+parameter SPI_STATUS = 4'b1000;
+
+// Init FSM
+parameter SPI_INIT_PWUP = 3'b000;
+parameter SPI_INIT_IDLE = 3'b001;
+parameter SPI_INIT_CMD_WAIT = 3'b010;
+parameter SPI_INIT_WREN_CMD = 3'b011;
+parameter SPI_INIT_WREN_WAIT = 3'b100;
+parameter SPI_INIT_WRR_CMD = 3'b101;
+parameter SPI_INIT_WRR_WAIT = 3'b110;
+parameter SPI_INIT_WAIT = 3'b111;
+
+/*************************************************************
+* SPI FSM State Control
+*
+* OPERATION COMMAND SEQUENCE
+*
+* ERASE P4E(0x20) -> COMMAND + ADDRESS
+* ERASE P8E(0x40) -> COMMAND + ADDRESS
+* ERASE SE(0xD8) -> COMMAND + ADDRESS
+* ERASE BE(0x60) -> COMMAND + ADDRESS
+* ERASE BE(0xC7) -> COMMAND
+* PROGRAM PP(0x02) -> COMMAND + ADDRESS + Write DATA
+* PROGRAM QPP(0x32) -> COMMAND + ADDRESS + Write DATA
+* READ READ(0x3) -> COMMAND + ADDRESS + READ DATA
+* READ FAST_READ(0xB) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DOR (0x3B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ QOR (0x6B) -> COMMAND + ADDRESS + DUMMY + READ DATA
+* READ DIOR (0xBB) -> COMMAND + ADDRESS + MODE + READ DATA
+* READ QIOR (0xEB) -> COMMAND + ADDRESS + MODE + DUMMY + READ DATA
+* READ RDID (0x9F) -> COMMAND + READ DATA
+* READ READ_ID (0x90) -> COMMAND + ADDRESS + READ DATA
+* WRITE WREN(0x6) -> COMMAND
+* WRITE WRDI -> COMMAND
+* STATUS RDSR(0x05) -> COMMAND + READ DATA
+* STATUS RCR(0x35) -> COMMAND + READ DATA
+* CONFIG WRR(0x01) -> COMMAND + WRITE DATA
+* CONFIG CLSR(0x30) -> COMMAND
+* Power Saving DP(0xB9) -> COMMAND
+* Power Saving RES(0xAB) -> COMMAND + READ DATA
+* OTP OTPP(0x42) -> COMMAND + ADDR+ WRITE DATA
+* OTP OTPR(0x4B) -> COMMAND + ADDR + DUMMY + READ DATA
+* ********************************************************************/
+parameter P_FSM_C = 4'b0000; // Command Phase Only
+parameter P_FSM_CW = 4'b0001; // Command + Write DATA Phase Only
+parameter P_FSM_CA = 4'b0010; // Command -> Address Phase Only
+
+parameter P_FSM_CAR = 4'b0011; // Command -> Address -> Read Data
+parameter P_FSM_CADR = 4'b0100; // Command -> Address -> Dummy -> Read Data
+parameter P_FSM_CAMR = 4'b0101; // Command -> Address -> Mode -> Read Data
+parameter P_FSM_CAMDR = 4'b0110; // Command -> Address -> Mode -> Dummy -> Read Data
+
+parameter P_FSM_CAW = 4'b0111; // Command -> Address ->Write Data
+parameter P_FSM_CADW = 4'b1000; // Command -> Address -> DUMMY + Write Data
+
+parameter P_FSM_CDR = 4'b1001; // COMMAND -> DUMMY -> READ
+parameter P_FSM_CDW = 4'b1010; // COMMAND -> DUMMY -> WRITE
+parameter P_FSM_CR = 4'b1011; // COMMAND -> READ
+//---------------------------------------------------------
+ parameter P_CS0 = 4'b0001;
+ parameter P_CS1 = 4'b0010;
+ parameter P_CS2 = 4'b0100;
+ parameter P_CS3 = 4'b1000;
+
+ parameter P_SINGLE = 2'b00;
+ parameter P_DOUBLE = 2'b01;
+ parameter P_QUAD = 2'b10;
+
+ parameter P_MODE_SWITCH_IDLE = 2'b00;
+ parameter P_MODE_SWITCH_AT_ADDR = 2'b01;
+ parameter P_MODE_SWITCH_AT_DATA = 2'b10;
+
+ parameter P_QOR = 8'h6B;
+ parameter P_QIOR = 8'hEB;
+ parameter P_RES = 8'hAB;
+ parameter P_WEN = 8'h06;
+ parameter P_WRR = 8'h01;
+
+ parameter P_8BIT = 2'b00;
+ parameter P_16BIT = 2'b01;
+ parameter P_24BIT = 2'b10;
+ parameter P_32BIT = 2'b11;
+//---------------------------------------------------------
+// Variable declartion
+// -------------------------------------------------------
+logic [2:0] spi_init_state ;
+logic spim_reg_req_f ;
+
+logic [1:0] cfg_m1_fsm_reset ;
+logic [3:0] cfg_m1_spi_seq ; // SPI SEQUENCE
+logic [1:0] cfg_m1_addr_cnt ; // SPI Addr Count
+logic [1:0] cfg_m1_dummy_cnt ; // SPI Dummy Count
+logic [7:0] cfg_m1_data_cnt ; // SPI Read Count
+logic [7:0] cfg_m1_cmd_reg ; // SPI MEM COMMAND
+logic [7:0] cfg_m1_mode_reg ; // SPI MODE REG
+logic [31:0] cfg_m1_addr ;
+logic [31:0] cfg_m1_wdata ;
+logic [31:0] cfg_m1_rdata ;
+logic cfg_m1_wrdy ;
+logic cfg_m1_req ;
+
+logic [31:0] reg_rdata ;
+
+
+logic [5:0] cur_cnt ;
+logic [5:0] next_cnt ;
+logic [3:0] next_state ;
+
+
+logic [31:0] spim_m1_rdata ;
+logic spim_m1_ack ;
+logic spim_m1_rrdy ;
+logic spim_m1_wrdy ;
+logic [9:0] spi_delay_cnt ;
+logic spim_fifo_rdata_req ;
+logic spim_fifo_wdata_req ;
+
+
+//----------------------------------------------
+// Consolidated Register Ack handling
+// 1. Handles Normal Register Read
+// 2. Indirect Memory Write
+// 3. Indirect Memory Read
+//----------------------------------------------
+//
+assign spim_fifo_rdata_req = spim_reg_req && spim_reg_we == 0 && (spim_reg_addr== IMEM_RDATA);
+assign spim_fifo_wdata_req = spim_reg_req && spim_reg_we == 1 && (spim_reg_addr== IMEM_WDATA);
+
+always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ spim_reg_ack <= 1'b0;
+ spim_reg_rdata <= 'h0;
+ end else begin
+ if(spi_init_done && spim_reg_ack == 0) begin
+ if (spim_fifo_wdata_req && (spim_m1_wrdy == 1)) begin // Indirect Memory Write
+ // If FIFO Write DATA case, Make sure that there no previous pending
+ // need to processed
+ spim_reg_ack <= 1'b1;
+ end else if (spim_reg_req && spim_reg_we && (spim_reg_addr != IMEM_WDATA)) begin // Indirect memory Write
+ spim_reg_ack <= 1'b1;
+ end else if (spim_fifo_rdata_req && (spim_m1_rrdy == 1)) begin // Indirect mem Read
+ // If FIFO Read DATA case, Make sure that there Data is read from
+ // External SPI Memory
+ spim_reg_ack <= 1'b1;
+ spim_reg_rdata <= reg_rdata;
+ end else if (spim_reg_req && spim_reg_we == 0 && (spim_reg_addr != IMEM_RDATA)) begin // Normal Read
+ // Read other than FIFO Read Data case
+ spim_reg_ack <= 1'b1;
+ spim_reg_rdata <= reg_rdata;
+ end
+ end else begin
+ spim_reg_ack <= 1'b0;
+ end
+ end
+end
+
+ //---------------------------------------------
+ // Manges the initial Config Phase of SPI Memory
+ // 1. Power Up Command - RES(0xAB)
+ // 2. Write Enable Command - WEN (0x06)
+ // 3. WRITE CONFIG Reg - WRR (0x01) - Set Qaud Mode
+ // --------------------------------------------
+
+ logic [9:0] cfg_exit_cnt ;
+ assign cfg_exit_cnt = (fast_sim_mode) ? 100: 1000;
+
+ integer byte_index;
+ always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ cfg_m0_fsm_reset <= 'h0;
+ cfg_m0_cs_reg <= P_CS0;
+ cfg_m0_spi_mode <= P_QUAD;
+ cfg_m0_spi_switch <= P_MODE_SWITCH_AT_ADDR;
+ cfg_m0_cmd_reg <= P_QIOR;
+ cfg_m0_mode_reg <= 'h0;
+ cfg_m0_spi_seq[3:0] <= P_FSM_CAMDR;
+ cfg_m0_addr_cnt[1:0] <= P_24BIT;
+ cfg_m0_dummy_cnt[1:0] <= P_16BIT;
+ cfg_m0_data_cnt[7:0] <= 8'h20; // 32 Byte
+
+ cfg_m1_fsm_reset <= 'h0;
+ cfg_m1_cs_reg <= P_CS0;
+ cfg_m1_spi_mode <= P_QUAD;
+ cfg_m1_spi_switch <= P_MODE_SWITCH_AT_DATA;
+ cfg_m1_cmd_reg <= P_QOR;
+ cfg_m1_mode_reg <= 'h0;
+ cfg_m1_spi_seq[3:0] <= P_FSM_CADR;
+ cfg_m1_addr_cnt[1:0] <= P_24BIT;
+ cfg_m1_dummy_cnt[1:0] <= P_8BIT;
+ cfg_m1_data_cnt[7:0] <= 0;
+ cfg_m1_req <= 0;
+ cfg_m1_wrdy <= 1'b0;
+ cfg_m1_wdata <= 'h0; // Not Used
+
+ cfg_cs_early <= 'h1;
+ cfg_cs_late <= 'h1;
+ spi_clk_div <= 'h2;
+
+ spi_init_done <= 'h0;
+ spi_delay_cnt <= 'h0;
+ spim_reg_req_f <= 1'b0;
+ spi_init_state <= SPI_INIT_PWUP;
+ end else begin
+ spim_reg_req_f <= spim_reg_req; // Needed for finding Req Edge
+ if (spi_init_done == 0) begin
+ case(spi_init_state)
+
+ //----------------------------------------------
+ // SPI MEMORY Need minimum 5Us after power up
+ // With 100Mhz, 10ns translated to 500 cycle
+ // We are waiting 1000 cycle
+ // ---------------------------------------------
+ SPI_INIT_PWUP:begin
+ if(spi_delay_cnt == cfg_exit_cnt) begin
+ spi_init_state <= SPI_INIT_IDLE;
+ end else begin
+ spi_delay_cnt <= spi_delay_cnt+1;
+ end
+ end
+
+ SPI_INIT_IDLE:
+ begin
+ cfg_m1_cs_reg <= P_CS0;
+ cfg_m1_spi_mode <= P_SINGLE;
+ cfg_m1_spi_seq[3:0] <= P_FSM_C;
+ cfg_m1_spi_switch <= '0;
+ cfg_m1_cmd_reg <= P_RES;
+ cfg_m1_mode_reg <= 'h0; // Not Used
+ cfg_m1_addr_cnt[1:0] <= 'h0; // Not Used
+ cfg_m1_dummy_cnt[1:0]<= 'h0; // Not Used
+ cfg_m1_data_cnt[7:0] <= 'h0; // Not Used
+ cfg_m1_addr <= 'h0; // Not Used
+ cfg_m1_wdata <= 'h0; // Not Used
+ cfg_m1_req <= 'h1;
+ spi_init_state <= SPI_INIT_CMD_WAIT;
+ end
+ SPI_INIT_CMD_WAIT:
+ begin
+ if(spim_m1_ack) begin
+ cfg_m1_req <= 1'b0;
+ spi_init_state <= SPI_INIT_WREN_CMD;
+ end
+ end
+ SPI_INIT_WREN_CMD:
+ begin
+ cfg_m1_cs_reg <= P_CS0;
+ cfg_m1_spi_mode <= P_SINGLE;
+ cfg_m1_spi_seq[3:0] <= P_FSM_C;
+ cfg_m1_spi_switch <= '0;
+ cfg_m1_cmd_reg <= P_WEN;
+ cfg_m1_mode_reg <= 'h0; // Not Used
+ cfg_m1_addr_cnt[1:0] <= 'h0; // Not Used
+ cfg_m1_dummy_cnt[1:0]<= 'h0; // Not Used
+ cfg_m1_data_cnt[7:0] <= 'h0; // Not Used
+ cfg_m1_addr <= 'h0; // Not Used
+ cfg_m1_wdata <= 'h0; // Not Used
+ cfg_m1_req <= 'h1;
+ spi_init_state <= SPI_INIT_WREN_WAIT;
+ end
+ SPI_INIT_WREN_WAIT:
+ begin
+ if(spim_m1_ack) begin
+ cfg_m1_req <= 1'b0;
+ spi_init_state <= SPI_INIT_WRR_CMD;
+ end
+ end
+ SPI_INIT_WRR_CMD:
+ begin
+ cfg_m1_cs_reg <= P_CS0;
+ cfg_m1_spi_mode <= P_SINGLE;
+ cfg_m1_spi_seq[3:0] <= P_FSM_CW;
+ cfg_m1_spi_switch <= '0;
+ cfg_m1_cmd_reg <= P_WRR;
+ cfg_m1_mode_reg <= 'h0;
+ cfg_m1_addr_cnt[1:0] <= 'h0;
+ cfg_m1_dummy_cnt[1:0]<= 'h0;
+ cfg_m1_data_cnt[7:0] <= 'h2; // 2 Bytes
+ cfg_m1_addr <= 'h0;
+ cfg_m1_wrdy <= 1'b1;
+ cfg_m1_wdata <= {16'h0,8'h2,8'h0}; // <<cr1[7:0]><sr1[7:0]>> cr1[1] = 1 indicate quad mode cr1[7:6]=3
+ cfg_m1_req <= 'h1;
+ spi_init_state <= SPI_INIT_WRR_WAIT;
+ end
+ SPI_INIT_WRR_WAIT:
+ begin
+ if(spim_m1_ack) begin
+ spi_delay_cnt <= 'h0;
+ cfg_m1_wrdy <= 1'b0;
+ cfg_m1_req <= 1'b0;
+ spi_init_state <= SPI_INIT_WAIT;
+ end
+ end
+ SPI_INIT_WAIT:
+ begin // SPI MEMORY need 5us after WRR Command
+ if(spi_delay_cnt == cfg_exit_cnt) begin
+ spi_init_done <= 'h1;
+ end else begin
+ spi_delay_cnt <= spi_delay_cnt+1;
+ end
+ end
+ endcase
+ end else if (spim_reg_req && spim_reg_we && spi_init_done )
+ begin
+ case(spim_reg_addr)
+ GLBL_CTRL: begin
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_cs_early <= spim_reg_wdata[1:0];
+ cfg_cs_late <= spim_reg_wdata[3:2];
+ end
+ if ( spim_reg_be[1] == 1 ) begin
+ spi_clk_div <= spim_reg_wdata[15:8];
+ end
+ end
+ DMEM_CTRL1: begin // This register control Direct Memory Access Type
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_m0_cs_reg <= spim_reg_wdata[3:0]; // Chip Select for Memory Interface
+ cfg_m0_spi_mode <= spim_reg_wdata[5:4]; // SPI Mode, 0 - Normal, 1- Double, 2 - Qard, 3 - QDDR
+ cfg_m0_spi_switch<= spim_reg_wdata[7:6]; // Phase where to switch the SPI Mode
+ end
+ if ( spim_reg_be[1] == 1 ) begin
+ cfg_m0_fsm_reset <= spim_reg_wdata[8];
+ end
+ end
+ DMEM_CTRL2: begin // This register control Direct Memory Access Type
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_m0_cmd_reg <= spim_reg_wdata[7:0];
+ end
+ if ( spim_reg_be[1] == 1 ) begin
+ cfg_m0_mode_reg <= spim_reg_wdata[15:8];
+ end
+ if ( spim_reg_be[2] == 1 ) begin
+ cfg_m0_spi_seq[3:0] <= spim_reg_wdata[19:16];
+ cfg_m0_addr_cnt[1:0] <= spim_reg_wdata[21:20];
+ cfg_m0_dummy_cnt[1:0]<= spim_reg_wdata[23:22];
+ end
+ if ( spim_reg_be[3] == 1 ) begin
+ cfg_m0_data_cnt[7:0] <= spim_reg_wdata[31:24];
+ end
+ end
+ IMEM_CTRL1: begin
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_m1_cs_reg <= spim_reg_wdata[3:0]; // Chip Select for Memory Interface
+ cfg_m1_spi_mode <= spim_reg_wdata[5:4]; // SPI Mode, 0 - Normal, 1- Double, 2 - Qard
+ cfg_m1_spi_switch<= spim_reg_wdata[7:6]; // Phase where to switch the SPI Mode
+ end
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_m1_fsm_reset <= spim_reg_wdata[8];
+ end
+ end
+ IMEM_CTRL2: begin // This register control Direct Memory Access Type
+ if ( spim_reg_be[0] == 1 ) begin
+ cfg_m1_cmd_reg <= spim_reg_wdata[7:0];
+ end
+ if ( spim_reg_be[1] == 1 ) begin
+ cfg_m1_mode_reg <= spim_reg_wdata[15:8];
+ end
+ if ( spim_reg_be[2] == 1 ) begin
+ cfg_m1_spi_seq[3:0] <= spim_reg_wdata[19:16];
+ cfg_m1_addr_cnt[1:0] <= spim_reg_wdata[21:20];
+ cfg_m1_dummy_cnt[1:0]<= spim_reg_wdata[23:22];
+ end
+ if ( spim_reg_be[3] == 1 ) begin
+ cfg_m1_data_cnt[7:0] <= spim_reg_wdata[31:24];
+ end
+ end
+ IMEM_ADDR: begin
+ for (byte_index = 0; byte_index < 4; byte_index = byte_index+1 )
+ if ( spim_reg_be[byte_index] == 1 )
+ cfg_m1_addr[byte_index*8 +: 8] <= spim_reg_wdata[(byte_index*8) +: 8];
+ end
+ endcase
+ end
+ end
+ end
+
+
+
+ // implement slave model register read mux
+ always_comb
+ begin
+ reg_rdata = '0;
+ if(spim_reg_req) begin
+ case(spim_reg_addr)
+ GLBL_CTRL: reg_rdata[31:0] = {16'h0,spi_clk_div,4'h0,cfg_cs_late,cfg_cs_early};
+ DMEM_CTRL1: reg_rdata[31:0] = {23'h0,cfg_m0_fsm_reset,cfg_m0_spi_switch,cfg_m0_spi_mode,cfg_m0_cs_reg};
+ DMEM_CTRL2: reg_rdata[31:0] = {cfg_m0_data_cnt,cfg_m0_dummy_cnt,cfg_m0_addr_cnt,cfg_m0_spi_seq,cfg_m0_mode_reg,cfg_m0_cmd_reg};
+ IMEM_CTRL1: reg_rdata[31:0] = {23'h0, cfg_m1_fsm_reset,cfg_m1_spi_switch,cfg_m1_spi_mode,cfg_m1_cs_reg};
+ IMEM_CTRL2: reg_rdata[31:0] = {cfg_m1_data_cnt,cfg_m1_dummy_cnt,cfg_m1_addr_cnt,cfg_m1_spi_seq,cfg_m1_mode_reg,cfg_m1_cmd_reg};
+ IMEM_ADDR: reg_rdata[31:0] = cfg_m1_addr;
+ IMEM_WDATA: reg_rdata[31:0] = cfg_m1_wdata;
+ IMEM_RDATA: reg_rdata[31:0] = cfg_m1_rdata;
+ SPI_STATUS: reg_rdata[31:0] = spi_debug;
+ endcase
+ end
+ end
+
+// FSM
+
+always_ff @(negedge rst_n or posedge mclk) begin
+ if ( rst_n == 1'b0 ) begin
+ cur_cnt <= 'h0;
+ state <= FSM_IDLE;
+ end else begin
+ if(cfg_m1_fsm_reset) begin
+ cur_cnt <= 'h0;
+ state <= FSM_IDLE;
+ end else begin
+ cur_cnt <= next_cnt;
+ state <= next_state;
+ end
+ end
+end
+
+/***********************************************************************************
+* This block interface with WishBone Request and Write Command & Read Response FIFO
+* **********************************************************************************/
+
+logic [7:0] cfg_data_cnt;
+logic [31:0] spim_fifo_wdata;
+logic spim_fifo_req;
+assign cfg_data_cnt = cfg_m1_data_cnt-1;
+
+assign spim_fifo_req = cfg_m1_req || spim_fifo_rdata_req || spim_fifo_wdata_req;
+
+assign spim_fifo_wdata = (cfg_m1_req) ? cfg_m1_wdata : spim_reg_wdata;
+
+always_comb
+begin
+ cmd_fifo_wr = '0;
+ cmd_fifo_wdata = '0;
+
+ res_fifo_rd = 0;
+ spim_m1_rdata = '0;
+
+ spim_m1_ack = 0;
+ spim_m1_rrdy = 0;
+ next_cnt = cur_cnt;
+ next_state = state;
+ spim_m1_rrdy = 0;
+ spim_m1_wrdy = 0;
+ cfg_m1_rdata = 0;
+
+ case(state)
+ FSM_IDLE: begin
+ next_cnt = 0;
+ if(spim_fifo_req && cmd_fifo_empty) begin
+ case(cfg_m1_spi_seq)
+ P_FSM_C: begin
+ cmd_fifo_wdata = {SOC,EOC, cfg_m1_data_cnt[7:0],cfg_m1_dummy_cnt[1:0],
+ cfg_m1_addr_cnt[1:0],cfg_m1_spi_seq[3:0],
+ cfg_m1_mode_reg[7:0],cfg_m1_cmd_reg[7:0]};
+ spim_m1_wrdy = 1;
+ next_state = FSM_ACK_PHASE;
+ end
+ P_FSM_CW,
+ P_FSM_CDW:
+ begin
+ cmd_fifo_wdata = {SOC,NOC, cfg_m1_data_cnt[7:0],cfg_m1_dummy_cnt[1:0],
+ cfg_m1_addr_cnt[1:0],cfg_m1_spi_seq[3:0],
+ cfg_m1_mode_reg[7:0],cfg_m1_cmd_reg[7:0]};
+ next_state = FSM_WRITE_PHASE;
+ end
+ P_FSM_CA,
+ P_FSM_CAR,
+ P_FSM_CADR,
+ P_FSM_CAMR,
+ P_FSM_CAMDR,
+ P_FSM_CAW,
+ P_FSM_CADW:
+ begin
+ cmd_fifo_wdata = {SOC,NOC, cfg_m1_data_cnt[7:0],cfg_m1_dummy_cnt[1:0],
+ cfg_m1_addr_cnt[1:0],cfg_m1_spi_seq[3:0],
+ cfg_m1_mode_reg[7:0],cfg_m1_cmd_reg[7:0]};
+ next_state = FSM_ADR_PHASE;
+ end
+ P_FSM_CDR,
+ P_FSM_CR:
+ begin
+ cmd_fifo_wdata = {SOC,EOC, cfg_m1_data_cnt[7:0],cfg_m1_dummy_cnt[1:0],
+ cfg_m1_addr_cnt[1:0],cfg_m1_spi_seq[3:0],
+ cfg_m1_mode_reg[7:0],cfg_m1_cmd_reg[7:0]};
+ next_state = FSM_READ_PHASE;
+ end
+
+
+ endcase
+ cmd_fifo_wr = 1;
+ end
+ end
+ // ADDRESS PHASE
+ FSM_ADR_PHASE: begin
+ if(!cmd_fifo_full) begin
+ case(cfg_m1_spi_seq)
+ P_FSM_CA: // COMMAND + ADDRESS PHASE
+ begin
+ cmd_fifo_wdata = {NOC,EOC,cfg_m1_addr[31:0]};
+ spim_m1_wrdy = 1;
+ next_state = FSM_ACK_PHASE;
+ end
+ P_FSM_CAR, // COMMAND + ADDRESS + READ PHASE
+ P_FSM_CADR, // COMMAND + ADDRESS + DUMMY + READ PHASE
+ P_FSM_CAMR, // COMMAND + ADDRESS + MODE + READ PHASE
+ P_FSM_CAMDR: // COMMAND + ADDRESS + MODE + DUMMY + READ PHASE
+ begin
+ cmd_fifo_wdata = {NOC,EOC,cfg_m1_addr[31:0]};
+ next_cnt = 'h0;
+ next_state = FSM_READ_PHASE;
+ end
+
+ P_FSM_CAW,
+ P_FSM_CADW:
+ begin
+ cmd_fifo_wdata = {NOC,NOC,cfg_m1_addr[31:0]};
+ next_cnt = 'h0;
+ next_state = FSM_WRITE_PHASE;
+ end
+ endcase
+ cmd_fifo_wr = 1;
+ end
+ end
+
+ //----------------------------------------------------------
+ // Check Resonse FIFO is not empty then read the data from response fifo
+ // ---------------------------------------------------------
+ FSM_READ_PHASE: begin
+ if(res_fifo_empty != 1 && spim_fifo_rdata_req) begin
+ spim_m1_rrdy = 1;
+ cfg_m1_rdata = res_fifo_rdata;
+ res_fifo_rd = 1;
+ if(cfg_data_cnt[7:2] == cur_cnt) begin
+ next_state = FSM_ACK_PHASE;
+ end else begin
+ next_state = FSM_READ_BUSY;
+ next_cnt = cur_cnt+1;
+ end
+ end
+ end
+ //----------------------------------------------
+ // Wait for Previous Read Data Read
+ // ---------------------------------------------
+ FSM_READ_BUSY: begin
+ spim_m1_rrdy = 0;
+ if(spim_fifo_rdata_req == 0) begin
+ next_state = FSM_READ_PHASE;
+ end
+ end
+
+ //----------------------------------------------------------
+ // Check command FIFO is not full and Write Data is available
+ // ---------------------------------------------------------
+ FSM_WRITE_PHASE: begin
+ if(cmd_fifo_full != 1 && spim_fifo_req) begin
+ // If this a single word config cycle or
+ // in crrent spim_fifo_wr request
+ spim_m1_wrdy = 1;
+ if(cfg_data_cnt[7:2] == cur_cnt) begin
+ cmd_fifo_wdata = {NOC,EOC,spim_fifo_wdata[31:0]};
+ next_state = FSM_ACK_PHASE;
+ end else begin
+ cmd_fifo_wdata = {NOC,NOC,spim_fifo_wdata[31:0]};
+ next_state = FSM_WRITE_BUSY;
+ next_cnt = cur_cnt+1;
+ end
+ cmd_fifo_wr = 1;
+ end
+ end
+ //----------------------------------------------
+ // Wait for NEXT Data Ready
+ // ---------------------------------------------
+ FSM_WRITE_BUSY: begin
+ spim_m1_wrdy = 0;
+ if(spim_fifo_wdata_req == 0) begin
+ next_state = FSM_WRITE_PHASE;
+ end
+ end
+
+ FSM_ACK_PHASE: begin
+ spim_m1_ack = 1;
+ next_state = FSM_IDLE;
+ end
+
+ endcase
+
+
+end
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_rx.sv b/verilog/rtl/qspim/src/qspim_rx.sv
index e69de29..097ae59 100644
--- a/verilog/rtl/qspim/src/qspim_rx.sv
+++ b/verilog/rtl/qspim/src/qspim_rx.sv
@@ -0,0 +1,229 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 RX Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// SPI RX module ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// V.0 - June 8, 2021 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+
+module qspim_rx #(
+ parameter ENDIEAN = 0 // 0 - Little, 1 - Big endian, since RISV is Little indian default set 0
+ )
+(
+ input logic clk,
+ input logic rstn,
+ input logic flush,
+ input logic en,
+ input logic rx_edge,
+ output logic rx_done,
+ input logic sdi0,
+ input logic sdi1,
+ input logic sdi2,
+ input logic sdi3,
+ input logic [1:0] s_spi_mode,
+ input logic [15:0] counter_in,
+ input logic counter_in_upd,
+ output logic [31:0] data,
+ input logic data_ready,
+ output logic data_valid,
+ output logic clk_en_o
+);
+//------------------------------------------------------
+// Parameter Decleration
+// -----------------------------------------------------
+ parameter P_SINGLE = 2'b00;
+ parameter P_DOUBLE = 2'b01;
+ parameter P_QUAD = 2'b10;
+ parameter P_QDDR = 2'b11;
+
+//------------------------------------------------------
+// Variable Decleration
+// -----------------------------------------------------
+
+ logic [31:0] data_int;
+ logic [31:0] data_int_next;
+ logic [15:0] counter;
+ logic [15:0] counter_trgt;
+ logic [15:0] counter_next;
+ logic reg_done;
+ logic data_valid_i;
+ logic qddr_rx_en;
+ enum logic [1:0] { IDLE, RECEIVE, WAIT_FIFO, WAIT_FIFO_DONE } rx_CS, rx_NS;
+
+
+ assign reg_done = (s_spi_mode == P_SINGLE && (counter[4:0] == 5'b11111)) ||
+ (s_spi_mode == P_DOUBLE && (counter[3:0] == 4'b1111)) ||
+ (s_spi_mode == P_QUAD && (counter[2:0] == 3'b111)) ||
+ (s_spi_mode == P_QDDR && (counter[2:0] == 3'b111));
+
+
+
+ always_comb
+ begin
+ rx_NS = rx_CS;
+ data_int_next = data_int;
+ data_valid_i = 1'b0;
+ counter_next = counter;
+
+ case (rx_CS)
+ IDLE: begin
+
+ // check first if there is available space instead of later
+ if (en) begin
+ rx_NS = RECEIVE;
+ end
+ end
+
+ RECEIVE: begin
+
+ if (rx_edge || qddr_rx_en) begin
+ counter_next = counter + 1;
+ if ((s_spi_mode == P_QUAD ) || (s_spi_mode == P_QDDR ))
+ data_int_next = {data_int[27:0],sdi3,sdi2,sdi1,sdi0};
+ else if (s_spi_mode == P_DOUBLE )
+ data_int_next = {data_int[29:0],sdi1,sdi0};
+ else
+ data_int_next = {data_int[30:0],sdi1};
+
+ if (rx_done) begin
+ counter_next = 0;
+ if (data_ready) begin
+ data_valid_i = 1'b1;
+ rx_NS = IDLE;
+ end else
+ rx_NS = WAIT_FIFO_DONE;
+ end else if (reg_done) begin
+ if (data_ready) begin
+ data_valid_i = 1'b1;
+ end else begin
+ // no space in the FIFO, wait for free space
+ rx_NS = WAIT_FIFO;
+ end
+ end
+ end
+ end
+
+ WAIT_FIFO_DONE: begin
+ if (data_ready) begin
+ data_valid_i = 1'b1;
+ rx_NS = IDLE;
+ end
+ end
+
+ WAIT_FIFO: begin
+ if (data_ready) begin
+ data_valid_i = 1'b1;
+ rx_NS = RECEIVE;
+ end
+ end
+ endcase
+ end
+
+
+ always_ff @(posedge clk, negedge rstn)
+ begin
+ if (rstn == 0)
+ begin
+ counter <= 0;
+ counter_trgt <= 'h8;
+ data_int <= '0;
+ rx_done <= '0;
+ clk_en_o <= '0;
+ data <= 'b0;
+ data_valid <= 1'b0;
+ qddr_rx_en <= '0;
+ rx_CS <= IDLE;
+ end else if(flush && rx_edge) begin
+ counter <= 0;
+ counter_trgt <= 'h8;
+ data_int <= '0;
+ rx_done <= '0;
+ clk_en_o <= '0;
+ data <= 'b0;
+ data_valid <= 1'b0;
+ qddr_rx_en <= 0;
+ rx_CS <= IDLE;
+ end else begin
+ // Enable qddr rx after first rx edge
+ if(en && rx_edge && (rx_CS == RECEIVE) && (s_spi_mode ==P_QDDR)) begin
+ qddr_rx_en <= 1;
+ end else if(!en || rx_done) begin
+ qddr_rx_en <= 0;
+ end
+
+ data_valid <= data_valid_i;
+ data <= (ENDIEAN) ? data_int_next : {data_int_next[7:0],data_int_next[15:8],data_int_next[23:16],data_int_next[31:24]};
+ clk_en_o <= (rx_NS == RECEIVE);
+ if (rx_edge || qddr_rx_en) begin
+ counter <= counter_next;
+ data_int <= data_int_next;
+ rx_CS <= rx_NS;
+ rx_done <= (counter_next == (counter_trgt-1)) && (rx_NS == RECEIVE);
+ clk_en_o <= (rx_NS == RECEIVE);
+ end
+ if (en && counter_in_upd) begin
+ counter_trgt <= (s_spi_mode ==P_QDDR ) ? {2'b00,counter_in[15:2]} :
+ (s_spi_mode ==P_QUAD ) ? {2'b00,counter_in[15:2]} :
+ (s_spi_mode ==P_DOUBLE ) ? {1'b0,counter_in[15:1]} : counter_in;
+ end
+ end
+ end
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_top.sv b/verilog/rtl/qspim/src/qspim_top.sv
index e69de29..036e8c8 100644
--- a/verilog/rtl/qspim/src/qspim_top.sv
+++ b/verilog/rtl/qspim/src/qspim_top.sv
@@ -0,0 +1,475 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 Master Top Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// SPI Master Top module ////
+//// There are two seperate Data path managed here ////
+//// with seperate command and response memory ////
+//// Master-0 : This is targetted for CORE IMEM request ////
+//// and expect only Read access ////
+//// Master-1: This is targetted to CORE DMEM or ////
+//// Indirect Memory access, Both Write and Read ////
+//// accesss are supported. ////
+//// Upto 255 Byte Read/Write Burst supported ////
+//// Limitation: ////
+//// 1. Write/Read FIFO Abort case not managed M1 port, ////
+//// expect user to clearly close the busrt request ////
+//// 2. Wishbone Request abort not yet supported. ////
+//// 3. Write access through M0 Port not supported ////
+//// 4. When Pre fetch feature used and both port m0 and ////
+//// m1 used, user need to make sure that data pre fetch////
+//// count is withing 8DW, less Read path can hang due ////
+//// to response FIFO full from one master port ////
+//// ////
+//// To Do: ////
+//// 1. Add support for WishBone request timout ////
+//// 2. Add Pre-fetch feature for M0 Port ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : ////
+//// V.0 - June 8, 2021 ////
+//// V.1 - June 25, 2021 ////
+//// Pad logic is brought inside the block to avoid ////
+//// logic at digital core level for caravel project ////
+//// V.2 - July 6, 2021 ////
+//// Added Hold fix cell for SPI data out signal to ////
+//// met interface hold ////
+//// V.3 - July 13, 2021 ////
+//// Data Prefetch feature added in M0 port, If Only ////
+//// M0 Read used, then Prefetch read can be 255 Byte, ////
+//// But if the Both M0 and M1 read access enabled, ////
+//// then user need to make sure that M0 Prefetch is ////
+//// with in 8DW or 32 Byte, else there is chance ////
+//// data path can hang due to response FIFO full due ////
+//// to partial reading of data ////
+//// V.4 - July 26, 2021 ////
+//// QDDR (0xED) supported is added ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+
+
+module qspim_top
+#( parameter WB_WIDTH = 32)
+(
+ input logic mclk,
+ input logic rst_n,
+
+
+ input logic wbd_stb_i, // strobe/request
+ input logic [WB_WIDTH-1:0] wbd_adr_i, // address
+ input logic wbd_we_i, // write
+ input logic [WB_WIDTH-1:0] wbd_dat_i, // data output
+ input logic [3:0] wbd_sel_i, // byte enable
+ output logic [WB_WIDTH-1:0] wbd_dat_o, // data input
+ output logic wbd_ack_o, // acknowlegement
+ output logic wbd_err_o, // error
+
+ output logic [31:0] spi_debug,
+
+ // PAD I/f
+ input logic [3:0] spi_sdi,
+ output logic spi_clk,
+ output logic spi_csn0,// No hold fix for CS#, as it asserted much eariler than SPI clock
+ output logic [3:0] spi_sdo,
+ output logic [3:0] spi_oen
+);
+
+
+
+ logic [7:0] spi_clk_div ;
+
+ // Master 0 Configuration
+ logic cfg_m0_fsm_reset ;
+ logic [3:0] cfg_m0_cs_reg ; // Chip select
+ logic [1:0] cfg_m0_spi_mode ; // Final SPI Mode
+ logic [1:0] cfg_m0_spi_switch; // SPI Mode Switching Place
+ logic [3:0] cfg_m0_spi_seq ; // SPI SEQUENCE
+ logic [1:0] cfg_m0_addr_cnt ; // SPI Addr Count
+ logic [1:0] cfg_m0_dummy_cnt ; // SPI Dummy Count
+ logic [7:0] cfg_m0_data_cnt ; // SPI Read Count
+ logic [7:0] cfg_m0_cmd_reg ; // SPI MEM COMMAND
+ logic [7:0] cfg_m0_mode_reg ; // SPI MODE REG
+
+ logic [3:0] cfg_m1_cs_reg ; // Chip select
+ logic [1:0] cfg_m1_spi_mode ; // Final SPI Mode
+ logic [1:0] cfg_m1_spi_switch; // SPI Mode Switching Place
+
+ logic [1:0] cfg_cs_early ; // Amount of cycle early CS asserted
+ logic [1:0] cfg_cs_late ; // Amount of cycle late CS de-asserted
+
+ // Towards Reg I/F
+ logic spim_reg_req ; // Reg Request
+ logic [3:0] spim_reg_addr ; // Reg Address
+ logic spim_reg_we ; // Reg Write/Read Command
+ logic [3:0] spim_reg_be ; // Reg Byte Enable
+ logic [31:0] spim_reg_wdata ; // Reg Write Data
+ logic spim_reg_ack ; // Read Ack
+ logic [31:0] spim_reg_rdata ; // Read Read Data
+
+ // Towards m0 Command FIFO
+ logic m0_cmd_fifo_full ; // Command FIFO full
+ logic m0_cmd_fifo_empty ; // Command FIFO empty
+ logic m0_cmd_fifo_wr ; // Command FIFO Write
+ logic m0_cmd_fifo_rd ; // Command FIFO read
+ logic [33:0] m0_cmd_fifo_wdata ; // Command FIFO WData
+ logic [33:0] m0_cmd_fifo_rdata ; // Command FIFO RData
+
+ // Towards m0 Response FIFO
+ logic m0_res_fifo_full ; // Response FIFO Empty
+ logic m0_res_fifo_empty ; // Response FIFO Empty
+ logic m0_res_fifo_wr ; // Response FIFO Write
+ logic m0_res_fifo_rd ; // Response FIFO Read
+ logic [31:0] m0_res_fifo_wdata ; // Response FIFO WData
+ logic [31:0] m0_res_fifo_rdata ; // Response FIFO RData
+
+ // Towards m1 Command FIFO
+ logic m1_cmd_fifo_full ; // Command FIFO full
+ logic m1_cmd_fifo_empty ; // Command FIFO empty
+ logic m1_cmd_fifo_wr ; // Command FIFO Write
+ logic m1_cmd_fifo_rd ; // Command FIFO Write
+ logic [33:0] m1_cmd_fifo_wdata ; // Command FIFO WData
+ logic [33:0] m1_cmd_fifo_rdata ; // Command FIFO RData
+
+ // Towards m0 Response FIFO
+ logic m1_res_fifo_full ; // Response FIFO Empty
+ logic m1_res_fifo_empty ; // Response FIFO Empty
+ logic m1_res_fifo_wr ; // Response FIFO Read
+ logic m1_res_fifo_rd ; // Response FIFO Read
+ logic [31:0] m1_res_fifo_wdata ; // Response FIFO WData
+ logic [31:0] m1_res_fifo_rdata ; // Response FIFO RData
+
+ logic m0_res_fifo_flush ; // m0 response fifo flush
+ logic m1_res_fifo_flush ; // m0 response fifo flush
+
+//-----------------------------------------------------
+// SPI Debug monitoring
+// ----------------------------------------------------
+ logic [8:0] spi_ctrl_status ;
+ logic [3:0] m0_state ;
+ logic [3:0] m1_state ;
+ logic [3:0] ctrl_state ;
+
+
+ assign spi_debug = {m0_res_fifo_flush,m1_res_fifo_flush,spi_init_done,
+ m0_cmd_fifo_full,m0_cmd_fifo_empty,m0_res_fifo_full,m0_res_fifo_empty,
+ m1_cmd_fifo_full,m1_cmd_fifo_empty,m1_res_fifo_full,m1_res_fifo_empty,
+ ctrl_state[3:0], m0_state[3:0],m1_state[3:0],spi_ctrl_status[8:0]};
+
+//-------------------------------------------------------
+// SPI Interface moved inside to support carvel IO pad
+// -------------------------------------------------------
+
+logic spi_csn1;
+logic spi_csn2;
+logic spi_csn3;
+logic [1:0] spi_mode;
+logic spi_en_tx;
+logic spi_init_done;
+logic [3:0] spi_sdo_int;
+
+logic spi_sdo0_dl;
+logic spi_sdo1_dl;
+logic spi_sdo2_dl;
+logic spi_sdo3_dl;
+
+
+
+// ADDing Delay cells for Interface hold fix
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay1_sdio0 (.X(spi_sdo0_d1),.A(spi_sdo_int[0]));
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay2_sdio0 (.X(spi_sdo0_d2),.A(spi_sdo0_d1));
+sky130_fd_sc_hd__clkbuf_16 u_buf_sdio0 (.X(spi_sdo[0]),.A(spi_sdo0_d2));
+
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay1_sdio1 (.X(spi_sdo1_d1),.A(spi_sdo_int[1]));
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay2_sdio1 (.X(spi_sdo1_d2),.A(spi_sdo1_d1));
+sky130_fd_sc_hd__clkbuf_16 u_buf_sdio1 (.X(spi_sdo[1]),.A(spi_sdo1_d2));
+
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay1_sdio2 (.X(spi_sdo2_d1),.A(spi_sdo_int[2]));
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay2_sdio2 (.X(spi_sdo2_d2),.A(spi_sdo2_d1));
+sky130_fd_sc_hd__clkbuf_16 u_buf_sdio2 (.X(spi_sdo[2]),.A(spi_sdo2_d2));
+
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay1_sdio3 (.X(spi_sdo3_d1),.A(spi_sdo_int[3]));
+sky130_fd_sc_hd__dlygate4sd3_1 u_delay2_sdio3 (.X(spi_sdo3_d2),.A(spi_sdo3_d1));
+sky130_fd_sc_hd__clkbuf_16 u_buf_sdio3 (.X(spi_sdo[3]),.A(spi_sdo3_d2));
+
+
+assign #1 spi_oen[0] = !spi_en_tx; // SPI_DIO0
+assign #1 spi_oen[1] = !spi_en_tx; // SPI_DIO1
+assign #1 spi_oen[2] = (spi_mode == 0) ? 1 'b0 : !spi_en_tx; // HOLD
+assign #1 spi_oen[3] = (spi_mode == 0) ? 1 'b0 : !spi_en_tx; //
+
+
+qspim_if #( .WB_WIDTH(WB_WIDTH)) u_wb_if(
+ .mclk (mclk ),
+ .rst_n (rst_n ),
+
+ .wbd_stb_i (wbd_stb_i ), // strobe/request
+ .wbd_adr_i (wbd_adr_i ), // address
+ .wbd_we_i (wbd_we_i ), // write
+ .wbd_dat_i (wbd_dat_i ), // data output
+ .wbd_sel_i (wbd_sel_i ), // byte enable
+ .wbd_dat_o (wbd_dat_o ), // data input
+ .wbd_ack_o (wbd_ack_o ), // acknowlegement
+ .wbd_err_o (wbd_err_o ), // error
+
+ // Configuration
+ .cfg_fsm_reset (cfg_m0_fsm_reset ),
+ .cfg_mem_seq (cfg_m0_spi_seq ), // SPI MEM SEQUENCE
+ .cfg_addr_cnt (cfg_m0_addr_cnt ), // SPI Addr Count
+ .cfg_dummy_cnt (cfg_m0_dummy_cnt ), // SPI Dummy Count
+ .cfg_data_cnt (cfg_m0_data_cnt ), // SPI Read Count
+ .cfg_cmd_reg (cfg_m0_cmd_reg ), // SPI MEM COMMAND
+ .cfg_mode_reg (cfg_m0_mode_reg ), // SPI MODE REG
+
+ .spi_init_done (spi_init_done ), // SPI internal Init completed
+
+ // Towards Reg I/F
+ .spim_reg_req (spim_reg_req ), // Reg Request
+ .spim_reg_addr (spim_reg_addr ), // Reg Address
+ .spim_reg_we (spim_reg_we ), // Reg Write/Read Command
+ .spim_reg_be (spim_reg_be ), // Reg Byte Enable
+ .spim_reg_wdata (spim_reg_wdata ), // Reg Write Data
+ .spim_reg_ack (spim_reg_ack ), // Read Ack
+ .spim_reg_rdata (spim_reg_rdata ), // Read Read Data
+
+ // Towards Command FIFO
+ .cmd_fifo_empty (m0_cmd_fifo_empty ), // Command FIFO empty
+ .cmd_fifo_wr (m0_cmd_fifo_wr ), // Command FIFO Write
+ .cmd_fifo_wdata (m0_cmd_fifo_wdata ), // Command FIFO WData
+
+ // Towards Response FIFO
+ .res_fifo_empty (m0_res_fifo_empty ), // Response FIFO Empty
+ .res_fifo_rd (m0_res_fifo_rd ), // Response FIFO Read
+ .res_fifo_rdata (m0_res_fifo_rdata ), // Response FIFO Data
+
+ .state (m0_state )
+
+ );
+
+
+qspim_regs
+ #(
+ .WB_WIDTH(WB_WIDTH)
+ )
+ u_spim_regs
+ (
+ .mclk (mclk ),
+ .rst_n (rst_n ),
+ .fast_sim_mode (1'b0 ),
+
+ .spi_clk_div (spi_clk_div ),
+ .spi_init_done (spi_init_done ),
+
+ .spi_debug (spi_debug ),
+
+ .cfg_m0_fsm_reset (cfg_m0_fsm_reset ),
+ .cfg_m0_cs_reg (cfg_m0_cs_reg ), // Chip select
+ .cfg_m0_spi_mode (cfg_m0_spi_mode ), // Final SPI Mode
+ .cfg_m0_spi_switch (cfg_m0_spi_switch ), // SPI Mode Switching Place
+ .cfg_m0_spi_seq (cfg_m0_spi_seq ), // SPI SEQUENCE
+ .cfg_m0_addr_cnt (cfg_m0_addr_cnt ), // SPI Addr Count
+ .cfg_m0_dummy_cnt (cfg_m0_dummy_cnt ), // SPI Dummy Count
+ .cfg_m0_data_cnt (cfg_m0_data_cnt ), // SPI Read Count
+ .cfg_m0_cmd_reg (cfg_m0_cmd_reg ), // SPI MEM COMMAND
+ .cfg_m0_mode_reg (cfg_m0_mode_reg ), // SPI MODE REG
+
+ .cfg_m1_cs_reg (cfg_m1_cs_reg ), // Chip select
+ .cfg_m1_spi_mode (cfg_m1_spi_mode ), // Final SPI Mode
+ .cfg_m1_spi_switch (cfg_m1_spi_switch ), // SPI Mode Switching Place
+
+ .cfg_cs_early (cfg_cs_early ),
+ .cfg_cs_late (cfg_cs_late ),
+
+ // Towards Reg I/F
+ .spim_reg_req (spim_reg_req ), // Reg Request
+ .spim_reg_addr (spim_reg_addr ), // Reg Address
+ .spim_reg_we (spim_reg_we ), // Reg Write/Read Command
+ .spim_reg_be (spim_reg_be ), // Reg Byte Enable
+ .spim_reg_wdata (spim_reg_wdata ), // Reg Write Data
+ .spim_reg_ack (spim_reg_ack ), // Read Ack
+ .spim_reg_rdata (spim_reg_rdata ), // Read Read Data
+
+ // Towards Command FIFO
+ .cmd_fifo_full (m1_cmd_fifo_full ), // Command FIFO empty
+ .cmd_fifo_empty (m1_cmd_fifo_empty ), // Command FIFO empty
+ .cmd_fifo_wr (m1_cmd_fifo_wr ), // Command FIFO Write
+ .cmd_fifo_wdata (m1_cmd_fifo_wdata ), // Command FIFO WData
+
+ // Towards Response FIFO
+ .res_fifo_full (m1_res_fifo_full ), // Response FIFO Empty
+ .res_fifo_empty (m1_res_fifo_empty ), // Response FIFO Empty
+ .res_fifo_rd (m1_res_fifo_rd ), // Response FIFO Read
+ .res_fifo_rdata (m1_res_fifo_rdata ), // Response FIFO Data
+
+ .state (m1_state )
+
+ );
+
+ // Master 0 Command FIFO
+qspim_fifo #(.W(34), .DP(2)) u_m0_cmd_fifo (
+ .clk (mclk ),
+ .reset_n (rst_n ),
+ .flush (1'b0 ),
+ .wr_en (m0_cmd_fifo_wr ),
+ .wr_data (m0_cmd_fifo_wdata ),
+ .full (m0_cmd_fifo_full ),
+ .afull ( ),
+ .rd_en (m0_cmd_fifo_rd ),
+ .empty (m0_cmd_fifo_empty ),
+ .aempty ( ),
+ .rd_data (m0_cmd_fifo_rdata )
+ );
+
+ // Master 0 Response FIFO
+qspim_fifo #(.W(32), .DP(8)) u_m0_res_fifo (
+ .clk (mclk ),
+ .reset_n (rst_n ),
+ .flush (m0_res_fifo_flush ),
+ .wr_en (m0_res_fifo_wr ),
+ .wr_data (m0_res_fifo_wdata ),
+ .full (m0_res_fifo_full ),
+ .afull ( ),
+ .rd_en (m0_res_fifo_rd ),
+ .empty (m0_res_fifo_empty ),
+ .aempty ( ),
+ .rd_data (m0_res_fifo_rdata )
+ );
+
+ // Master 1 Command FIFO
+qspim_fifo #(.W(34), .DP(4)) u_m1_cmd_fifo (
+ .clk (mclk ),
+ .reset_n (rst_n ),
+ .flush (1'b0 ),
+ .wr_en (m1_cmd_fifo_wr ),
+ .wr_data (m1_cmd_fifo_wdata ),
+ .full (m1_cmd_fifo_full ),
+ .afull ( ),
+ .rd_en (m1_cmd_fifo_rd ),
+ .empty (m1_cmd_fifo_empty ),
+ .aempty ( ),
+ .rd_data (m1_cmd_fifo_rdata )
+ );
+ // Master 1 Response FIFO
+qspim_fifo #(.W(32), .DP(8)) u_m1_res_fifo (
+ .clk (mclk ),
+ .reset_n (rst_n ),
+ .flush (m1_res_fifo_flush ),
+ .wr_en (m1_res_fifo_wr ),
+ .wr_data (m1_res_fifo_wdata ),
+ .full (m1_res_fifo_full ),
+ .afull ( ),
+ .rd_en (m1_res_fifo_rd ),
+ .empty (m1_res_fifo_empty ),
+ .aempty ( ),
+ .rd_data (m1_res_fifo_rdata )
+ );
+
+
+qspim_ctrl u_spictrl
+ (
+ .clk (mclk ),
+ .rstn (rst_n ),
+
+ .spi_clk_div (spi_clk_div ),
+ .spi_status (spi_ctrl_status ),
+
+ .cfg_m0_cs_reg (cfg_m0_cs_reg ), // Chip select
+ .cfg_m0_spi_mode (cfg_m0_spi_mode ), // Final SPI Mode
+ .cfg_m0_spi_switch (cfg_m0_spi_switch ), // SPI Mode Switching Place
+
+ .cfg_m1_cs_reg (cfg_m1_cs_reg ), // Chip select
+ .cfg_m1_spi_mode (cfg_m1_spi_mode ), // Final SPI Mode
+ .cfg_m1_spi_switch (cfg_m1_spi_switch ), // SPI Mode Switching Place
+
+ .cfg_cs_early (cfg_cs_early ),
+ .cfg_cs_late (cfg_cs_late ),
+
+ .m0_cmd_fifo_empty (m0_cmd_fifo_empty ),
+ .m0_cmd_fifo_rd (m0_cmd_fifo_rd ),
+ .m0_cmd_fifo_rdata (m0_cmd_fifo_rdata ),
+
+ .m0_res_fifo_flush (m0_res_fifo_flush ),
+ .m0_res_fifo_empty (m0_res_fifo_empty ),
+ .m0_res_fifo_full (m0_res_fifo_full ),
+ .m0_res_fifo_wr (m0_res_fifo_wr ),
+ .m0_res_fifo_wdata (m0_res_fifo_wdata ),
+
+ .m1_cmd_fifo_empty (m1_cmd_fifo_empty ),
+ .m1_cmd_fifo_rd (m1_cmd_fifo_rd ),
+ .m1_cmd_fifo_rdata (m1_cmd_fifo_rdata ),
+
+ .m1_res_fifo_flush (m1_res_fifo_flush ),
+ .m1_res_fifo_empty (m1_res_fifo_empty ),
+ .m1_res_fifo_full (m1_res_fifo_full ),
+ .m1_res_fifo_wr (m1_res_fifo_wr ),
+ .m1_res_fifo_wdata (m1_res_fifo_wdata ),
+
+ .ctrl_state (ctrl_state ),
+
+ .spi_clk (spi_clk ),
+ .spi_csn0 (spi_csn0 ),
+ .spi_csn1 (spi_csn1 ),
+ .spi_csn2 (spi_csn2 ),
+ .spi_csn3 (spi_csn3 ),
+ .spi_mode (spi_mode ),
+ .spi_sdo0 (spi_sdo_int[0] ),
+ .spi_sdo1 (spi_sdo_int[1] ),
+ .spi_sdo2 (spi_sdo_int[2] ),
+ .spi_sdo3 (spi_sdo_int[3] ),
+ .spi_sdi0 (spi_sdi[0] ),
+ .spi_sdi1 (spi_sdi[1] ),
+ .spi_sdi2 (spi_sdi[2] ),
+ .spi_sdi3 (spi_sdi[3] ),
+ .spi_en_tx_out (spi_en_tx )
+ );
+
+endmodule
diff --git a/verilog/rtl/qspim/src/qspim_tx.sv b/verilog/rtl/qspim/src/qspim_tx.sv
index e69de29..d80737c 100644
--- a/verilog/rtl/qspim/src/qspim_tx.sv
+++ b/verilog/rtl/qspim/src/qspim_tx.sv
@@ -0,0 +1,249 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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 TX Module ////
+//// ////
+//// This file is part of the YIFive cores project ////
+//// https://github.com/dineshannayya/yifive_r0.git ////
+//// http://www.opencores.org/cores/yifive/ ////
+//// ////
+//// Description ////
+//// This is SPI Master Transmit Word control logic. ////
+//// This logic transmit data upto 32 bit in bit or Quad spi ////
+//// mode ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision: ////
+//// 0.1 - 16th Feb 2021, Dinesh A ////
+//// Initial version ////
+//// 0.2 - 24th Mar 2021, Dinesh A ////
+//// 1. Comments are added ////
+//// 2. RTL clean-up done and the output are registred////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module qspim_tx
+(
+ // General Input
+ input logic clk, // SPI clock
+ input logic rstn, // Active low Reset
+ input logic flush, // init the state
+ input logic en, // Transmit Enable
+ input logic tx_edge, // Transmiting Edge
+ output logic tx_done, // Transmission completion
+ output logic sdo0, // SPI Dout0
+ output logic sdo1, // SPI Dout1
+ output logic sdo2, // SPI Dout2
+ output logic sdo3, // SPI Dout3
+ input logic [1:0] s_spi_mode, // SPI quad mode indication
+ input logic [15:0] counter_in, // Transmit counter
+ input logic counter_in_upd,
+ input logic [31:0] txdata, // 32 bit tranmsit data
+ input logic dummy_phase, // dummy data
+ input logic data_valid, // Input data valid
+ output logic data_ready, // Data in acepted, this for txfifo
+ output logic spi_dummy, // spi dummy phase
+ output logic clk_en_o // Enable Tx clock
+);
+
+//------------------------------------------------------
+// Parameter Decleration
+// -----------------------------------------------------
+ parameter P_SINGLE = 2'b00;
+ parameter P_DOUBLE = 2'b01;
+ parameter P_QUAD = 2'b10;
+ parameter P_QDDR = 2'b11;
+
+//------------------------------------------------------
+// Variable Decleration
+// -----------------------------------------------------
+ logic [31:0] data_int ; // Data Input
+ logic [31:0] data_int_next ; // Next Data Input
+ logic [15:0] counter ; // Tx Counter
+ logic [15:0] counter_next ; // tx next counter
+ logic [15:0] counter_trgt ; // counter exit counter
+ logic tx32b_done ; // 32 bit Transmit done
+ logic [1:0] spi_mode ;
+ logic [1:0] spi_mode_next;
+
+ logic data_ready_i; // Data in acepted, this for txfifo
+ logic next_data_ready_i;// Data in acepted, this for txfifo
+ enum logic [1:0] { IDLE, TRANSMIT,WAIT_FIFO_AVAIL } tx_CS, tx_NS;
+
+
+ // Indicate 32 bit data done, usefull for readining next 32b from txfifo
+ assign tx32b_done = (spi_mode == P_SINGLE && (counter[4:0] == 5'b11111)) ||
+ (spi_mode == P_DOUBLE && (counter[3:0] == 4'b1111)) ||
+ (spi_mode == P_QUAD && (counter[2:0] == 3'b111)) ||
+ (spi_mode == P_QDDR && (counter[2:0] == 3'b111));
+
+ assign tx_done = (counter == (counter_trgt-1)) && (tx_CS == TRANSMIT);
+
+ assign clk_en_o = (tx_NS == TRANSMIT);
+
+ always_comb
+ begin
+ tx_NS = tx_CS;
+ data_int_next = data_int;
+ data_ready_i = 1'b0;
+ next_data_ready_i = 1'b0;
+ counter_next = counter;
+ spi_mode_next = spi_mode;
+
+ case (tx_CS)
+ IDLE: begin
+ data_int_next = txdata;
+ counter_next = '0;
+
+ if (en && data_valid && tx_edge) begin
+ spi_mode_next = s_spi_mode;
+ data_ready_i = 1'b1;
+ tx_NS = TRANSMIT;
+ end
+ end
+
+ TRANSMIT: begin
+ if ((counter + 1) ==counter_trgt) begin
+ counter_next = 0;
+ // Check if there is next data
+ if (en && data_valid && tx_edge) begin
+ spi_mode_next = s_spi_mode;
+ data_int_next = txdata;
+ data_ready_i = 1'b1;
+ tx_NS = TRANSMIT;
+ end else begin
+ tx_NS = IDLE;
+ end
+ end else if (tx32b_done) begin
+ if (en && (spi_dummy || data_valid) && tx_edge) begin
+ spi_mode_next = s_spi_mode;
+ data_int_next = txdata;
+ next_data_ready_i = 1'b1;
+ counter_next = counter + 1;
+ tx_NS = TRANSMIT;
+ end else begin
+ tx_NS = WAIT_FIFO_AVAIL;
+ end
+ end else begin
+ counter_next = counter + 1;
+ data_int_next = (spi_mode == P_QDDR ) ? {data_int[27:0],4'b0000} :
+ (spi_mode == P_QUAD ) ? {data_int[27:0],4'b0000} :
+ (spi_mode == P_DOUBLE ) ? {data_int[29:0],2'b00} : {data_int[30:0],1'b0};
+ end
+ end
+ WAIT_FIFO_AVAIL: begin
+ if (en && data_valid && tx_edge) begin
+ spi_mode_next = s_spi_mode;
+ data_int_next = txdata;
+ data_ready_i = 1'b1;
+ tx_NS = TRANSMIT;
+ end
+ end
+ endcase
+ end
+
+ logic data_ready_f;
+
+ always_ff @(posedge clk, negedge rstn)
+ begin
+ if (~rstn)
+ begin
+ counter <= 0;
+ data_int <= 'h0;
+ tx_CS <= IDLE;
+ sdo0 <= '0;
+ sdo1 <= '0;
+ sdo2 <= '1;
+ sdo3 <= '1;
+ counter_trgt <= '0;
+ data_ready <= '0;
+ data_ready_f <= 0;
+ spi_dummy <= 0;
+ spi_mode <= P_SINGLE;
+ end
+ else if(flush && tx_edge) begin
+ counter <= 0;
+ data_int <= 'h0;
+ tx_CS <= IDLE;
+ sdo0 <= '0;
+ sdo1 <= '0;
+ sdo2 <= '1;
+ sdo3 <= '1;
+ counter_trgt <= '0;
+ data_ready <= '0;
+ data_ready_f <= 0;
+ spi_dummy <= dummy_phase;
+ spi_mode <= P_SINGLE;
+ end else begin
+ data_ready_f <= data_ready_i | next_data_ready_i;
+ data_ready <= data_ready_f && !(data_ready_i | next_data_ready_i); // Generate Pulse at falling edge
+ if(tx_edge || (spi_mode_next == P_QDDR)) begin
+ tx_CS <= tx_NS;
+ counter <= counter_next;
+ data_int <= data_int_next;
+ end
+ // Counter Exit condition, quad mode div-4 , else actual counter
+ if (en && data_ready_i && tx_edge) begin
+ spi_mode <= s_spi_mode;
+ spi_dummy <= dummy_phase;
+ counter_trgt <= (s_spi_mode == P_QDDR ) ? {2'b00,counter_in[15:2]} :
+ (s_spi_mode == P_QUAD ) ? {2'b00,counter_in[15:2]} :
+ (s_spi_mode == P_DOUBLE ) ? {1'b0, counter_in[15:1]} : counter_in;
+ end else if (en == 0) begin
+ spi_dummy <= '0;
+ end
+ if((tx_edge || (spi_mode_next == P_QDDR)) && tx_NS == TRANSMIT) begin
+ sdo0 <= ((spi_mode_next == P_QUAD) || (spi_mode_next == P_QDDR))? data_int_next[28] : (spi_mode_next == P_DOUBLE) ? data_int_next[30] : data_int_next[31];
+ sdo1 <= ((spi_mode_next == P_QUAD) || (spi_mode_next == P_QDDR))? data_int_next[29] : (spi_mode_next == P_DOUBLE) ? data_int_next[31] : 1'b0;
+ sdo2 <= ((spi_mode_next == P_QUAD) || (spi_mode_next == P_QDDR))? data_int_next[30] : 1'b1; // Protect
+ sdo3 <= ((spi_mode_next == P_QUAD) || (spi_mode_next == P_QDDR))? data_int_next[31] : 1'b1; // Hold need to '1'
+ end
+ end
+ end
+endmodule
diff --git a/verilog/rtl/uart_i2c_usb/src/uart_i2c_usb.sv b/verilog/rtl/uart_i2c_usb/src/uart_i2c_usb.sv
index a089bb0..f1e7af6 100644
--- a/verilog/rtl/uart_i2c_usb/src/uart_i2c_usb.sv
+++ b/verilog/rtl/uart_i2c_usb/src/uart_i2c_usb.sv
@@ -159,8 +159,8 @@
i2cm_top u_i2cm (
// wishbone signals
.wb_clk_i (app_clk ), // master clock input
- .sresetn (1'b1 ), // synchronous reset
- .aresetn (i2c_rstn ), // asynchronous reset
+ .sresetn (i2c_rstn ), // synchronous reset
+ .aresetn (1'b1 ), // asynchronous reset
.wb_adr_i (reg_addr[4:2] ), // lower address bits
.wb_dat_i (reg_wdata[7:0] ), // databus input
.wb_dat_o (reg_i2c_rdata ), // databus output