spi master added
diff --git a/openlane/spi_master/config.tcl b/openlane/spi_master/config.tcl
new file mode 100755
index 0000000..b69e7cf
--- /dev/null
+++ b/openlane/spi_master/config.tcl
@@ -0,0 +1,118 @@
+# Global
+# ------
+
+set script_dir [file dirname [file normalize [info script]]]
+# Name
+set ::env(DESIGN_NAME) spim_top
+
+# This is macro
+set ::env(DESIGN_IS_CORE) 0
+
+# Diode insertion
+	#  Spray
+set ::env(DIODE_INSERTION_STRATEGY) 0
+
+	# Smart-"ish"
+#set ::env(DIODE_INSERTION_STRATEGY) 3
+#set ::env(GLB_RT_MAX_DIODE_INS_ITERS) 10
+
+# Timing configuration
+set ::env(CLOCK_PERIOD) "10"
+set ::env(CLOCK_PORT) "mclk"
+
+
+# Sources
+# -------
+
+# Local sources + no2usb sources
+set ::env(VERILOG_FILES) "\
+        $script_dir/../../verilog/rtl/spi_master/src/spim_top.sv \
+        $script_dir/../../verilog/rtl/spi_master/src/spim_regs.sv \
+        $script_dir/../../verilog/rtl/spi_master/src/spim_clkgen.sv \
+        $script_dir/../../verilog/rtl/spi_master/src/spim_ctrl.sv \
+        $script_dir/../../verilog/rtl/spi_master/src/spim_rx.sv \
+        $script_dir/../../verilog/rtl/spi_master/src/spim_tx.sv "
+
+#set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/syntacore/scr1/src/includes ]
+
+#set ::env(SYNTH_DEFINES) [list SCR1_DBG_EN ]
+
+
+# Need blackbox for cells
+set ::env(SYNTH_READ_BLACKBOX_LIB) 0
+
+
+# Floorplanning
+# -------------
+
+# Fixed area and pin position
+set ::env(FP_SIZING) "absolute"
+#actual die area is 0 0 2920 3520, given 500 micron extra margin
+set ::env(DIE_AREA) [list 0.0 0.0 300.0 300.0]
+set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg
+
+# Halo around the Macros
+set ::env(FP_HORIZONTAL_HALO) 25
+set ::env(FP_VERTICAL_HALO) 20
+
+#set ::env(PDN_CFG) $::env(DESIGN_DIR)/pdn.tcl
+
+
+
+# Placement
+# ---------
+
+set ::env(PL_TARGET_DENSITY) 0.40
+
+#set ::env(MACRO_PLACEMENT_CFG) $::env(DESIGN_DIR)/macro_placement.cfg
+
+
+# Routing
+# -------
+
+#| `ROUTING_CORES` | Specifies the number of threads to be used in TritonRoute. <br> (Default: `4`) |
+set ::env(ROUTING_CORES) 4
+
+#| `GLB_RT_ALLOW_CONGESTION` | Allow congestion in the resultign guides. 0 = false, 1 = true <br> (Default: `0`) |
+set ::env(GLB_RT_ALLOW_CONGESTION) 0
+
+# | `GLB_RT_MINLAYER` | The number of lowest layer to be used in routing. <br> (Default: `1`)|
+set ::env(GLB_RT_MINLAYER) 1
+
+# | `GLB_RT_MAXLAYER` | The number of highest layer to be used in routing. <br> (Default: `6`)|
+set ::env(GLB_RT_MAXLAYER) 6
+
+# Obstructions
+    # li1 over the SRAM areas
+	# met5 over the whole design
+#set ::env(GLB_RT_OBS) "li1 0.00 22.68 1748.00 486.24, li1 0.00 851.08 1748.00 486.24, met5 0.0 0.0 1748.0 1360.0"
+
+#| `ROUTING_OPT_ITERS` | Specifies the maximum number of optimization iterations during Detailed Routing in TritonRoute. <br> (Default: `64`) |
+set ::env(ROUTING_OPT_ITERS) "64"
+
+#| `GLOBAL_ROUTER` | Specifies which global router to use. Values: `fastroute` or `cugr`. <br> (Default: `fastroute`) |
+set ::env(GLOBAL_ROUTER) "fastroute"
+
+#| `DETAILED_ROUTER` | Specifies which detailed router to use. Values: `tritonroute`, `tritonroute_or`, or `drcu`. <br> (Default: `tritonroute`) |
+set ::env(DETAILED_ROUTER) "tritonroute"
+
+# DRC
+# ---
+
+
+set ::env(MAGIC_DRC_USE_GDS) 1
+
+
+# Tape Out
+# --------
+
+set ::env(MAGIC_ZEROIZE_ORIGIN) 0
+
+
+# Cell library specific config
+# ----------------------------
+
+set filename $::env(DESIGN_DIR)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
+if { [file exists $filename] == 1} {
+	source $filename
+}
diff --git a/openlane/spi_master/pin_order.cfg b/openlane/spi_master/pin_order.cfg
new file mode 100644
index 0000000..9691d54
--- /dev/null
+++ b/openlane/spi_master/pin_order.cfg
@@ -0,0 +1,36 @@
+#BUS_SORT
+
+#E
+mclk
+rst_n
+events_o.*
+
+
+#N
+spi_mode.*
+spi_clk
+spi_csn0
+spi_csn1
+spi_csn2
+spi_csn3
+spi_en_tx
+spi_sdi0
+spi_sdi1
+spi_sdi2
+spi_sdi3
+spi_sdo0
+spi_sdo1
+spi_sdo2
+spi_sdo3
+
+
+#N
+wbd_ack_o
+wbd_err_o
+wbd_stb_i
+wbd_we_i
+wbd_adr_i.*
+wbd_dat_i.*
+wbd_dat_o.*
+wbd_sel_i.*
+
diff --git a/openlane/syntacore/config.tcl b/openlane/syntacore/config.tcl
index f1d6458..766f736 100755
--- a/openlane/syntacore/config.tcl
+++ b/openlane/syntacore/config.tcl
@@ -3,7 +3,7 @@
 
 set script_dir [file dirname [file normalize [info script]]]
 # Name
-set ::env(DESIGN_NAME) scr1_top_axi
+set ::env(DESIGN_NAME) scr1_top_wb
 
 # This is macro
 set ::env(DESIGN_IS_CORE) 0
@@ -26,34 +26,36 @@
 
 # Local sources + no2usb sources
 set ::env(VERILOG_FILES) "\
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_top.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_core_top.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_dm.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_tapc_synchronizer.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_clk_ctrl.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_scu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_tapc.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_tapc_shift_reg.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/scr1_dmi.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/primitives/scr1_reset_cells.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ifu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_idu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_exu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_mprf.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_csr.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ialu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_lsu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_hdu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_tdu.sv  \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_ipic.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_dmem_router.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_imem_router.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_tcm.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_timer.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_top_axi.sv   \
-	$script_dir/../../verilog/rtl/syntacore_scr1/src/top/scr1_mem_axi.sv "
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_top.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_core_top.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_dm.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_tapc_synchronizer.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_clk_ctrl.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_scu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_tapc.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_tapc_shift_reg.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/scr1_dmi.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/primitives/scr1_reset_cells.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_ifu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_idu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_exu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_mprf.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_csr.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_ialu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_lsu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_hdu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_pipe_tdu.sv  \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/core/pipeline/scr1_ipic.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_dmem_router.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_imem_router.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_tcm.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_timer.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_top_wb.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv   \
+	$script_dir/../../verilog/rtl/syntacore/scr1/src/top/scr1_imem_wb.sv   \
+	$script_dir/../../verilog/rtl/lib/sync_fifo.sv "
 
-set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/syntacore_scr1/src/includes ]
+set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/syntacore/scr1/src/includes ]
 
 #set ::env(SYNTH_DEFINES) [list SCR1_DBG_EN ]
 
