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