From 2948100d70ab4c85222836c4ae3b4dace5a3258d Mon Sep 17 00:00:00 2001
From: Daniel Newbrook <dwn1c21@soton.ac.uk>
Date: Thu, 19 Sep 2024 16:10:20 +0100
Subject: [PATCH] APB QSPI Commands working

---
 flist/Top/ahb_QSPI_SIM.flist                  |   5 +-
 .../apb_qspi_regs/logical/apb_qspi_regs.sv    |  52 ++++-
 logical/cache_models/generic/cache_ram.v      |  97 +++++++++
 .../cache_subsytem/logical/cache_subsystem.v  |  38 ++++
 .../logical/qspi_controller.sv                | 190 ++++++++++++++++--
 logical/top_ahb_qspi/logical/top_ahb_qspi.sv  | 155 +++++++++-----
 verif/cocotb/ahb_qspi_cocotb.v                |  18 +-
 verif/cocotb/ahb_qspi_tests.py                | 105 ++++++++--
 8 files changed, 566 insertions(+), 94 deletions(-)
 create mode 100644 logical/cache_models/generic/cache_ram.v

diff --git a/flist/Top/ahb_QSPI_SIM.flist b/flist/Top/ahb_QSPI_SIM.flist
index 0f86644..bff3000 100644
--- a/flist/Top/ahb_QSPI_SIM.flist
+++ b/flist/Top/ahb_QSPI_SIM.flist
@@ -1,2 +1,5 @@
 -f $(SOCLABS_AHB_QSPI_DIR)/flist/Top/ahb_QSPI.flist 
--f $(SOCLABS_AHB_QSPI_DIR)/flist/VIP/ahb_QSPI_VIP.flist
\ No newline at end of file
+-f $(SOCLABS_AHB_QSPI_DIR)/flist/VIP/ahb_QSPI_VIP.flist
+
+$(SOCLABS_AHB_QSPI_DIR)/logical/cache_models/generic/cache_ram.v
+$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/testbench/execution_tb/verilog/p_flash_cache_f0_sp_ram.v
\ No newline at end of file
diff --git a/logical/apb_qspi_regs/logical/apb_qspi_regs.sv b/logical/apb_qspi_regs/logical/apb_qspi_regs.sv
index 42db538..e28ee78 100644
--- a/logical/apb_qspi_regs/logical/apb_qspi_regs.sv
+++ b/logical/apb_qspi_regs/logical/apb_qspi_regs.sv
@@ -12,24 +12,72 @@ module apb_qspi_regs(
     input  wire [3:0]           PSTRB,
     output reg [31:0]           PRDATA,
     output wire                 PREADY,
-    output wire                 PSLVERR
+    output wire                 PSLVERR,
+
+    output wire [7:0]           QSPI_CMD,
+    output wire                 QSPI_ENABLE,
+    input  wire                 QSPI_ENABLE_ACK,
+    output wire                 QSPI_READ,
+    output wire                 QSPI_WRITE,
+    output wire                 QSPI_ADDR_EN,
+    output wire [3:0]           QSPI_DUMMY_CYCLES,
+    output wire [3:0]           QSPI_N_RW_BYTES,
+    input  wire                 QSPI_BUSY,
+    output wire                 QSPI_QIO_MODE,
+    output wire [24:0]          QSPI_ADDR
 );   
 // Registers
+// reg  Name    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+// reg0 Control 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+//      QSPI_QIO_MODE[0]
+//
+//
+
+// reg1 Status
+
+// reg2 SPI Commands 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+//     QSPI_CMD [7:0]                                        |     |              |  | | | |----> QSPI_CMD [7:0]
+//     QSPI_ENABLE [8]                                       |     |              |  | | |---> QSPI_ENABLE [8]   
+//     QSPI_READ [9]                                         |     |              |  | |-------> QSPI_READ [9] 
+//     QSPI_WRITE [10]                                       |     |              |  |--------> QSPI_WRITE [10]
+//     QSPI_ADDR_EN[11]                                      |     |              |---------> QSPI_ADDR_EN [11]
+//     QSPI_DUMMY_CYCLES[15:12]
+//     QSPI_N_RW_BYTES [19:16]                               |<--->|---------------------> QSPI_N_RW_BYTES [18:16]
+
+
 reg [31:0] reg0;
 reg [31:0] reg1;
+reg [31:0] reg2;
+reg [31:0] reg3;
+
+
+assign QSPI_QIO_MODE = reg0[0];
 
+assign QSPI_CMD = reg2[7:0];
+assign QSPI_ENABLE = reg2[8];
+assign QSPI_READ = reg2[9];
+assign QSPI_WRITE = reg2[10];
+assign QSPI_ADDR_EN = reg2[11];
+assign QSPI_DUMMY_CYCLES = reg2[15:12];
+assign QSPI_N_RW_BYTES = reg2[19:16];
 
 always @(posedge PCLK or negedge PRESETn) begin
     if(~PRESETn) begin
         reg0 = 32'd0;
         reg1 = 32'd0;
