spi master with qddr mode support added
diff --git a/openlane/spi_master/config.tcl b/openlane/spi_master/config.tcl
index ec8bb96..fa42bf3 100755
--- a/openlane/spi_master/config.tcl
+++ b/openlane/spi_master/config.tcl
@@ -61,7 +61,10 @@
 set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg
 
 set ::env(FP_SIZING) absolute
-set ::env(DIE_AREA) "0 0 400 600"
+set ::env(DIE_AREA) "0 0 400 650"
+
+set ::env(PL_TIME_DRIVEN) 1
+set ::env(PL_TARGET_DENSITY) "0.45"
 
 
 # If you're going to use multiple power domains, then keep this disabled.
diff --git a/openlane/wb_interconnect/config.tcl b/openlane/wb_interconnect/config.tcl
index 4e6a946..31e4c0c 100755
--- a/openlane/wb_interconnect/config.tcl
+++ b/openlane/wb_interconnect/config.tcl
@@ -68,6 +68,8 @@
 
 
 set ::env(PL_ROUTABILITY_DRIVEN) 1
+set ::env(FP_CORE_UTIL) "40"
+set ::env(PL_TARGET_DENSITY) "0.50"
 
 set ::env(FP_IO_VEXTEND) 4
 set ::env(FP_IO_HEXTEND) 4
diff --git a/signoff/spi_master/final_summary_report.csv b/signoff/spi_master/final_summary_report.csv
index 099784f..2d25b3d 100644
--- a/signoff/spi_master/final_summary_report.csv
+++ b/signoff/spi_master/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/spi_master,spim_top,spi_master,Flow_completed,0h10m24s,0h6m34s,64225.0,0.24,32112.5,47,650.94,7707,0,0,0,0,0,0,0,2,4,-1,0,340960,59901,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,257797329,0.0,27.62,36.77,0.2,-1,-1,7643,7783,1271,1411,0,0,0,7707,242,0,168,95,1009,216,28,2394,1352,1291,25,424,2889,0,3313,100.0,10.0,10,AREA 0,4,50,1,100,100,0.55,0,sky130_fd_sc_hd,4,3
+0,/project/openlane/spi_master,spim_top,spi_master,Flow_completed,0h9m17s,0h5m31s,58515.38461538461,0.26,29257.692307692305,43,643.85,7607,0,0,0,0,0,0,0,7,1,-1,0,373344,58969,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,302026706,0.0,25.54,39.4,0.02,-1,-1,7543,7683,1272,1412,0,0,0,7607,245,0,169,101,1053,212,32,2444,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,3
diff --git a/signoff/syntacore/final_summary_report.csv b/signoff/syntacore/final_summary_report.csv
index 03d8be4..fe9e111 100644
--- a/signoff/syntacore/final_summary_report.csv
+++ b/signoff/syntacore/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/syntacore,scr1_top_wb,syntacore,Flow_completed,0h52m12s,0h27m25s,27759.375,1.92,13879.6875,19,1195.43,26649,0,0,0,0,0,0,0,105,1,-1,0,1672470,234282,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1304827840,0.0,18.7,16.26,3.38,0.29,-1,26472,26773,3391,3692,0,0,0,26649,876,68,661,601,2743,980,298,7804,3218,3182,68,866,24574,1,25441,100.0,10.0,10,AREA 0,4,50,1,100,100,0.45,0,sky130_fd_sc_hd,4,3
+0,/project/openlane/syntacore,scr1_top_wb,syntacore,Flow_completed,0h51m54s,0h25m57s,27752.083333333336,1.92,13876.041666666668,21,1260.14,26642,0,0,0,0,0,0,0,22,4,-1,0,1736239,260546,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1305933937,0.0,24.35,15.89,5.68,0.9,-1,26465,26766,3393,3694,0,0,0,26642,718,68,677,584,2809,986,293,7964,3220,3184,61,866,24574,0,25440,100.0,10.0,10,AREA 0,4,50,1,100,100,0.45,0,sky130_fd_sc_hd,4,4
diff --git a/signoff/user_project_wrapper/final_summary_report.csv b/signoff/user_project_wrapper/final_summary_report.csv
index fa9e31a..b467fd5 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,0h39m53s,0h4m37s,3.3079078455790785,10.2784,1.6539539227895392,0,551.71,17,0,0,0,0,0,0,0,0,1,-1,-1,1189766,3917,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1,0.0,1.26,4.3,0.77,1.93,-1,848,1466,848,1466,0,0,0,17,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,80,0.55,0,sky130_fd_sc_hd,4,0
+0,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,Flow_completed,0h41m39s,0h4m37s,3.3079078455790785,10.2784,1.6539539227895392,0,552.52,17,0,0,0,0,0,0,0,0,1,-1,-1,1190352,4009,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1,0.0,1.26,4.32,0.78,1.93,-1,848,1466,848,1466,0,0,0,17,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,80,0.55,0,sky130_fd_sc_hd,4,0
diff --git a/verilog/dv/user_spi/run_iverilog b/verilog/dv/user_spi/run_iverilog
index a88ab91..eb92eae 100755
--- a/verilog/dv/user_spi/run_iverilog
+++ b/verilog/dv/user_spi/run_iverilog
@@ -31,7 +31,7 @@
 #iverilog -g2005-sv -DWFDUMP -DFUNCTIONAL -DSIM -I $PDK_PATH -I  ../../../caravel/verilog/rtl  -I ../ -I ../../../verilog/rtl -I ../ -I ../../../verilog -I ../../../verilog/rtl/syntacore/scr1/src/includes   -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_spi_tb.v -o user_spi_tb.vvp
 
 #iverilog without Dump