diff --git a/verilog/rtl/lib/sync_fifo.sv b/verilog/rtl/lib/sync_fifo.sv
index 0eeb134..fb934a2 100644
--- a/verilog/rtl/lib/sync_fifo.sv
+++ b/verilog/rtl/lib/sync_fifo.sv
@@ -60,14 +60,13 @@
 );
 
 
-reg [DATA_WIDTH-1:0] ram [FIFO_DEPTH-1:0];
+reg [DATA_WIDTH-1:0]  ram [FIFO_DEPTH-1:0];
 reg [ADDR_WIDTH-1:0]  wptr; // write ptr
 reg [ADDR_WIDTH-1:0]  rptr; // write ptr
 reg [ADDR_WIDTH:0]    status_cnt; // status counter
+reg                   empty;
+reg                   full;
 
- //-----------Variable assignments---------------
- assign full  = (status_cnt == FIFO_DEPTH);
- assign empty = (status_cnt == 0);
  
  //-----------Code Start---------------------------
  always @ (negedge rstn or posedge clk)
@@ -101,7 +100,37 @@
   end
 end
 
+// underflow is not handled
+always @ (negedge rstn or posedge clk)
+begin : EMPTY_FLAG
+  if (rstn==1'b0) begin
+       empty <= 1;
+  // Read but no write.
+  end else if (rd_en &&   (!wr_en) && (status_cnt  == 1)) begin
+    empty <= 1;
+  // Write 
+  end else if (wr_en) begin
+    empty <= 0;
+  end else if (status_cnt  == 0) begin
+     empty <= 1;
+  end
+end
 
+// overflow is not handled
+always @ (negedge rstn or posedge clk)
+begin : FULL_FLAG
+  if (rstn==1'b0) begin
+       full <= 0;
+  // Write but no read.
+  end else if (wr_en &&  (!rd_en) && (status_cnt  == (FIFO_DEPTH-1))) begin
+    full <= 1;
+  // Read 
+  end else if (rd_en &&  (!wr_en) ) begin
+    full <= 0;
+  end else if (status_cnt  == FIFO_DEPTH) begin
+     full <= 1;
+  end
+end
 assign dout = ram[rptr];
 
 always @ (posedge clk)
diff --git a/verilog/rtl/spi_master/src/filelist.f b/verilog/rtl/spi_master/src/filelist.f
new file mode 100644
index 0000000..6b47b62
--- /dev/null
+++ b/verilog/rtl/spi_master/src/filelist.f
@@ -0,0 +1,6 @@
+spim_top.sv
+spim_regs.sv
+spim_clkgen.sv
+spim_ctrl.sv
+spim_rx.sv
+spim_tx.sv
diff --git a/verilog/rtl/spi_master/src/spim_clkgen.sv b/verilog/rtl/spi_master/src/spim_clkgen.sv
new file mode 100644
index 0000000..022b300
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_clkgen.sv
@@ -0,0 +1,116 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI Clkgen  Module                                          ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  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 spim_clkgen
+(
+    input  logic                        clk,
+    input  logic                        rstn,
+    input  logic                        en,
+    input  logic          [7:0]         cfg_sck_period,
+    output logic                        spi_clk,
+    output logic                        spi_fall,
+    output logic                        spi_rise
+);
+
+	logic [7:0] sck_half_period;
+	logic [7:0] clk_cnt;
+
+    assign sck_half_period = {1'b0, cfg_sck_period[7: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
+    	   clk_cnt    <= 'h1;
+    	   spi_clk    <= 1'b1;
+	   spi_fall   <= 1'b0;
+	   spi_rise   <= 1'b0;
+    	end // if (!reset_n)
+    	else 
+    	begin
+    	   if(en) 
+    	   begin
+    	      if(clk_cnt == sck_half_period) 
+    	      begin
+    		 spi_clk    <= 1'b0;
+	         spi_fall   <= 1'b1;
+	         spi_rise   <= 1'b0;
+    		 clk_cnt    <= clk_cnt + 1'b1;
+    	      end // if (clk_cnt == sck_half_period)
+    	      else begin
+    		 if(clk_cnt == cfg_sck_period) 
+    		 begin
+    		    spi_clk    <= 1'b1;
+	            spi_fall   <= 1'b0;
+	            spi_rise   <= 1'b1;
+    		    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 // if (en)
+    	   else begin
+    	      clk_cnt    <= 'h1;
+	      spi_fall   <= 1'b0; 
+	      spi_rise   <= 1'b0;
+    	   end // else: !if(en)
+    	end // else: !if(!reset_n)
+    end // always @ (posedge clk or negedge reset_n)
+
+endmodule
diff --git a/verilog/rtl/spi_master/src/spim_ctrl.sv b/verilog/rtl/spi_master/src/spim_ctrl.sv
new file mode 100644
index 0000000..20d2515
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_ctrl.sv
@@ -0,0 +1,684 @@
+
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI CTRL I/F Module                                         ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  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 spim_ctrl
+(
+    input  logic                          clk,
+    input  logic                          rstn,
+    output logic                          eot,
+
+    input  logic                    [7:0] spi_clk_div,
+    input  logic                          spi_clk_div_valid,
+    output logic                    [7:0] spi_status,
+
+
+    input  logic                          spi_req,
+    input  logic                   [31:0] spi_addr,
+    input  logic                    [5:0] spi_addr_len,
+    input  logic                   [7:0]  spi_cmd,
+    input  logic                    [5:0] spi_cmd_len,
+    input  logic                   [7:0]  spi_mode_cmd,
+    input  logic                          spi_mode_cmd_enb,
+    input  logic                    [3:0] spi_csreg,
+    input  logic                   [15:0] spi_data_len,
+    input  logic                   [15:0] spi_dummy_rd_len,
+    input  logic                   [15:0] spi_dummy_wr_len,
+    input  logic                          spi_swrst, //FIXME Not used at all
+    input  logic                          spi_rd,
+    input  logic                          spi_wr,
+    input  logic                          spi_qrd,
+    input  logic                          spi_qwr,
+    input  logic                   [31:0] spi_wdata,
+    output logic                   [31:0] spi_rdata,
+    output logic                          spi_ack,
+
+    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 // Spi Direction control
+);
+
+
+parameter  SPI_STD     = 2'b00;
+parameter  SPI_QUAD_TX = 2'b01;
+parameter  SPI_QUAD_RX = 2'b10;
+
+  logic spi_rise;
+  logic spi_fall;
+
+  logic spi_clock_en;
+
+  logic spi_en_rx;
+
+  logic [15:0] counter_tx;
+  logic        counter_tx_valid;
+  logic [15:0] counter_rx;
+  logic        counter_rx_valid;
+
+  logic [31:0] data_to_tx;
+  logic        data_to_tx_valid;
+  logic        data_to_tx_ready;
+
+  logic en_quad;
+  logic en_quad_int;
+  logic do_tx; //FIXME NOT USED at all!!
+  logic do_rx;
+
+  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 en_quad_in;
+  
+
+  enum logic [2:0] {DATA_NULL,DATA_EMPTY,DATA_CMD,DATA_ADDR,DATA_MODE,DATA_FIFO} ctrl_data_mux;
+
+  enum logic [4:0] {IDLE,CMD,ADDR,MODE,DUMMY,DATA_TX,DATA_RX,WAIT_EDGE} state,state_next;
+
+  assign en_quad = spi_qrd | spi_qwr | en_quad_int;
+  
+  
+  assign en_quad_in = (s_spi_mode == SPI_STD) ? 1'b0 : 1'b1;
+
+  spim_clkgen u_clkgen
+  (
+    .clk           ( clk               ),
+    .rstn          ( rstn              ),
+    .en            ( spi_clock_en      ),
+    .cfg_sck_period( spi_clk_div       ),
+    .spi_clk       ( spi_clk           ),
+    .spi_fall      ( spi_fall          ),
+    .spi_rise      ( spi_rise          )
+  );
+
+  spim_tx u_txreg
+  (
+    .clk            ( clk              ),
+    .rstn           ( rstn             ),
+    .en             ( spi_en_tx        ),
+    .tx_edge        ( spi_fall         ),
+    .tx_done        ( tx_done          ),
+    .sdo0           ( spi_sdo0         ),
+    .sdo1           ( spi_sdo1         ),
+    .sdo2           ( spi_sdo2         ),
+    .sdo3           ( spi_sdo3         ),
+    .en_quad_in     ( en_quad_in       ),
+    .counter_in     ( counter_tx       ),
+    .txdata         ( data_to_tx       ),
+    .data_valid     ( data_to_tx_valid ),
+    .data_ready     (                  ),
+    .clk_en_o       ( tx_clk_en        )
+  );
+
+  spim_rx u_rxreg
+  (
+    .clk            ( clk                    ),
+    .rstn           ( rstn                   ),
+    .en             ( spi_en_rx              ),
+    .rx_edge        ( spi_rise               ),
+    .rx_done        ( rx_done                ),
+    .sdi0           ( spi_sdi0               ),
+    .sdi1           ( spi_sdi1               ),
+    .sdi2           ( spi_sdi2               ),
+    .sdi3           ( spi_sdi3               ),
+    .en_quad_in     ( en_quad_in             ),
+    .counter_in     ( counter_rx             ),
+    .counter_in_upd ( counter_rx_valid       ),
+    .data           ( spi_rdata              ),
+    .data_valid     (                        ),
+    .data_ready     ( 1'b1                   ),
+    .clk_en_o       ( rx_clk_en              )
+  );
+
+
+  
+  always_comb
+  begin
+      data_to_tx       =  'h0;
+      data_to_tx_valid = 1'b0;
+
+      case(ctrl_data_mux)
+          DATA_NULL:
+          begin
+              data_to_tx       =  '0;
+              data_to_tx_valid = 1'b0;
+          end
+
+          DATA_EMPTY:
+          begin
+              data_to_tx       =  '0;
+              data_to_tx_valid = 1'b1;
+          end
+
+          DATA_CMD:
+          begin
+              data_to_tx       = {spi_cmd,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       = spi_addr;
+              data_to_tx_valid = ctrl_data_valid;
+          end
+
+          DATA_FIFO:
+          begin
+             data_to_tx             = spi_wdata;
+             data_to_tx_valid       = ctrl_data_valid;
+          end
+      endcase
+  end
+
+  always_comb
+  begin
+    spi_cs           = 1'b1;
+    spi_clock_en     = 1'b0;
+    counter_tx       =  '0;
+    counter_tx_valid = 1'b0;
+    counter_rx       =  '0;
+    counter_rx_valid = 1'b0;
+    state_next       = state;
+    ctrl_data_mux    = DATA_NULL;
+    ctrl_data_valid  = 1'b0;
+    spi_en_rx        = 1'b0;
+    spi_en_tx        = 1'b0;
+    spi_status       =  '0;
+    s_spi_mode       = SPI_QUAD_RX;
+    eot              = 1'b0;
+    case(state)
+      IDLE:
+      begin
+        spi_status[0] = 1'b1;
+        s_spi_mode = SPI_QUAD_RX;
+        if (spi_req)
+        begin
+          spi_cs       = 1'b0;
+          spi_clock_en = 1'b1;
+
+          if (spi_cmd_len != 0)
+          begin
+//            s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD;
+            s_spi_mode       = SPI_STD; // COMMAND is always Standard Mode ?
+            counter_tx       = {8'h0,spi_cmd_len};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_CMD;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = CMD;
+          end
+          else if (spi_addr_len != 0)
+          begin
+            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
+            counter_tx       = {8'h0,spi_addr_len};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_ADDR;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = ADDR;
+          end
+          else if (spi_mode_cmd_enb != 0)
+          begin
+            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
+            counter_tx       = {8'h0,8'h8};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_MODE;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = MODE;
+          end
+          else if (spi_data_len != 0)
+          begin
+             if (spi_rd || spi_qrd)
+             begin
+                s_spi_mode = (spi_qrd) ? SPI_QUAD_RX : SPI_STD;
+                if(spi_dummy_rd_len != 0)
+                begin
+                  counter_tx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
+                  counter_tx_valid = 1'b1;
+                  spi_en_tx        = 1'b1;
+                  ctrl_data_mux    = DATA_EMPTY;
+                  state_next       = DUMMY;
+                end
+                else
+                begin
+                   counter_rx       = spi_data_len;
+                   counter_rx_valid = 1'b1;
+                   spi_en_rx        = 1'b1;
+                   state_next       = DATA_RX;
+                end
+             end
+             else
+             begin
+                s_spi_mode = (spi_qwr) ? SPI_QUAD_TX : SPI_STD;
+                if(spi_dummy_wr_len != 0)
+                begin
+                   counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
+                   counter_tx_valid = 1'b1;
+                   ctrl_data_mux    = DATA_EMPTY;
+                   spi_en_tx        = 1'b1;
+                   state_next       = DUMMY;
+                end
+                else
+                begin
+                   counter_tx       = spi_data_len;
+                   counter_tx_valid = 1'b1;
+                   ctrl_data_mux    = DATA_FIFO;
+                   ctrl_data_valid  = 1'b0;
+                   spi_en_tx        = 1'b1;
+                   state_next       = DATA_TX;
+                end
+             end
+          end
+        end
+        else
+        begin
+          spi_cs = 1'b1;
+          state_next = IDLE;
+        end
+      end
+
+      CMD:
+      begin
+        spi_status[1] = 1'b1;
+        spi_cs = 1'b0;
+        spi_clock_en = 1'b1;
+//      s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+        s_spi_mode = SPI_STD; // Command is always Standard Mode ?
+        if (tx_done)
+        begin
+          if (spi_addr_len != 0)
+          begin
+            s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+            counter_tx       = {8'h0,spi_addr_len};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_ADDR;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = ADDR;
+          end
+          else if (spi_mode_cmd_enb != 0)
+          begin
+            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
+            counter_tx       = {8'h0,8'h8};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_MODE;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = MODE;
+          end
+          else if (spi_data_len != 0)
+          begin
+            if (do_rx)
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+              if(spi_dummy_rd_len != 0)
+              begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
+                counter_tx_valid = 1'b1;
+                spi_en_tx        = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                state_next       = DUMMY;
+              end
+              else
+              begin
+                counter_rx       = spi_data_len;
+                counter_rx_valid = 1'b1;
+                spi_en_rx        = 1'b1;
+                state_next       = DATA_RX;
+              end
+            end
+            else
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+              if(spi_dummy_wr_len != 0)
+              begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                spi_en_tx        = 1'b1;
+                state_next       = DUMMY;
+              end
+              else
+              begin
+                counter_tx       = spi_data_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_FIFO;
+                ctrl_data_valid  = 1'b1;
+                spi_en_tx        = 1'b1;
+                state_next       = DATA_TX;
+              end
+            end
+          end
+          else
+          begin
+            spi_en_tx  = 1'b1;
+            state_next = WAIT_EDGE;
+          end
+        end
+        else
+        begin
+          spi_en_tx  = 1'b1;
+          state_next = CMD;
+        end
+      end
+
+      ADDR:
+      begin
+        spi_en_tx     = 1'b1;
+        spi_status[2] = 1'b1;
+        spi_cs        = 1'b0;
+        spi_clock_en  = 1'b1;
+        s_spi_mode    = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+
+        if (tx_done)
+        begin
+          if (spi_mode_cmd_enb != 0)
+          begin
+            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
+            counter_tx       = {8'h0,8'h8};
+            counter_tx_valid = 1'b1;
+            ctrl_data_mux    = DATA_MODE;
+            ctrl_data_valid  = 1'b1;
+            spi_en_tx        = 1'b1;
+            state_next       = MODE;
+          end
+          else if (spi_data_len != 0)
+          begin
+            if (do_rx)
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+              if(spi_dummy_rd_len != 0)
+              begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
+                counter_tx_valid = 1'b1;
+                spi_en_tx        = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                state_next       = DUMMY;
+              end
+              else
+              begin
+                counter_rx       = spi_data_len;
+                counter_rx_valid = 1'b1;
+                spi_en_rx        = 1'b1;
+                state_next       = DATA_RX;
+              end
+            end
+            else
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+              spi_en_tx  = 1'b1;
+
+              if(spi_dummy_wr_len != 0) begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                state_next       = DUMMY;
+              end else begin
+                counter_tx       = spi_data_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_FIFO;
+                ctrl_data_valid  = 1'b1;
+                state_next       = DATA_TX;
+              end
+            end
+          end
+          else
+          begin
+            state_next = WAIT_EDGE;
+          end
+        end
+      end
+
+      MODE:
+      begin
+        spi_en_tx     = 1'b1;
+        spi_status[3] = 1'b1;
+        spi_cs        = 1'b0;
+        spi_clock_en  = 1'b1;
+        s_spi_mode    = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+        if (tx_done)
+        begin
+          if (spi_data_len != 0)
+          begin
+            if (do_rx)
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+              if(spi_dummy_rd_len != 0)
+              begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
+                counter_tx_valid = 1'b1;
+                spi_en_tx        = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                state_next       = DUMMY;
+              end
+              else
+              begin
+                counter_rx       = spi_data_len;
+                counter_rx_valid = 1'b1;
+                spi_en_rx        = 1'b1;
+                state_next       = DATA_RX;
+              end
+            end
+            else
+            begin
+              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+              spi_en_tx  = 1'b1;
+
+              if(spi_dummy_wr_len != 0) begin
+                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_EMPTY;
+                state_next       = DUMMY;
+              end else begin
+                counter_tx       = spi_data_len;
+                counter_tx_valid = 1'b1;
+                ctrl_data_mux    = DATA_FIFO;
+                ctrl_data_valid  = 1'b1;
+                state_next       = DATA_TX;
+              end
+            end
+          end
+          else
+          begin
+            state_next = WAIT_EDGE;
+          end
+        end
+      end
+
+      DUMMY:
+      begin
+        spi_en_tx     = 1'b1;
+        spi_status[4] = 1'b1;
+        spi_cs        = 1'b0;
+        spi_clock_en  = 1'b1;
+        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+
+        if (tx_done) begin
+          if (spi_data_len != 0) begin
+            if (do_rx) begin
+              counter_rx       = spi_data_len;
+              counter_rx_valid = 1'b1;
+              spi_en_rx        = 1'b1;
+              state_next       = DATA_RX;
+            end else begin
+              counter_tx       = spi_data_len;
+              counter_tx_valid = 1'b1;
+              s_spi_mode       = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+
+              spi_clock_en     = tx_clk_en;
+              spi_en_tx        = 1'b1;
+              state_next       = DATA_TX;
+            end
+          end
+          else
+          begin
+            eot        = 1'b1;
+            state_next = WAIT_EDGE;
+          end
+        end
+        else
+        begin
+          ctrl_data_mux = DATA_EMPTY;
+          spi_en_tx     = 1'b1;
+          state_next    = DUMMY;
+        end
+      end
+
+      DATA_TX:
+      begin
+        spi_status[5]    = 1'b1;
+        spi_cs           = 1'b0;
+        spi_clock_en     = tx_clk_en;
+        ctrl_data_mux    = DATA_FIFO;
+        ctrl_data_valid  = 1'b1;
+        spi_en_tx        = 1'b1;
+        s_spi_mode       = (en_quad) ? SPI_QUAD_TX : SPI_STD;
+
+        if (tx_done) begin
+          eot          = 1'b1;
+          state_next   = WAIT_EDGE;
+          spi_clock_en = 1'b0;
+        end else begin
+          state_next = DATA_TX;
+        end
+      end
+
+      DATA_RX:
+      begin
+        spi_status[6] = 1'b1;
+        spi_cs        = 1'b0;
+        spi_clock_en  = rx_clk_en;
+        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+
+        if (rx_done) begin
+          state_next = WAIT_EDGE;
+        end else begin
+          spi_en_rx  = 1'b1;
+          state_next = DATA_RX;
+        end
+      end
+      WAIT_EDGE:
+      begin
+        spi_status[7] = 1'b1;
+        spi_cs        = 1'b0;
+        spi_clock_en  = 1'b0;
+        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
+        eot           = 1'b1;
+        state_next    = IDLE;
+      end
+    endcase
+  end
+
+assign  spi_ack = ((spi_req ==1) && (state_next == WAIT_EDGE)) ? 1'b1 : 1'b0;
+
+
+  always_ff @(posedge clk, negedge rstn)
+  begin
+    if (rstn == 1'b0)
+    begin
+      state       <= IDLE;
+      en_quad_int <= 1'b0;
+      do_rx       <= 1'b0;
+      do_tx       <= 1'b0;
+      spi_mode    <= SPI_QUAD_RX;
+    end
+    else
+    begin
+       state <= state_next;
+       spi_mode <= s_spi_mode;
+      if (spi_qrd || spi_qwr)
+        en_quad_int <= 1'b1;
+      else if (state_next == IDLE)
+        en_quad_int <= 1'b0;
+
+      if (spi_rd || spi_qrd)
+      begin
+        do_rx <= 1'b1;
+        do_tx <= 1'b0;
+      end
+      else if (spi_wr || spi_qwr)
+      begin
+        do_rx <= 1'b0;
+        do_tx <= 1'b1;
+      end
+      else if (state_next == IDLE)
+      begin
+        do_rx <= 1'b0;
+        do_tx <= 1'b0;
+      end
+    end
+  end
+
+  assign spi_csn0 = ~spi_csreg[0] | spi_cs;
+  assign spi_csn1 = ~spi_csreg[1] | spi_cs;
+  assign spi_csn2 = ~spi_csreg[2] | spi_cs;
+  assign spi_csn3 = ~spi_csreg[3] | spi_cs;
+
+endmodule
+
diff --git a/verilog/rtl/spi_master/src/spim_fifo.sv b/verilog/rtl/spi_master/src/spim_fifo.sv
new file mode 100644
index 0000000..e1c665b
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_fifo.sv
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  YiFive cores common library Module                          ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  http://www.opencores.org/cores/yifive/                      ////
+////                                                              ////
+////  Description                                                 ////
+////     Sync Fifo with full and empty                            ////
+////                                                              ////
+////  To Do:                                                      ////
+////    nothing                                                   ////
+////                                                              ////
+////  Author(s):                                                  ////
+////      - Dinesh Annayya, dinesha@opencores.org                 ////
+////                                                              ////
+////  Revision : June 7, 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 spim_fifo #(
+      parameter  DATA_WIDTH  = 32, // Data Width
+      parameter  ADDR_WIDTH   = 1, // Address Width
+      parameter  FIFO_DEPTH   = 2  // FIFO DEPTH
+	
+)(
+       input                   rstn,
+       input                   srst,
+       input                   clk,
+       input                   wr_en, // Write
+       input [DATA_WIDTH-1:0]  din,
+       output                  ready_o,
+
+       input                   rd_en, // Read
+       output [DATA_WIDTH-1:0] dout,
+       output                  valid_o
+);
+
+
+reg [DATA_WIDTH-1:0]  ram [FIFO_DEPTH-1:0];
+reg [ADDR_WIDTH-1:0]  wptr; // write ptr
+reg [ADDR_WIDTH-1:0]  rptr; // write ptr
+reg [ADDR_WIDTH:0]    status_cnt; // status counter
+reg                   empty;
+reg                   full;
+
+ wire ready_o = ! full;
+ wire valid_o = ! empty;
+
+ //-----------Code Start---------------------------
+ always @ (negedge rstn or posedge clk)
+ begin : WRITE_POINTER
+   if (rstn==1'b0) begin
+     wptr <= 0;
+   end else if (srst ) begin
+     wptr <= 0;
+   end else if (wr_en ) begin
+     wptr <= wptr + 1;
+   end
+ end
+
+always @ (negedge rstn or posedge clk)
+begin : READ_POINTER
+  if (rstn==1'b0) begin
+    rptr <= 0;
+   end else if (srst ) begin
+     rptr <= 0;
+  end else if (rd_en) begin
+    rptr <= rptr + 1;
+  end
+end
+
+always @ (negedge rstn or posedge clk)
+begin : STATUS_COUNTER
+  if (rstn==1'b0) begin
+       status_cnt <= 0;
+  end else if (srst ) begin
+       status_cnt <= 0;
+  // Read but no write.
+  end else if (rd_en &&   (!wr_en) && (status_cnt  != 0)) begin
+    status_cnt <= status_cnt - 1;
+  // Write but no read.
+  end else if (wr_en &&  (!rd_en) && (status_cnt  != FIFO_DEPTH)) begin
+    status_cnt <= status_cnt + 1;
+  end
+end
+
+// underflow is not handled
+always @ (negedge rstn or posedge clk)
+begin : EMPTY_FLAG
+  if (rstn==1'b0) begin
+       empty <= 1;
+  end else if (srst ) begin
+       empty <= 1;
+  // Read but no write.
+  end else if (rd_en &&   (!wr_en) && (status_cnt  == 1)) begin
+    empty <= 1;
+  // Write 
+  end else if (wr_en) begin
+    empty <= 0;
+  end else if (status_cnt  == 0) begin
+     empty <= 1;
+  end
+end
+
+// overflow is not handled
+always @ (negedge rstn or posedge clk)
+begin : FULL_FLAG
+  if (rstn==1'b0) begin
+       full <= 0;
+  end else if (srst ) begin
+       full <= 0;
+  // Write but no read.
+  end else if (wr_en &&  (!rd_en) && (status_cnt  == (FIFO_DEPTH-1))) begin
+    full <= 1;
+  // Read 
+  end else if (rd_en &&  (!wr_en) ) begin
+    full <= 0;
+  end else if (status_cnt  == FIFO_DEPTH) begin
+     full <= 1;
+  end
+end
+assign dout = ram[rptr];
+
+always @ (posedge clk)
+begin
+  if (wr_en) ram[wptr] <= din;
+end
+
+
+endmodule
diff --git a/verilog/rtl/spi_master/src/spim_regs.sv b/verilog/rtl/spi_master/src/spim_regs.sv
new file mode 100644
index 0000000..7d06f3e
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_regs.sv
@@ -0,0 +1,410 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI WishBone Register I/F Module                            ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  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 spim_regs #( 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                   [7:0] spi_clk_div,
+    output logic                         spi_clk_div_valid,
+    input logic                    [7:0] spi_status,
+
+    // Towards SPI TX/RX FSM
+
+
+    output logic                          spi_req,
+    output logic                   [31:0] spi_addr,
+    output logic                    [5:0] spi_addr_len,
+    output logic                   [7:0]  spi_cmd,
+    output logic                    [5:0] spi_cmd_len,
+    output logic                   [7:0]  spi_mode_cmd,
+    output logic                          spi_mode_cmd_enb,
+    output logic                    [3:0] spi_csreg,
+    output logic                   [15:0] spi_data_len,
+    output logic                   [15:0] spi_dummy_rd_len,
+    output logic                   [15:0] spi_dummy_wr_len,
+    output logic                          spi_swrst,
+    output logic                          spi_rd,
+    output logic                          spi_wr,
+    output logic                          spi_qrd,
+    output logic                          spi_qwr,
+    output logic                   [31:0] spi_wdata,
+    input logic                   [31:0]  spi_rdata,
+    input logic                           spi_ack
+
+    );
+
+//----------------------------
+// Register Decoding
+// ---------------------------
+parameter REG_CTRL     = 4'b0000;
+parameter REG_CLKDIV   = 4'b0001;
+parameter REG_SPICMD   = 4'b0010;
+parameter REG_SPIADR   = 4'b0011;
+parameter REG_SPILEN   = 4'b0100;
+parameter REG_SPIDUM   = 4'b0101;
+parameter REG_SPIWDATA = 4'b0110;
+parameter REG_SPIRDATA = 4'b0111;
+parameter REG_STATUS   = 4'b1000;
+
+// Init FSM
+parameter SPI_INIT_IDLE     = 3'b000;
+parameter SPI_INIT_CMD_WAIT = 3'b001;
+parameter SPI_INIT_WRR_CMD  = 3'b010;
+parameter SPI_INIT_WRR_WAIT = 3'b011;
+
+//---------------------------------------------------------
+// Variable declartion
+// -------------------------------------------------------
+logic                 spi_init_done  ;
+logic   [2:0]         spi_init_state ;
+logic                spim_mem_req   ;
+logic                spim_reg_req   ;
+
+
+logic                 spim_wb_req    ;
+logic                 spim_wb_req_l  ;
+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]  spim_reg_rdata ;
+logic [WB_WIDTH-1:0]  spim_wb_rdata  ;
+logic  [WB_WIDTH-1:0] reg_rdata      ;
+
+// Control Signal Generated from Reg to SPI Access
+logic                 reg2spi_req;
+logic         [31:0]  reg2spi_addr;
+logic          [5:0]  reg2spi_addr_len;
+logic         [31:0]  reg2spi_cmd;
+logic          [5:0]  reg2spi_cmd_len;
+logic          [3:0]  reg2spi_csreg;
+logic         [15:0]  reg2spi_data_len;
+logic                 reg2spi_mode_enb; // mode enable
+logic         [7:0]   reg2spi_mode;     // mode 
+logic         [15:0]  reg2spi_dummy_rd_len;
+logic         [15:0]  reg2spi_dummy_wr_len;
+logic                 reg2spi_swrst;
+logic                 reg2spi_rd;
+logic                 reg2spi_wr;
+logic                 reg2spi_qrd;
+logic                 reg2spi_qwr;
+logic         [31:0]  reg2spi_wdata;
+//------------------------------------------------------------------   
+// Priority given to mem2spi request over Reg2Spi
+
+    assign  spi_req           =  (spim_mem_req && !spim_wb_we) ? 1'b1                           : reg2spi_req;      
+    assign  spi_addr          =  (spim_mem_req && !spim_wb_we) ? {spim_wb_addr[23:0],8'h0}      : reg2spi_addr;      
+    assign  spi_addr_len      =  (spim_mem_req && !spim_wb_we) ? 24                             : reg2spi_addr_len;  
+    assign  spi_cmd           =  (spim_mem_req && !spim_wb_we) ? 8'hEB                          : reg2spi_cmd;       
+    assign  spi_cmd_len       =  (spim_mem_req && !spim_wb_we) ? 8                              : reg2spi_cmd_len;   
+    assign  spi_mode_cmd      =  (spim_mem_req && !spim_wb_we) ? 8'h00                          : reg2spi_mode;       
+    assign  spi_mode_cmd_enb  =  (spim_mem_req && !spim_wb_we) ? 1                              : reg2spi_mode_enb;   
+    assign  spi_csreg         =  (spim_mem_req && !spim_wb_we) ? '1                             : reg2spi_csreg;     
+    assign  spi_data_len      =  (spim_mem_req && !spim_wb_we) ? 'h10                           : reg2spi_data_len;  
+    assign  spi_dummy_rd_len  =  (spim_mem_req && !spim_wb_we) ? 16                             : reg2spi_dummy_rd_len;  
+    assign  spi_dummy_wr_len  =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_dummy_wr_len;  
+    assign  spi_swrst         =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_swrst;     
+    assign  spi_rd            =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_rd;        
+    assign  spi_wr            =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_wr;        
+    assign  spi_qrd           =  (spim_mem_req && !spim_wb_we) ? 1                              : reg2spi_qrd;       
+    assign  spi_qwr           =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_qwr;       
+    assign  spi_wdata         =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_wdata;       
+
+
+
+
+  //---------------------------------------------------------------
+  // Address Decoding
+  // 0x0000_0000 - 0x0FFF_FFFF  - SPI FLASH MEMORY ACCESS - 256MB
+  // 0x1000_0000 -              - SPI Register Access
+  // --------------------------------------------------------------
+
+  assign spim_mem_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0000);
+  assign spim_reg_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0001);
+
+
+  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_req_l <= '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
+        spim_wb_req   <= wbd_stb_i;
+        spim_wb_req_l <= spim_wb_req;
+        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 there is Reg2Spi read Access, Register the Read Data
+	if(reg2spi_req && (reg2spi_rd || reg2spi_qrd ) && spi_ack) 
+             spim_reg_rdata <= spi_rdata;
+
+	if(!spim_wb_we && spim_wb_req && spi_ack) 
+           spim_wb_rdata <= spi_rdata;
+        else
+           spim_wb_rdata <= reg_rdata;
+
+        // For safer design, we have generated ack after 2 cycle latter to 
+	// cross-check current request is towards SPI or not
+        spim_wb_ack   <= (spi_req) ? spi_ack :
+		         ((spim_wb_ack==0) && spim_wb_req && spim_wb_req_l) ;
+   end
+end
+
+  integer byte_index;
+  always_ff @(negedge rst_n or posedge mclk) begin
+    if ( rst_n == 1'b0 ) begin
+      reg2spi_swrst         <= 1'b0;
+      reg2spi_rd            <= 1'b0;
+      reg2spi_wr            <= 1'b0;
+      reg2spi_qrd           <= 1'b0;
+      reg2spi_qwr           <= 1'b0;
+      reg2spi_cmd           <=  'h0;
+      reg2spi_addr          <=  'h0;
+      reg2spi_cmd_len       <=  'h0;
+      reg2spi_addr_len      <=  'h0;
+      reg2spi_data_len      <=  'h0;
+      reg2spi_wdata         <=  'h0;
+      reg2spi_mode_enb      <=  'h0;
+      reg2spi_mode          <=  'h0;
+      reg2spi_dummy_rd_len  <=  'h0;
+      reg2spi_dummy_wr_len  <=  'h0;
+      reg2spi_csreg         <=  'h0;
+      reg2spi_req           <=  'h0;
+      spi_clk_div_valid     <= 1'b0;
+      spi_clk_div           <=  'h2;
+      spi_init_done         <=  'h0;
+      spi_init_state        <=  SPI_INIT_IDLE;
+    end
+    else if (spi_init_done == 0) begin
+       case(spi_init_state)
+	   SPI_INIT_IDLE:
+	   begin
+              reg2spi_rd        <= 'h0;
+              reg2spi_wr        <= 'h1; // SPI Write Req
+              reg2spi_qrd       <= 'h0;
+              reg2spi_qwr       <= 'h0;
+              reg2spi_swrst     <= 'h0;
+              reg2spi_csreg     <= 'h1;
+              reg2spi_cmd[7:0]  <= 'h6; // WREN command
+              reg2spi_mode[7:0] <= 'h0;
+              reg2spi_cmd_len   <= 'h8;
+              reg2spi_addr_len  <= 'h0;
+              reg2spi_data_len  <= 'h0;
+              reg2spi_wdata     <= 'h0;
+	      reg2spi_req       <= 'h1;
+              spi_init_state    <=  SPI_INIT_CMD_WAIT;
+	   end
+	   SPI_INIT_CMD_WAIT:
+	   begin
+	      if(spi_ack)   begin
+	         reg2spi_req      <= 1'b0;
+                 spi_init_state    <=  SPI_INIT_WRR_CMD;
+	      end
+	   end
+	   SPI_INIT_WRR_CMD:
+	   begin
+              reg2spi_rd        <= 'h0;
+              reg2spi_wr        <= 'h1; // SPI Write Req
+              reg2spi_qrd       <= 'h0;
+              reg2spi_qwr       <= 'h0;
+              reg2spi_swrst     <= 'h0;
+              reg2spi_csreg     <= 'h1;
+              reg2spi_cmd[7:0]  <= 'h1; // WRR command
+              reg2spi_mode[7:0] <= 'h0;
+              reg2spi_cmd_len   <= 'h8;
+              reg2spi_addr_len  <= 'h0;
+              reg2spi_data_len  <= 'h10;
+              reg2spi_wdata     <= {8'h0,8'h2,16'h0}; // <sr1[7:0]><<cr1[7:0]><16'h0> cr1[1] = 1 indicate quad mode
+	      reg2spi_req       <= 'h1;
+              spi_init_state    <=  SPI_INIT_WRR_WAIT;
+	   end
+	   SPI_INIT_WRR_WAIT:
+	   begin
+	      if(spi_ack)   begin
+	         reg2spi_req      <= 1'b0;
+                 spi_init_done    <=  'h1;
+	      end
+	   end
+       endcase
+    end else if (spim_reg_req & spim_wb_we )
+    begin
+      case(spim_wb_addr[7:4])
+        REG_CTRL:
+        begin
+          if ( spim_wb_be[0] == 1 )
+          begin
+            reg2spi_rd    <= spim_wb_wdata[0];
+            reg2spi_wr    <= spim_wb_wdata[1];
+            reg2spi_qrd   <= spim_wb_wdata[2];
+            reg2spi_qwr   <= spim_wb_wdata[3];
+            reg2spi_swrst <= spim_wb_wdata[4];
+	    reg2spi_req   <= 1'b1;
+          end
+          if ( spim_wb_be[1] == 1 )
+          begin
+            reg2spi_csreg <= spim_wb_wdata[11:8];
+          end
+        end
+        REG_CLKDIV:
+          if ( spim_wb_be[0] == 1 )
+          begin
+            spi_clk_div <= spim_wb_wdata[7:0];
+            spi_clk_div_valid <= 1'b1;
+          end
+        REG_SPICMD: begin
+          if ( spim_wb_be[0] == 1 )
+              reg2spi_cmd[7:0] <= spim_wb_wdata[7:0];
+          if ( spim_wb_be[1] == 1 )
+              reg2spi_mode[7:0] <= spim_wb_wdata[15:8];
+          end
+        REG_SPIADR:
+          for (byte_index = 0; byte_index < 4; byte_index = byte_index+1 )
+            if ( spim_wb_be[byte_index] == 1 )
+              reg2spi_addr[byte_index*8 +: 8] <= spim_wb_wdata[(byte_index*8) +: 8];
+        REG_SPILEN:
+        begin
+          if ( spim_wb_be[0] == 1 ) begin
+               reg2spi_mode_enb <= spim_wb_wdata[6];
+               reg2spi_cmd_len  <= spim_wb_wdata[5:0];
+          end
+          if ( spim_wb_be[1] == 1 )
+            reg2spi_addr_len <= spim_wb_wdata[13:8];
+          if ( spim_wb_be[2] == 1 )
+            reg2spi_data_len[7:0] <= spim_wb_wdata[23:16];
+          if ( spim_wb_be[3] == 1 )
+            reg2spi_data_len[15:8] <= spim_wb_wdata[31:24];
+        end
+        REG_SPIDUM:
+        begin
+          if ( spim_wb_be[0] == 1 )
+            reg2spi_dummy_rd_len[7:0]  <= spim_wb_wdata[7:0];
+          if ( spim_wb_be[1] == 1 )
+            reg2spi_dummy_rd_len[15:8] <= spim_wb_wdata[15:8];
+          if ( spim_wb_be[2] == 1 )
+            reg2spi_dummy_wr_len[7:0]  <= spim_wb_wdata[23:16];
+          if ( spim_wb_be[3] == 1 )
+            reg2spi_dummy_wr_len[15:8] <= spim_wb_wdata[31:24];
+        end
+	REG_SPIWDATA: begin
+           reg2spi_wdata     <= spim_wb_wdata;
+	end
+      endcase
+    end
+    else
+    begin
+      if(spi_ack && spim_reg_req)   
+	 reg2spi_req <= 1'b0;
+    end
+  end 
+
+
+  // implement slave model register read mux
+  always_comb
+    begin
+      reg_rdata = '0;
+      case(spim_wb_addr[7:4])
+        REG_CTRL:
+                reg_rdata[31:0] =  { 20'h0, 
+		                     reg2spi_csreg,
+		                     3'b0,
+		                     reg2spi_swrst,
+		                     reg2spi_qwr,
+		                     reg2spi_qrd,
+		                     reg2spi_wr,
+		                     reg2spi_rd};
+
+        REG_CLKDIV:
+                reg_rdata[31:0] = {24'h0,spi_clk_div};
+        REG_SPICMD:
+                reg_rdata[31:0] = {16'h0,reg2spi_mode,reg2spi_cmd};
+        REG_SPIADR:
+                reg_rdata[31:0] = reg2spi_addr;
+        REG_SPILEN:
+                reg_rdata[31:0] = {reg2spi_data_len,2'b00,reg2spi_addr_len,1'b0,reg2spi_mode_enb,reg2spi_cmd_len};
+        REG_SPIDUM:
+                reg_rdata[31:0] = {reg2spi_dummy_wr_len,reg2spi_dummy_rd_len};
+        REG_SPIWDATA:
+                reg_rdata[31:0] = reg2spi_wdata;
+        REG_SPIRDATA:
+                reg_rdata[31:0] = spim_reg_rdata;
+        REG_STATUS:
+                reg_rdata[31:0] = {24'h0,spi_status};
+      endcase
+    end 
+
+
+endmodule
diff --git a/verilog/rtl/spi_master/src/spim_rx.sv b/verilog/rtl/spi_master/src/spim_rx.sv
new file mode 100644
index 0000000..f11c16b
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_rx.sv
@@ -0,0 +1,175 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI RX  Module                                              ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  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 spim_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        en,
+    input  logic        rx_edge,
+    output logic        rx_done,
+    input  logic        sdi0,
+    input  logic        sdi1,
+    input  logic        sdi2,
+    input  logic        sdi3,
+    input  logic        en_quad_in,
+    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
+);
+
+  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 [15:0] counter_trgt_next;
+  logic        reg_done;
+  enum logic [1:0] { IDLE, RECEIVE, WAIT_FIFO, WAIT_FIFO_DONE } rx_CS, rx_NS;
+
+
+  assign reg_done  = (!en_quad_in && (counter[4:0] == 5'b11111)) || (en_quad_in && (counter[2:0] == 3'b111));
+
+  // RISV is little endian, so data is converted to little endian format
+  assign 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]};
+  assign rx_done = (counter == (counter_trgt-1)) &  rx_edge;
+
+  always_comb
+  begin
+    if (counter_in_upd)
+      counter_trgt_next = (en_quad_in) ? {2'b00,counter_in[15:2]} : counter_in;
+    else
+      counter_trgt_next = counter_trgt;
+  end
+
+  always_comb
+  begin
+    rx_NS         = rx_CS;
+    clk_en_o      = 1'b0;
+    data_int_next = data_int;
+    data_valid    = 1'b0;
+    counter_next  = counter;
+
+    case (rx_CS)
+      IDLE: begin
+        clk_en_o = 1'b0;
+
+        // check first if there is available space instead of later
+        if (en) begin
+          rx_NS = RECEIVE;
+        end
+      end
+
+      RECEIVE: begin
+        clk_en_o = 1'b1;
+
+        if (rx_edge) begin
+          counter_next = counter + 1;
+          if (en_quad_in)
+             data_int_next = {data_int[27:0],sdi3,sdi2,sdi1,sdi0};
+          else
+             data_int_next = {data_int[30:0],sdi1};
+
+          if (rx_done) begin
+            counter_next = 0;
+            data_valid   = 1'b1;
+
+            if (data_ready)
+              rx_NS = IDLE;
+            else
+              rx_NS = WAIT_FIFO_DONE;
+          end else if (reg_done) begin
+            data_valid = 1'b1;
+
+            if (~data_ready) begin
+              // no space in the FIFO, wait for free space
+              clk_en_o = 1'b0;
+              rx_NS    = WAIT_FIFO;
+            end
+          end
+        end
+      end
+
+      WAIT_FIFO_DONE: begin
+        data_valid = 1'b1;
+        if (data_ready)
+          rx_NS = IDLE;
+      end
+
+      WAIT_FIFO: begin
+        data_valid = 1'b1;
+        if (data_ready)
+          rx_NS = RECEIVE;
+      end
+    endcase
+  end
+
+
+  always_ff @(posedge clk, negedge rstn)
+  begin
+    if (rstn == 0)
+    begin
+      counter      <= 0;
+      counter_trgt <= 'h8;
+      data_int     <= '0;
+      rx_CS        <= IDLE;
+    end
+    else
+    begin
+      counter      <= counter_next;
+      counter_trgt <= counter_trgt_next;
+      data_int     <= data_int_next;
+      rx_CS        <= rx_NS;
+    end
+  end
+
+endmodule
diff --git a/verilog/rtl/spi_master/src/spim_top.sv b/verilog/rtl/spi_master/src/spim_top.sv
new file mode 100644
index 0000000..9943f00
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_top.sv
@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI Master Top Module                                       ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  http://www.opencores.org/cores/yifive/                      ////
+////                                                              ////
+////  Description                                                 ////
+////     SPI Master Top 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 spim_top
+#( parameter WB_WIDTH = 32)
+(
+    input  logic                          mclk,
+    input  logic                          rst_n,
+
+
+    output  logic                         wbd_stb_i, // strobe/request
+    output  logic   [WB_WIDTH-1:0]        wbd_adr_i, // address
+    output  logic                         wbd_we_i,  // write
+    output  logic   [WB_WIDTH-1:0]        wbd_dat_i, // data output
+    output  logic   [3:0]                 wbd_sel_i, // byte enable
+    input   logic   [WB_WIDTH-1:0]        wbd_dat_o, // data input
+    input   logic                         wbd_ack_o, // acknowlegement
+    input   logic                         wbd_err_o,  // error
+
+    output logic                    [1:0] events_o,
+
+    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
+);
+
+
+
+    logic   [7:0] spi_clk_div;
+    logic         spi_clk_div_valid;
+    logic   [7:0] spi_status;
+    logic  [31:0] spi_addr;
+    logic   [5:0] spi_addr_len;
+    logic  [7:0]  spi_cmd;
+    logic   [5:0] spi_cmd_len;
+    logic  [7:0]  spi_mode_cmd;
+    logic         spi_mode_cmd_enb;
+    logic  [15:0] spi_data_len;
+    logic  [15:0] spi_dummy_rd_len;
+    logic  [15:0] spi_dummy_wr_len;
+    logic         spi_swrst;
+    logic         spi_rd;
+    logic         spi_wr;
+    logic         spi_qrd;
+    logic         spi_qwr;
+    logic [31:0]  spi_wdata;
+    logic [31:0]  spi_rdata;
+    logic   [3:0] spi_csreg;
+    logic  [31:0] spi_data_tx;
+    logic         spi_data_tx_valid;
+    logic         spi_data_tx_ready;
+    logic  [31:0] spi_data_rx;
+    logic         spi_data_rx_valid;
+    logic         spi_data_rx_ready;
+    logic   [7:0] spi_ctrl_status;
+    logic  [31:0] spi_ctrl_data_tx;
+    logic         spi_ctrl_data_tx_valid;
+    logic         spi_ctrl_data_tx_ready;
+    logic  [31:0] spi_ctrl_data_rx;
+    logic         spi_ctrl_data_rx_valid;
+    logic         spi_ctrl_data_rx_ready;
+    logic  [31:0] reg2spi_wdata;
+
+    logic         s_eot;
+
+
+
+
+
+    spim_regs
+    #(
+        .WB_WIDTH(WB_WIDTH)
+    )
+    u_spim_regs
+    (
+        .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
+
+        .spi_clk_div                    (spi_clk_div                  ),
+        .spi_clk_div_valid              (spi_clk_div_valid            ),
+        .spi_status                     (spi_status                   ),
+
+
+        .spi_req                        (spi_req                     ),
+        .spi_addr                       (spi_addr                     ),
+        .spi_addr_len                   (spi_addr_len                 ),
+        .spi_cmd                        (spi_cmd                      ),
+        .spi_cmd_len                    (spi_cmd_len                  ),
+        .spi_mode_cmd                   (spi_mode_cmd                 ),
+        .spi_mode_cmd_enb               (spi_mode_cmd_enb             ),
+        .spi_csreg                      (spi_csreg                    ),
+        .spi_data_len                   (spi_data_len                 ),
+        .spi_dummy_rd_len               (spi_dummy_rd_len             ),
+        .spi_dummy_wr_len               (spi_dummy_wr_len             ),
+        .spi_swrst                      (spi_swrst                    ),
+        .spi_rd                         (spi_rd                       ),
+        .spi_wr                         (spi_wr                       ),
+        .spi_qrd                        (spi_qrd                      ),
+        .spi_qwr                        (spi_qwr                      ),
+        .spi_wdata                      (spi_wdata                    ),
+        .spi_rdata                      (spi_rdata                    ),
+        .spi_ack                        (spi_ack                      )
+    );
+
+    spim_ctrl u_spictrl
+    (
+        .clk                            (mclk                         ),
+        .rstn                           (rst_n                        ),
+        .eot                            (                             ),
+
+        .spi_clk_div                    (spi_clk_div                  ),
+        .spi_clk_div_valid              (spi_clk_div_valid            ),
+        .spi_status                     (spi_ctrl_status              ),
+
+        .spi_req                        (spi_req                      ),
+        .spi_addr                       (spi_addr                     ),
+        .spi_addr_len                   (spi_addr_len                 ),
+        .spi_cmd                        (spi_cmd                      ),
+        .spi_cmd_len                    (spi_cmd_len                  ),
+        .spi_mode_cmd                   (spi_mode_cmd                 ),
+        .spi_mode_cmd_enb               (spi_mode_cmd_enb             ),
+        .spi_csreg                      (spi_csreg                    ),
+        .spi_data_len                   (spi_data_len                 ),
+        .spi_dummy_rd_len               (spi_dummy_rd_len             ),
+        .spi_dummy_wr_len               (spi_dummy_wr_len             ),
+        .spi_swrst                      (spi_swrst                    ),
+        .spi_rd                         (spi_rd                       ),
+        .spi_wr                         (spi_wr                       ),
+        .spi_qrd                        (spi_qrd                      ),
+        .spi_qwr                        (spi_qwr                      ),
+        .spi_wdata                      (spi_wdata                    ),
+        .spi_rdata                      (spi_rdata                    ),
+        .spi_ack                        (spi_ack                      ),
+
+        .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_sdo0                     ),
+        .spi_sdo1                       (spi_sdo1                     ),
+        .spi_sdo2                       (spi_sdo2                     ),
+        .spi_sdo3                       (spi_sdo3                     ),
+        .spi_sdi0                       (spi_sdi0                     ),
+        .spi_sdi1                       (spi_sdi1                     ),
+        .spi_sdi2                       (spi_sdi2                     ),
+        .spi_sdi3                       (spi_sdi3                     ),
+	.spi_en_tx                      (spi_en_tx                    )
+    );
+
+endmodule
diff --git a/verilog/rtl/spi_master/src/spim_tx.sv b/verilog/rtl/spi_master/src/spim_tx.sv
new file mode 100644
index 0000000..d3fd332
--- /dev/null
+++ b/verilog/rtl/spi_master/src/spim_tx.sv
@@ -0,0 +1,169 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  SPI TX  Module                                              ////
+////                                                              ////
+////  This file is part of the YIFive cores project               ////
+////  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 spim_tx
+(
+    // General Input
+    input  logic        clk,            // SPI clock
+    input  logic        rstn,           // Active low Reset
+    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        en_quad_in,     // SPI quad mode indication
+    input  logic [15:0] counter_in,     // Transmit counter
+    input  logic [31:0] txdata,         // 32 bit tranmsit data
+    input  logic        data_valid,     // Input data valid
+    output logic        data_ready,     // Data in acepted, this for txfifo
+    output logic        clk_en_o        // Enable Tx clock
+);
+
+  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                 en_quad;
+
+  enum logic [0:0] { IDLE, TRANSMIT } tx_CS, tx_NS;
+
+  // Counter Exit condition, quad mode div-4 , else actual counter
+  always_comb
+  begin
+     counter_trgt = (en_quad_in) ? {2'b00,counter_in[15:2]} : counter_in;
+  end
+
+  //Indicate end of transmission of all the bytes
+  assign tx_done = (counter == counter_trgt) && tx_edge;
+
+
+  // Indicate 32 bit data done, usefull for readining next 32b from txfifo
+  assign tx32b_done  = (!en_quad && (counter[4:0] == 5'b11111)) || (en_quad && (counter[2:0] == 3'b111)) && tx_edge;
+
+
+
+  always_comb
+  begin
+    tx_NS         = tx_CS;
+    clk_en_o      = 1'b0;
+    data_int_next = data_int;
+    data_ready    = 1'b0;
+    counter_next  = counter;
+
+    case (tx_CS)
+      IDLE: begin
+        clk_en_o = 1'b0;
+        data_int_next = txdata;
+
+        if (en && data_valid) begin
+          data_ready    = 1'b1;
+          tx_NS         = TRANSMIT;
+        end
+      end
+
+      TRANSMIT: begin
+        clk_en_o = 1'b1;
+        counter_next = counter + 1;
+        data_int_next = (en_quad) ? {data_int[27:0],4'b0000} : {data_int[30:0],1'b0};
+
+        if (tx_done) begin
+            counter_next = 0;
+	    // Check if there is next data
+            if (en && data_valid) begin 
+              data_int_next = txdata;
+              data_ready    = 1'b1;
+              tx_NS         = TRANSMIT;
+            end else begin
+              clk_en_o = 1'b0;
+              tx_NS    = IDLE;
+            end
+        end else if (tx32b_done) begin
+            if (data_valid) begin
+              data_int_next = txdata;
+              data_ready    = 1'b1;
+            end else begin
+              clk_en_o = 1'b0;
+              tx_NS    = IDLE;
+            end
+        end
+      end
+    endcase
+  end
+
+  always_ff @(posedge clk, negedge rstn)
+  begin
+    if (~rstn)
+    begin
+      counter      <= 0;
+      data_int     <= 'h0;
+      tx_CS        <= IDLE;
+      en_quad      <= 0;
+    end
+    else
+    begin
+       if(tx_edge) begin
+          counter      <= counter_next;
+          data_int     <= data_int_next;
+          sdo0         <= (en_quad_in) ? data_int_next[28] : data_int_next[31];
+          sdo1         <= (en_quad_in) ? data_int_next[29] : 1'b1;
+          sdo2         <= (en_quad_in) ? data_int_next[30] : 1'b1;
+          sdo3         <= (en_quad_in) ? data_int_next[31] : 1'b1;
+          tx_CS        <= tx_NS;
+	  en_quad      <= en_quad_in;
+       end
+    end
+  end
+endmodule