+        reg2 = 32'd0;
     end else begin
         if(PSEL & PENABLE & PWRITE) begin
             case(PADDR)
                 10'h000: reg0 = PWDATA;
                 10'h001: reg1 = PWDATA;
+                10'h002: reg2 = PWDATA;
+                10'h003: reg3 = PWDATA;
             endcase
         end 
+        if(QSPI_ENABLE_ACK)
+            reg2[8]=1'b0;
+        reg1[0] = QSPI_BUSY;
     end
 end
 
@@ -38,6 +86,8 @@ always @(PCLK, PADDR) begin
         case(PADDR) 
             10'h000: PRDATA = reg0;
             10'h001: PRDATA = reg1;
+            10'h002: PRDATA = reg2;
+            10'h003: PRDATA = reg3;
         endcase
     end
 end
diff --git a/logical/cache_models/generic/cache_ram.v b/logical/cache_models/generic/cache_ram.v
new file mode 100644
index 0000000..25756b9
--- /dev/null
+++ b/logical/cache_models/generic/cache_ram.v
@@ -0,0 +1,97 @@
+module cache_ram #(
+    parameter ADDR_W=8
+    )(
+    input  wire                 CLK,
+    input  wire [ADDR_W-1:0]    TAG_ADDR,
+    input  wire                 TAG_WE,
+    input  wire                 TAG_RD,
+    input  wire                 TAG_CS,
+    input  wire [10:0]          TAG_WDATA,
+    output wire [10:0]          TAG_RDATA,
+
+    input  wire [ADDR_W-1:0]    CLD_ADDR,
+    input  wire                 CLD_WE,
+    input  wire [3:0]           CLD_RD,
+    input  wire [3:0]           CLD_CS,
+    input  wire [127:0]         CLD_WDATA,
+    output wire [127:0]         CLD_RDATA
+);
+
+// ----------------------------------------------------------------------------
+// RAM0 Instance for Word index 0
+// ----------------------------------------------------------------------------
+wire    cs_ram0_word0;
+assign  cs_ram0_word0   = CLD_CS[0] & (CLD_WE | CLD_RD[0]);
+
+p_flash_cache_f0_sp_ram #(.DATA_WIDTH(32), .MEMORY_DEPTH(2**(ADDR_W)), .ADDR_WIDTH(ADDR_W)) data_ram_0_word_0_i (
+    .CLK    (CLK),
+    .A      (CLD_ADDR),
+    .CEN    (~cs_ram0_word0),
+    .WEN    (~CLD_WE),
+    .Q      (CLD_RDATA[31:0]),
+    .D      (CLD_WDATA[31:0])
+);
+
+// ----------------------------------------------------------------------------
+// RAM0 Instance for Word index 1
+// ----------------------------------------------------------------------------
+wire    cs_ram0_word1;
+assign  cs_ram0_word1   = CLD_CS[1] & (CLD_WE | CLD_RD[1]);
+
+p_flash_cache_f0_sp_ram #(.DATA_WIDTH(32), .MEMORY_DEPTH(2**(ADDR_W)), .ADDR_WIDTH(ADDR_W)) data_ram_0_word_1_i (
+    .CLK    (CLK),
+    .A      (CLD_ADDR),
+    .CEN    (~cs_ram0_word1),
+    .WEN    (~CLD_WE),
+    .Q      (CLD_RDATA[63:32]),
+    .D      (CLD_WDATA[63:32])
+);
+
+// ----------------------------------------------------------------------------
+// RAM0 Instance for Word index 2
+// ----------------------------------------------------------------------------
+wire    cs_ram0_word2;
+assign  cs_ram0_word2   = CLD_CS[2] & (CLD_WE | CLD_RD[2]);
+
+p_flash_cache_f0_sp_ram #(.DATA_WIDTH(32), .MEMORY_DEPTH(2**(ADDR_W)), .ADDR_WIDTH(ADDR_W)) data_ram_0_word_2_i (
+    .CLK    (CLK),
+    .A      (CLD_ADDR),
+    .CEN    (~cs_ram0_word2),
+    .WEN    (~CLD_WE),
+    .Q      (CLD_RDATA[95:64]),
+    .D      (CLD_WDATA[95:64])
+);
+
+// ----------------------------------------------------------------------------
+// RAM0 Instance for Word index 3
+// ----------------------------------------------------------------------------
+wire    cs_ram0_word3;
+assign  cs_ram0_word3   = CLD_CS[3] & (CLD_WE | CLD_RD[3]);
+
+p_flash_cache_f0_sp_ram #(.DATA_WIDTH(32), .MEMORY_DEPTH(2**(ADDR_W)), .ADDR_WIDTH(ADDR_W)) data_ram_0_word_3_i (
+    .CLK    (CLK),
+    .A      (CLD_ADDR),
+    .CEN    (~cs_ram0_word3),
+    .WEN    (~CLD_WE),
+    .Q      (CLD_RDATA[127:96]),
+    .D      (CLD_WDATA[127:96])
+);
+
+// ----------------------------------------------------------------------------
+// TAG RAM 0 Instance
+// ----------------------------------------------------------------------------
+wire    cs_tag0;
+assign  cs_tag0         = TAG_CS & (TAG_WE | TAG_RD);
+
+p_flash_cache_f0_sp_ram #(.DATA_WIDTH(11), .MEMORY_DEPTH(2**(ADDR_W)), .ADDR_WIDTH(ADDR_W)) tag_ram_0_i (
+    .CLK    (CLK),
+    .A      (TAG_ADDR),
+    .CEN    (~cs_tag0),
+    .WEN    (~TAG_WE),
+    .Q      (TAG_RDATA),
+    .D      (TAG_WDATA)
+);
+
+
+
+endmodule
\ No newline at end of file
diff --git a/logical/cache_subsytem/logical/cache_subsystem.v b/logical/cache_subsytem/logical/cache_subsystem.v
index a2fa972..3355621 100644
--- a/logical/cache_subsytem/logical/cache_subsystem.v
+++ b/logical/cache_subsytem/logical/cache_subsystem.v
@@ -170,5 +170,43 @@ p_flash_cache_f0 #(
         .CACHEHIT(CACHEHIT)
 );
 