-iverilog -g2005-sv -DFUNCTIONAL -DSIM -I $PDK_PATH -I  ../../../caravel/verilog/rtl  -I ../ -I ../../../verilog/rtl -I ../ -I ../../../verilog -I ../../../verilog/rtl/syntacore/scr1/src/includes   -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_spi_tb.v -o user_spi_tb.vvp
+iverilog -g2005-sv -D WFDUMP -DFUNCTIONAL -DSIM -I $PDK_PATH -I  ../../../caravel/verilog/rtl  -I ../ -I ../../../verilog/rtl -I ../ -I ../../../verilog -I ../../../verilog/rtl/syntacore/scr1/src/includes   -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_spi_tb.v -o user_spi_tb.vvp
 
 # GLS 
 #iverilog -g2005-sv -D GL -D FUNCTIONAL -I $PDK_PATH -I  ../../../caravel/verilog/rtl  -I ../ -I ../../../verilog/gl -I ../../../verilog -I /home/dinesha/workarea/pdk/sky130A -I ../../../verilog/rtl/syntacore/scr1/src/includes   -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_spi_tb.v -o user_spi_tb.vvp
diff --git a/verilog/dv/user_spi/user_spi_tb.v b/verilog/dv/user_spi/user_spi_tb.v
index 65371ae..17d3292 100644
--- a/verilog/dv/user_spi/user_spi_tb.v
+++ b/verilog/dv/user_spi/user_spi_tb.v
@@ -203,6 +203,33 @@
 		wb_user_core_read_check(32'h1000001C,read_data,32'h00190201);
 		$display("#############################################");
 		$display("Testing Direct SPI Memory Read              ");
