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