+cache_ram #(
+    .ADDR_W(8)
+) u_way0_cache_ram (
+    .CLK(HCLK),
+    .TAG_ADDR(RAMTAG0ADDR),
+    .TAG_WE(RAMTAG0WE),
+    .TAG_RD(RAMTAG0RD),
+    .TAG_CS(RAMTAG0CS),
+    .TAG_WDATA(RAMTAG0WDATA),
+    .TAG_RDATA(RAMTAG0RDATA),
+
+    .CLD_ADDR(RAMCLD0ADDR),
+    .CLD_WE(RAMCLD0WE),
+    .CLD_RD(RAMCLD0RD),
+    .CLD_CS(RAMCLD0CS),
+    .CLD_WDATA(RAMCLD0WDATA),
+    .CLD_RDATA(RAMCLD0RDATA)
+);
+
+cache_ram #(
+    .ADDR_W(8)
+) u_way1_cache_ram (
+    .CLK(HCLK),
+    .TAG_ADDR(RAMTAG1ADDR),
+    .TAG_WE(RAMTAG1WE),
+    .TAG_RD(RAMTAG1RD),
+    .TAG_CS(RAMTAG1CS),
+    .TAG_WDATA(RAMTAG1WDATA),
+    .TAG_RDATA(RAMTAG1RDATA),
+
+    .CLD_ADDR(RAMCLD1ADDR),
+    .CLD_WE(RAMCLD1WE),
+    .CLD_RD(RAMCLD1RD),
+    .CLD_CS(RAMCLD1CS),
+    .CLD_WDATA(RAMCLD1WDATA),
+    .CLD_RDATA(RAMCLD1RDATA)
+);
+
 
 endmodule
\ No newline at end of file
diff --git a/logical/qspi_controller/logical/qspi_controller.sv b/logical/qspi_controller/logical/qspi_controller.sv
index d435d5c..23035c8 100644
--- a/logical/qspi_controller/logical/qspi_controller.sv
+++ b/logical/qspi_controller/logical/qspi_controller.sv
@@ -5,42 +5,204 @@ module qspi_controller (
 
     input  wire [7:0]   QSPI_CLK_DIV,
     input  wire [1:0]   QSPI_SPI_MODE, // {CPOL, CPHA} 
-
+    
     input  wire [7:0]   QSPI_CMD,
+    input  wire         QSPI_ENABLE,
+    output reg          QSPI_ENABLE_ACK,
+    input  wire         QSPI_READ,
+    input  wire         QSPI_WRITE,
+    input  wire         QSPI_ADDR_EN,
+    input  wire [3:0]   QSPI_DUMMY_CYCLES,
+    input  wire [3:0]   QSPI_N_RW_BYTES,
     input  wire [23:0]  QSPI_ADDR,
     input  wire [31:0]  QSPI_WDATA,
     output wire [31:0]  QSPI_RDATA,
+    input  wire         QSPI_QIO_MODE,
 
     // QSPI Interface
-    output wire         QSPI_SCLK
+    output wire         QSPI_SCLK,
+    output wire         QSPI_nCS,
+    output wire [3:0]   QSPI_IO_o,
+    input  wire [3:0]   QSPI_IO_i,
+    output wire [3:0]   QSPI_IO_e
 );
 
 reg [7:0] QSPI_CLK_DIV_COUNTER;