+		$display(" SPI Mode: QDDR (Dual 4 but)                ");
+		$display("Prefetch : 1DW, OPCODE:READ(0xED)           ");
+		$display("SEQ: Command -> Address -> Read Data        ");
+		$display("#############################################");
+		// QDDR Config
+                wb_user_core_write('h3080_0004,'h10); // Change the Bank Sel 10
+		wb_user_core_write(32'h10000004,{24'h0,2'b01,2'b11,4'b0001});
+		wb_user_core_write(32'h10000008,{8'h04,2'b01,2'b10,4'h6,8'h00,8'hED});
+                wb_user_core_write('h3080_0004,'h00); // Change the Bank Sel 00
+		wb_user_core_read_check(32'h00000200,read_data,32'h00000093);
+		wb_user_core_read_check(32'h00000204,read_data,32'h00000113);
+		wb_user_core_read_check(32'h00000208,read_data,32'h00000193);
+		wb_user_core_read_check(32'h0000020C,read_data,32'h00000213);
+		wb_user_core_read_check(32'h00000210,read_data,32'h00000293);
+		wb_user_core_read_check(32'h00000214,read_data,32'h00000313);
+		wb_user_core_read_check(32'h00000218,read_data,32'h00000393);
+		wb_user_core_read_check(32'h0000021C,read_data,32'h00000413);
+		wb_user_core_read_check(32'h00000400,read_data,32'h11223737);
+		wb_user_core_read_check(32'h00000404,read_data,32'h300007b7);
+		wb_user_core_read_check(32'h00000408,read_data,32'h34470293);
+		wb_user_core_read_check(32'h0000040C,read_data,32'h22334337);
+		wb_user_core_read_check(32'h00000410,read_data,32'h0057ac23);
+		wb_user_core_read_check(32'h00000414,read_data,32'h45530393);
+		wb_user_core_read_check(32'h00000418,read_data,32'h33445537);
+		wb_user_core_read_check(32'h0000041C,read_data,32'h0077ae23);
+		$display("#############################################");
+		$display("Testing Direct SPI Memory Read              ");
 		$display(" SPI Mode: Normal/Single Bit                ");
 		$display("Prefetch : 1DW, OPCODE:READ(0x3)            ");
 		$display("SEQ: Command -> Address -> Read Data        ");
diff --git a/verilog/rtl/spi_master/src/spim_ctrl.sv b/verilog/rtl/spi_master/src/spim_ctrl.sv
index 42f7a5d..e8aa2e4 100644
--- a/verilog/rtl/spi_master/src/spim_ctrl.sv
+++ b/verilog/rtl/spi_master/src/spim_ctrl.sv
@@ -123,15 +123,17 @@
     input  logic                          spi_sdi1,
     input  logic                          spi_sdi2,
     input  logic                          spi_sdi3,
-    output logic                          spi_en_tx // Spi Direction control
+    output logic                          spi_en_tx_out // Spi Direction control
 );
 
 //--------------------------------------
 // Parameter
 // --------------------------------------
-parameter  SPI_STD     = 2'b00;
-parameter  SPI_QUAD_TX = 2'b01;
-parameter  SPI_QUAD_RX = 2'b10;
+parameter P_SINGLE = 2'b00;
+parameter P_DOUBLE = 2'b01;
+parameter P_QUAD   = 2'b10;
+parameter P_QDDR   = 2'b11;
+
 
 /*************************************************************
 *  SPI FSM State Control
@@ -200,6 +202,7 @@
   logic spi_clock_en;
 
   logic spi_en_rx;
+  logic spi_en_tx;
 
 
   logic [15:0] counter_tx;
@@ -207,6 +210,7 @@
   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;
@@ -298,11 +302,13 @@
   //---------------------------------------------------------------------------
   
   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
 
   spim_clkgen u_clkgen
   (
@@ -329,9 +335,11 @@
     .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              )
   );
   spim_rx #(.ENDIEAN(ENDIEAN)) u_rxreg
@@ -359,6 +367,7 @@
   begin
       data_to_tx       =  'h0;
       data_to_tx_valid = 1'b0;
+      dummy_phase       = 1'b0;
 
       case(ctrl_data_mux)
           DATA_NULL:
@@ -369,6 +378,7 @@
 
           DATA_EMPTY:
           begin
+	      dummy_phase       =  1'b1;
               data_to_tx       =  '0;
               data_to_tx_valid = 1'b1;
           end
@@ -471,7 +481,7 @@
           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 : 'd20;
+	                      (cfg_addr_cnt == P_24BIT) ? 'd24 : 'd32;
           counter_tx_valid = 1'b1;
           spi_en_tx        = 1'b1;
 	  if (tx_data_ready) begin
@@ -496,9 +506,16 @@
           ctrl_data_mux    = DATA_EMPTY;
           ctrl_data_valid  = 1'b1;
           counter_tx_valid = 1'b1;
-          counter_tx       =  (cfg_dummy_cnt == P_8BIT) ? 'd8 :
-	                      (cfg_dummy_cnt == P_16BIT) ? 'd16 :
-	                      (cfg_dummy_cnt == P_24BIT) ? 'd24 : 'd20;
+	  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;
@@ -575,7 +592,7 @@
              // If you see new command request, then abort the current request
 	      next_state = FSM_FLUSH;
 	  end else begin
-	     if (rx_done && spi_rise) begin
+	     if (rx_done) begin
 	         next_state = FSM_CS_DEASEERT;
              end 
 	  end
@@ -666,10 +683,10 @@
   // ----------------------------------------------------------------------
   always @(posedge clk or negedge rstn) begin
      if (rstn == 1'b0) begin
-        s_spi_mode <= SPI_STD;
+        s_spi_mode <= P_SINGLE;
      end else begin
 	if(state == FSM_IDLE) begin // Reset the Mode at IDLE State
-            s_spi_mode <= SPI_STD;
+            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
diff --git a/verilog/rtl/spi_master/src/spim_regs.sv b/verilog/rtl/spi_master/src/spim_regs.sv
index 545e3b3..496d75e 100644
--- a/verilog/rtl/spi_master/src/spim_regs.sv
+++ b/verilog/rtl/spi_master/src/spim_regs.sv
@@ -443,7 +443,7 @@
                  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
+                 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
@@ -480,7 +480,7 @@
         MEM_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
+               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
diff --git a/verilog/rtl/spi_master/src/spim_rx.sv b/verilog/rtl/spi_master/src/spim_rx.sv
index 47c4922..199ef4c 100644
--- a/verilog/rtl/spi_master/src/spim_rx.sv
+++ b/verilog/rtl/spi_master/src/spim_rx.sv
@@ -91,6 +91,7 @@
   parameter P_SINGLE = 2'b00;
   parameter P_DOUBLE = 2'b01;
   parameter P_QUAD   = 2'b10;
+  parameter P_QDDR   = 2'b11;
 
 //------------------------------------------------------
 // Variable Decleration
@@ -103,12 +104,14 @@
   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_QUAD && (counter[2:0] == 3'b111))    ||
+	             (s_spi_mode == P_QDDR && (counter[2:0] == 3'b111));
 
 
 
@@ -130,9 +133,9 @@
 
       RECEIVE: begin
 
-        if (rx_edge) begin
+        if (rx_edge || qddr_rx_en) begin
           counter_next = counter + 1;
-          if (s_spi_mode == P_QUAD )
+          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};
@@ -185,6 +188,7 @@
       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;
@@ -194,11 +198,20 @@
         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]};
-       if (rx_edge) begin
+       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;
@@ -206,7 +219,8 @@
           clk_en_o     <= (rx_NS == RECEIVE);
        end
        if (en && counter_in_upd) begin
-           counter_trgt <= (s_spi_mode ==P_QUAD )   ? {2'b00,counter_in[15:2]} : 
+           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
diff --git a/verilog/rtl/spi_master/src/spim_top.sv b/verilog/rtl/spi_master/src/spim_top.sv
index b1af420..042319c 100644
--- a/verilog/rtl/spi_master/src/spim_top.sv
+++ b/verilog/rtl/spi_master/src/spim_top.sv
@@ -66,6 +66,8 @@
 ////            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                   ////
 ////                                                              ////
 //////////////////////////////////////////////////////////////////////
 ////                                                              ////
@@ -240,10 +242,10 @@
 
 assign  io_out[0] =  spi_clk;
 assign  io_out[1] =  spi_csn0;// No hold fix for CS#, as it asserted much eariler than SPI clock
-assign  io_out[2] =  spi_sdo0_out;
-assign  io_out[3] =  spi_sdo1_out;
-assign  io_out[4] =  spi_sdo2_out;
-assign  io_out[5] =  spi_sdo3_out;
+assign  #1 io_out[2] =  spi_sdo0_out;
+assign  #1 io_out[3] =  spi_sdo1_out;
+assign  #1 io_out[4] =  spi_sdo2_out;
+assign  #1 io_out[5] =  spi_sdo3_out;
 
 // ADDing Delay cells for Interface hold fix
 sky130_fd_sc_hd__dlygate4sd3_1 u_delay1_sdio0 (.X(spi_sdo0_d1),.A(spi_sdo0));
@@ -265,10 +267,10 @@
 
 assign  io_oeb[0] =  1'b0;         // spi_clk
 assign  io_oeb[1] =  1'b0;         // spi_csn
-assign  io_oeb[2] =  !spi_en_tx;   // spi_dio0
-assign  io_oeb[3] =  !spi_en_tx;   // spi_dio1
-assign  io_oeb[4] =  (spi_mode == 0) ? 1 'b0 : !spi_en_tx;   // spi_dio2
-assign  io_oeb[5] =  (spi_mode == 0) ? 1 'b0 : !spi_en_tx;   // spi_dio3
+assign  #1 io_oeb[2] =  !spi_en_tx;   // spi_dio0
+assign  #1 io_oeb[3] =  !spi_en_tx;   // spi_dio1
+assign  #1 io_oeb[4] =  (spi_mode == 0) ? 1 'b0 : !spi_en_tx;   // spi_dio2
+assign  #1 io_oeb[5] =  (spi_mode == 0) ? 1 'b0 : !spi_en_tx;   // spi_dio3
 
 spim_if #( .WB_WIDTH(WB_WIDTH)) u_wb_if(
         .mclk                           (mclk                         ),
@@ -491,7 +493,7 @@
         .spi_sdi1                       (spi_sdi1                     ),
         .spi_sdi2                       (spi_sdi2                     ),
         .spi_sdi3                       (spi_sdi3                     ),
-	.spi_en_tx                      (spi_en_tx                    )
+	.spi_en_tx_out                      (spi_en_tx                    )
     );
 
 endmodule
diff --git a/verilog/rtl/spi_master/src/spim_tx.sv b/verilog/rtl/spi_master/src/spim_tx.sv
index 20c499f..4b57e64 100644
--- a/verilog/rtl/spi_master/src/spim_tx.sv
+++ b/verilog/rtl/spi_master/src/spim_tx.sv
@@ -85,8 +85,10 @@
     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
 );
 
@@ -96,6 +98,7 @@
   parameter P_SINGLE = 2'b00;
   parameter P_DOUBLE = 2'b01;
   parameter P_QUAD   = 2'b10;
+  parameter P_QDDR   = 2'b11;
 
 //------------------------------------------------------
 // Variable Decleration
@@ -117,7 +120,8 @@
   // 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_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);
 
@@ -137,7 +141,7 @@
         data_int_next = txdata;
         counter_next  = '0;
 
-        if (en && data_valid) begin
+        if (en && data_valid && tx_edge) begin
 	  spi_mode_next    = s_spi_mode;
           data_ready_i    = 1'b1;
           tx_NS         = TRANSMIT;
@@ -148,7 +152,7 @@
          if ((counter + 1) ==counter_trgt) begin
                counter_next = 0;
                // Check if there is next data
-               if (en && data_valid) begin 
+               if (en && data_valid && tx_edge) begin 
 	         spi_mode_next    = s_spi_mode;
                  data_int_next = txdata;
                  data_ready_i    = 1'b1;
@@ -157,7 +161,7 @@
                  tx_NS    = IDLE;
                end
          end else if (tx32b_done) begin
-               if (en && data_valid) 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;
@@ -168,12 +172,13 @@
                end
            end else begin
               counter_next = counter + 1;
-              data_int_next = (spi_mode == P_QUAD   ) ? {data_int[27:0],4'b0000} : 
+              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) begin 
+           if (en && data_valid && tx_edge) begin 
 	     spi_mode_next    = s_spi_mode;
              data_int_next = txdata;
              data_ready_i    = 1'b1;
@@ -199,6 +204,7 @@
       counter_trgt <= '0;
       data_ready   <= '0;
       data_ready_f <= 0;
+      spi_dummy    <= 0;
       spi_mode     <= P_SINGLE;
     end
     else if(flush && tx_edge) begin
@@ -212,11 +218,12 @@
        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) begin
+       if(tx_edge || (spi_mode_next == P_QDDR)) begin
           tx_CS        <= tx_NS;
           counter      <= counter_next;
           data_int     <= data_int_next;
@@ -224,14 +231,18 @@
        // Counter Exit condition, quad mode div-4 , else actual counter
        if (en && data_ready_i && tx_edge) begin
 	  spi_mode      <= s_spi_mode;
-          counter_trgt <= (s_spi_mode == P_QUAD )   ? {2'b00,counter_in[15:2]} : 
+	  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 && tx_NS == TRANSMIT) begin
-          sdo0         <= (spi_mode_next == P_QUAD) ? data_int_next[28] : (spi_mode_next == P_DOUBLE) ? data_int_next[30] : data_int_next[31];
-          sdo1         <= (spi_mode_next == P_QUAD) ? data_int_next[29] : (spi_mode_next == P_DOUBLE) ? data_int_next[31] :  1'b0;
-          sdo2         <= (spi_mode_next == P_QUAD) ? data_int_next[30] : 1'b1; // Protect
-          sdo3         <= (spi_mode_next == P_QUAD) ? data_int_next[31] : 1'b1; // Hold need to '1'
+       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