-wire QSPI_ACTIVE;
 reg     QSPI_SCLK_reg;
-assign QSPI_ACTIVE = 1'b1;
+wire    QSPI_SCLK_i;
+reg     QSPI_SCLK_e;
+
+assign QSPI_SCLK_i = (QSPI_CLK_DIV==8'h00) ? HCLK : QSPI_SCLK_reg;
+assign QSPI_SCLK = (QSPI_SCLK_e==1'b1) ? QSPI_SCLK_i : QSPI_SPI_MODE[1];
 
-assign QSPI_SCLK = (QSPI_CLK_DIV==8'h00) ? HCLK : QSPI_SCLK_reg;
 // Clock Divider for SCLK
 always @(posedge HCLK or negedge HRESETn) begin
     if(~HRESETn) begin
         QSPI_CLK_DIV_COUNTER<=8'h00;
         QSPI_SCLK_reg <= 1'b0;
     end else begin 
-        if(QSPI_ACTIVE) begin 
-            if(QSPI_CLK_DIV!=8'h00) begin 
-                if(QSPI_CLK_DIV_COUNTER==QSPI_CLK_DIV-1'b1) begin 
-                    QSPI_CLK_DIV_COUNTER <= 8'h00;
-                end else begin 
-                    QSPI_SCLK_reg <= ~QSPI_SCLK_reg;
-                    QSPI_CLK_DIV_COUNTER <= QSPI_CLK_DIV_COUNTER + 1'b1;
-                end
+        if(QSPI_CLK_DIV!=8'h00) begin 
+            if(QSPI_CLK_DIV_COUNTER==QSPI_CLK_DIV-1'b1) begin 
+                QSPI_CLK_DIV_COUNTER <= 8'h00;
             end else begin 
-                QSPI_SCLK_reg <= QSPI_SPI_MODE[1];
+                QSPI_SCLK_reg <= ~QSPI_SCLK_reg;
+                QSPI_CLK_DIV_COUNTER <= QSPI_CLK_DIV_COUNTER + 1'b1;
             end
         end else begin 
             QSPI_SCLK_reg <= QSPI_SPI_MODE[1];
         end
     end
 end
+
+enum {IDLE, OP, ADDR, DUMMY, DATA_O, DATA_I} current_state, next_state;
+
+reg [2:0] op_counter;
+reg [7:0] data_counter;
+reg [3:0] dummy_counter;
+reg [4:0] byte_counter;
+reg [7:0] op_code;
+reg [3:0] QSPI_IO_o_reg;
+reg [7:0] data_in_reg;
+assign QSPI_IO_o = QSPI_IO_o_reg;
+
+always @(posedge QSPI_SCLK_i or negedge HRESETn) begin
+    if(~HRESETn) begin 
+        current_state <= IDLE;
+    end else begin 
+        current_state <= next_state;
+    end
+end 
+
+always @(*) begin 
+    case(current_state)
+        IDLE: begin
+            if(QSPI_ENABLE) begin
+                next_state = OP;
+            end else begin
+                next_state = IDLE;
+                QSPI_ENABLE_ACK = 1'b0;
+            end 
+            //op_counter=3'h0; 
+        end
+        OP: begin
+            QSPI_ENABLE_ACK = 1'b1;
+            if(QSPI_QIO_MODE==1'b1 & op_counter==3'h1) begin
+                QSPI_ENABLE_ACK = 1'b0;
+                if(QSPI_ADDR_EN)
+                    next_state = ADDR;
+                else if(QSPI_DUMMY_CYCLES>4'h0)
+                    next_state = DUMMY;
+                else if(QSPI_READ)
+                    next_state = DATA_I;
+                else if(QSPI_WRITE)
+                    next_state = DATA_O;
+                else
+                    next_state = IDLE;
+            end
+            else if(QSPI_QIO_MODE==1'b0 & op_counter==3'h7) begin
+                QSPI_ENABLE_ACK = 1'b0;
+                if(QSPI_ADDR_EN)
+                    next_state = ADDR;
+                else if(QSPI_DUMMY_CYCLES>4'h0)
+                    next_state = DUMMY;
+                else if(QSPI_READ)
+                    next_state = DATA_I;
+                else if(QSPI_WRITE)
+                    next_state = DATA_O;
+                else
+                    next_state = IDLE;
+            end
+        end     
+        ADDR: begin
+            
+        end 
+        DUMMY: begin
+            if(dummy_counter >= QSPI_DUMMY_CYCLES - 1'b1) begin
+                if(QSPI_WRITE)
+                    next_state = DATA_O;
+                else if(QSPI_READ)
+                    next_state = DATA_I;
+                else
+                    next_state = IDLE;
+            end 
+        end 
+        DATA_O: begin
+            
+        end 
+        DATA_I: begin 
+            if(byte_counter==QSPI_N_RW_BYTES+1'b1) begin
+                next_state = IDLE;
+            end
+        end
+    endcase
+end
+
+reg QSPI_IO_e_int;
+
+always @(negedge QSPI_SCLK_i) begin
+    if(current_state==OP) begin 
+        QSPI_IO_e_int <= 1'b1;
+        QSPI_SCLK_e <= 1'b1;
+        if(QSPI_QIO_MODE==1'b1) begin
+            QSPI_IO_o_reg[3:0]<=op_code[7:4];
+            op_code[7:0] <= {op_code[3:0],4'h0};
+        end else begin
+            QSPI_IO_o_reg[3:0]<={3'h7, op_code[7]};
+            op_code[7:0] <= {op_code[6:0], 1'b0};
+        end
+    end else if(current_state == DATA_I) begin
+        QSPI_IO_e_int <= 1'b0;
+        QSPI_SCLK_e <= 1'b1;
+    end else if(current_state == DUMMY) begin 
+        QSPI_IO_e_int <= 1'b1;
+        QSPI_SCLK_e <= 1'b1;
+    end else begin 
+        op_code <= QSPI_CMD;
+        QSPI_SCLK_e<=1'b0;
+        QSPI_IO_o_reg<=4'hF;
+        QSPI_IO_e_int <= 1'b1;
+    end
+end
+always @(posedge QSPI_SCLK_i) begin 
+    if(current_state==OP) begin 
+        op_counter<=op_counter+1'b1;
+    end else begin 
+        op_counter <= 3'h0;
+    end
+    if(current_state==DATA_I || current_state ==DATA_O) begin
+        data_counter <= data_counter + 1'b1;
+        if(QSPI_QIO_MODE==1'b0 && data_counter == 3'h7) begin 
+            byte_counter <= byte_counter+1'b1;
+            data_counter <= 3'h0;
+        end else if (QSPI_QIO_MODE==1'b1 && data_counter == 3'h1) begin
+            byte_counter <= byte_counter+1'b1;
+            data_counter <= 3'h0;
+        end
+    end else begin 
+        data_counter <= 3'h0;
+        byte_counter <= 4'h0;
+    end
+    if(current_state == DATA_I) begin
+        if(QSPI_QIO_MODE==1'b1) begin 
+            data_in_reg <= {data_in_reg[3:0], QSPI_IO_i};
+        end else begin 
+            data_in_reg <= {data_in_reg[6:0],QSPI_IO_i[1]};
+        end
+    end
+
+    if(current_state == DUMMY) begin 
+        dummy_counter <= dummy_counter + 1'b1;
+    end else begin 
+        dummy_counter <= 4'h0;
+    end
+
+end
+
+assign QSPI_nCS = ((QSPI_ENABLE==1'b1) ||(current_state!=IDLE) || (QSPI_SCLK_e==1'b1))?1'b0:1'b1;
+//assign QSPI_SCLK_e = (current_state!=IDLE)?1'b1:1'b0;w
+
+assign QSPI_IO_e[3] = (QSPI_QIO_MODE==1'b1)?QSPI_IO_e_int:1'b1;
+assign QSPI_IO_e[2] = (QSPI_QIO_MODE==1'b1)?QSPI_IO_e_int:1'b1;
+assign QSPI_IO_e[1] = (QSPI_QIO_MODE==1'b1)?QSPI_IO_e_int:1'b0;
+assign QSPI_IO_e[0] = (QSPI_QIO_MODE==1'b1)?QSPI_IO_e_int:1'b1;
 endmodule
\ No newline at end of file
diff --git a/logical/top_ahb_qspi/logical/top_ahb_qspi.sv b/logical/top_ahb_qspi/logical/top_ahb_qspi.sv
index a444a6f..366df55 100644
--- a/logical/top_ahb_qspi/logical/top_ahb_qspi.sv
+++ b/logical/top_ahb_qspi/logical/top_ahb_qspi.sv
@@ -43,15 +43,31 @@ module top_ahb_qspi #(
 );
 
 
-wire             qspi_psel;
-wire     [31:0]  qspi_prdata;
-wire             qspi_pready;
-wire             qspi_pslverr;
-
-wire             cache_psel;
-wire     [31:0]  cache_prdata;
-wire             cache_pready;
-wire             cache_pslverr;
+wire            qspi_psel;
+wire     [31:0] qspi_prdata;
+wire            qspi_pready;
+wire            qspi_pslverr;
+
+wire            cache_psel;
+wire     [31:0] cache_prdata;
+wire            cache_pready;
+wire            cache_pslverr;
+
+
+  // AHB Outputs 
+wire            flash_HSELM;        // Device select
+wire [21:0]     flash_HADDRM;       // Address
+wire [2:0]      flash_HBURSTM;      // Burst Type - Not used (tied to 0)!
+wire            flash_HMASTLOCKM;   // Master Lock - Not used (tied to 0)!
+wire [1:0]      flash_HTRANSM;      // Transfer control
+wire [2:0]      flash_HSIZEM;       // Transfer size
+wire [3:0]      flash_HPROTM;       // Transfer Protection
+wire            flash_HWRITEM;      // Write control
+wire [127:0]    flash_HWDATAM;      // Write data
+wire            flash_HREADYM;      // Transfer phase done
+wire            flash_HREADYOUTM;   // Device ready
+wire [127:0]    flash_HRDATAM;      // Read data output
+wire            flash_HRESPM;       // Error response
 
 
 cmsdk_apb_slave_mux #(
@@ -109,40 +125,50 @@ cache_subsystem u_cache_subsystem(
     .PSLVERR(cache_pslverr),
     .PREADY(cache_pready),
 
-    .HSELS(),
-    .HADDRS(),
-    .HBURSTS(),
+    .HSELS(HSELx),
+    .HADDRS(HADDR[21:0]),
+    .HBURSTS(HBURST),
     .HMASTLOCKS(),
-    .HTRANSS(),
-    .HSIZES(),
-    .HPROTS(),
-    .HWRITES(),
-    .HWDATAS(),
-    .HREADYS(),
+    .HTRANSS(HTRANS),
+    .HSIZES(HSIZE),
+    .HPROTS(HPROT),
+    .HWRITES(HWRITE),
+    .HWDATAS(HWDATA),
+    .HREADYS(HREADY),
     .HMASTERS(),
-    .HREADYOUTS(),
-    .HRDATAS(),
-    .HRESPS(),
-
-    .HSELM(),
-    .HADDRM(),
-    .HBURSTM(),
-    .HMASTLOCKM(),
-    .HTRANSM(),
-    .HSIZEM(),
-    .HPROTM(),
-    .HWRITEM(),
-    .HWDATAM(),
-    .HREADYM(),
-    .HREADYOUTM(),
-    .HRDATAM(),
-    .HRESPM(),
+    .HREADYOUTS(HREADYOUT),
+    .HRDATAS(HRDATA),
+    .HRESPS(HRESP),
+
+    .HSELM(flash_HSELM),
+    .HADDRM(flash_HADDRM),
+    .HBURSTM(flash_HBURSTM),
+    .HMASTLOCKM(flash_HMASTLOCKM),
+    .HTRANSM(flash_HTRANSM),
+    .HSIZEM(flash_HSIZEM),
+    .HPROTM(flash_HPROTM),
+    .HWRITEM(flash_HWRITEM),
+    .HWDATAM(flash_HWDATAM),
+    .HREADYM(flash_HREADYM),
+    .HREADYOUTM(flash_HREADYOUTM),
+    .HRDATAM(flash_HRDATAM),
+    .HRESPM(flash_HRESPM),
 
     .IRQ(),
     .CACHEMISS(),
     .CACHEHIT()
 );
 
+wire [7:0]  QSPI_CMD;
+wire        QSPI_ENABLE;
+wire        QSPI_ENABLE_ACK;
+wire        QSPI_READ;
+wire        QSPI_WRITE;
+wire        QSPI_ADDR_EN;
+wire [3:0]  QSPI_N_RW_BYTES;
+wire        QSPI_QIO_MODE;
+wire [3:0]  QSPI_DUMMY_CYCLES;
+
 apb_qspi_regs u_apb_qspi_regs(
     .PCLK(PCLK),
     .PRESETn(PRESETn),
@@ -155,39 +181,62 @@ apb_qspi_regs u_apb_qspi_regs(
     .PSTRB(PSTRB),
     .PRDATA(qspi_prdata),
     .PREADY(qspi_pready),
-    .PSLVERR(qspi_pslverr)
+    .PSLVERR(qspi_pslverr),
+
+    .QSPI_CMD(QSPI_CMD),
+    .QSPI_ENABLE(QSPI_ENABLE),
+    .QSPI_ENABLE_ACK(QSPI_ENABLE_ACK),
+    .QSPI_READ(QSPI_READ),
+    .QSPI_WRITE(QSPI_WRITE),
+    .QSPI_ADDR_EN(QSPI_ADDR_EN),
+    .QSPI_DUMMY_CYCLES(QSPI_DUMMY_CYCLES),
+    .QSPI_N_RW_BYTES(QSPI_N_RW_BYTES),
+    .QSPI_BUSY(~QSPI_nCS),
+    .QSPI_QIO_MODE(QSPI_QIO_MODE)
 );
 
 ahb_qspi_interface #(
-    .ADDR_W(ADDR_W),
-    .DATA_W(DATA_W)
+    .ADDR_W(22),
+    .DATA_W(128)
     ) u_ahb_qspi_interface (
         .HCLK(HCLK),
         .HRESETn(HRESETn),
-        .HADDR(HADDR),
-        .HTRANS(HTRANS),
-        .HWRITE(HWRITE),
-        .HSIZE(HSIZE),
-        .HBURST(HBURST),
-        .HPROT(HPROT),
-        .HWDATA(HWDATA),
-        .HSELx(HSELx),
-        .HRDATA(HRDATA),
-        .HREADY(HREADY),
-        .HREADYOUT(HREADYOUT),
-        .HRESP(HRESP)
+        .HADDR(flash_HADDRM),
+        .HTRANS(flash_HTRANSM),
+        .HWRITE(flash_HWRITEM),
+        .HSIZE(flash_HSIZEM),
+        .HBURST(flash_HBURSTM),
+        .HPROT(flash_HPROTM),
+        .HWDATA(flash_HWDATAM),
+        .HSELx(flash_HSELM),
+        .HRDATA(flash_HRDATAM),
+        .HREADY(flash_HREADYM),
+        .HREADYOUT(flash_HREADYOUTM),
+        .HRESP(flash_HRESPM)
 );
 
 qspi_controller u_qspi_controller(
     .HCLK(HCLK),
     .HRESETn(HRESETn),
     .QSPI_CLK_DIV(8'h02),
-    .QSPI_SPI_MODE(2'b11),
-    .QSPI_CMD(),
+    .QSPI_SPI_MODE(2'b00),
+    .QSPI_CMD(QSPI_CMD),
+    .QSPI_ENABLE(QSPI_ENABLE),
+    .QSPI_ENABLE_ACK(QSPI_ENABLE_ACK),
+    .QSPI_READ(QSPI_READ),
+    .QSPI_WRITE(QSPI_WRITE),
+    .QSPI_ADDR_EN(QSPI_ADDR_EN),
+    .QSPI_DUMMY_CYCLES(QSPI_DUMMY_CYCLES),
+    .QSPI_N_RW_BYTES(QSPI_N_RW_BYTES),
+    .QSPI_QIO_MODE(QSPI_QIO_MODE),
     .QSPI_ADDR(),
     .QSPI_WDATA(),
     .QSPI_RDATA(),
 
-    .QSPI_SCLK(QSPI_SCLK)
+    .QSPI_SCLK(QSPI_SCLK),
+    .QSPI_nCS(QSPI_nCS),
+    .QSPI_IO_o(QSPI_IO_o),
+    .QSPI_IO_i(QSPI_IO_i),
+    .QSPI_IO_e(QSPI_IO_e)
 );
 endmodule
\ No newline at end of file
diff --git a/verif/cocotb/ahb_qspi_cocotb.v b/verif/cocotb/ahb_qspi_cocotb.v
index e79d67e..30a8796 100644
--- a/verif/cocotb/ahb_qspi_cocotb.v
+++ b/verif/cocotb/ahb_qspi_cocotb.v
@@ -138,18 +138,18 @@ assign QSPI_IO_i[1] = QSPI_IO[1];
 assign QSPI_IO_i[2] = QSPI_IO[2];
 assign QSPI_IO_i[3] = QSPI_IO[3];
 
-sst26wfxxxb u_sst26wfxxxb(
+sst26wf040b u_sst26wfxxxb(
     .SCK(QSPI_SCLK),
     .SIO(QSPI_IO),
     .CEb(QSPI_nCS)
 );
-
-defparam u_sst26wfxxxb.Ksize = 4096;
-defparam u_sst26wfxxxb.Msize = 4;
-defparam u_sst26wfxxxb.ADDR_MSB = 21;
-defparam u_sst26wfxxxb.Memory_Capacity = 8'h52;
-defparam u_sst26wfxxxb.WLLD_value = 24'h00_0000;
-defparam u_sst26wfxxxb.INIT_WPEN = 1'b0;
-defparam u_sst26wfxxxb.SECURITY_LOCKOUT_VALUE = 1'b0;
+	//defparam u_sst26wfxxxb.IO.Ksize = 512;  //Size of memory in Kilo bytes
+	//defparam u_sst26wfxxxb.I0.Msize = 0;				// Size of memory in Mega bites. I.E. 8-bit field size, use S080=1, S016=2, S032=4
+	//defparam u_sst26wfxxxb.I0.ADDR_MSB=18;			// most significant address bit, 32Mb=21,16Mb=20, 8Mb=19, 4Mb=18;
+	//defparam u_sst26wfxxxb.I0.Memory_Capacity = 8'h54;		// ID read memory size 32M=52,16M=51,8M=58, JEDEC read value
+	//// change below values if you need non-default values on POR
+	//defparam u_sst26wfxxxb.I0.WLLD_value = 24'h00_0000;	// init WLLD protection register non-volitale, default to all 0's
+	//defparam u_sst26wfxxxb.I0.INIT_WPEN = 1'b0;			// value of WPEN, configuration register bit 7 default on POR
+	//defparam u_sst26wfxxxb.I0.SECURITY_LOCKOUT_VALUE=1'b0;	// Value of SEC, status register bit 5 on POR
 
 endmodule 
\ No newline at end of file
diff --git a/verif/cocotb/ahb_qspi_tests.py b/verif/cocotb/ahb_qspi_tests.py
index a738dc2..a95f4d8 100644
--- a/verif/cocotb/ahb_qspi_tests.py
+++ b/verif/cocotb/ahb_qspi_tests.py
@@ -32,21 +32,6 @@ class TB:
         self.dut.HRESETn.setimmediatevalue(1)
         await ClockCycles(self.dut.HCLK,10)
             
-@cocotb.test()
-async def AHB_QSPI_1(dut):
-    tb = TB(dut)
-    await tb.cycle_reset()
-    
-    await tb.config_ahb_master.write(0x00,0xBEEFBEEF)
-    await tb.config_ahb_master.write(0x04,0xCAFECAFE)
-    await ClockCycles(dut.HCLK,2)
-    data = await tb.config_ahb_master.read(0x00,4)
-    await ClockCycles(dut.HCLK,2)
-    print(data)
-    data = await tb.config_ahb_master.read(0x00,4)
-    print(data)
-    data = await tb.config_ahb_master.read(0x04,4)
-    assert int(data[0]['data'],16) == 0xcafecafe
 
 @cocotb.test()
 async def CACHE_CONFIG(dut):
@@ -56,4 +41,92 @@ async def CACHE_CONFIG(dut):
     # After reset CCR register should = 0x40
     assert int(data[0]['data'],16) == 0x40
     data = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR+0x20,4)
-    print(data)
\ No newline at end of file
+    print(data)
+    
+async def SPI_RESET(dut,tb):
+    await tb.config_ahb_master.write(0x08, 0x00000066)
+    await tb.config_ahb_master.write(0x08, 0x00000166)
+
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+    
+    await tb.config_ahb_master.write(0x08, 0x00000099)
+    await tb.config_ahb_master.write(0x08, 0x00000199)
+    
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+            
+async def SPI_READ_JEDIC(dut, tb):
+    await tb.config_ahb_master.write(0x08, 0x0002009F)
+    await tb.config_ahb_master.write(0x08, 0x0002039F)
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,10)
+        data = await tb.config_ahb_master.read(0x04,4)
+
+async def SET_QPI_MODE(dut,tb):
+    await tb.config_ahb_master.write(0x08, 0x00000038)
+    await tb.config_ahb_master.write(0x08, 0x00000138)
+
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+
+async def QPI_READ_JEDIC(dut, tb):
+    await tb.config_ahb_master.write(0x08, 0x000210AF)
+    await tb.config_ahb_master.write(0x08, 0x000213AF)
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,10)
+        data = await tb.config_ahb_master.read(0x04,4)
+        
+async def SPI_WRITE_ENABLE(dut, tb):
+    await tb.config_ahb_master.write(0x08, 0x00000006)
+    await tb.config_ahb_master.write(0x08, 0x00000106)
+
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+        
+async def SPI_CLR_PROTECTION(dut, tb):
+    await tb.config_ahb_master.write(0x08, 0x00000098)
+    await tb.config_ahb_master.write(0x08, 0x00000198)
+
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+   
+
+async def SPI_BLOCK_ERASE(dut, tb):
+    await tb.config_ahb_master.write(0x08, 0x000008D8)
+    await tb.config_ahb_master.write(0x08, 0x000009D8)
+
+    data = await tb.config_ahb_master.read(0x04,4)
+    while(int(data[0]['data'],16)&1):
+        await ClockCycles(dut.HCLK,2)
+        data = await tb.config_ahb_master.read(0x04,4)
+   
+
+
+@cocotb.test()
+async def QSPI_TESTS(dut):  
+    tb = TB(dut)
+    await tb.cycle_reset()
+    await SPI_RESET(dut, tb)
+    await SPI_READ_JEDIC(dut, tb)
+    await SET_QPI_MODE(dut, tb)
+    await tb.config_ahb_master.write(0x00,0x1)
+    await QPI_READ_JEDIC(dut, tb)
+    await SPI_WRITE_ENABLE(dut, tb)
+    await SPI_CLR_PROTECTION(dut, tb)
+    await SPI_CHIP_ERASE(dut, tb)
+
+    
+    
\ No newline at end of file
-- 
GitLab