From 4cf04f6b9622e8cbf70fc36626daa5be62d5ca50 Mon Sep 17 00:00:00 2001 From: dwn1c21 <dwn1c21@soton.ac.uk> Date: Fri, 20 Sep 2024 17:16:51 +0100 Subject: [PATCH] QSPI BE working, read/write initial NW --- .gitignore | 2 +- flist/IP/CG092_cache.flist | 5 +- flist/VIP/ahb_QSPI_VIP.flist | 2 +- .../apb_qspi_regs/logical/apb_qspi_regs.sv | 58 +++++-- .../logical/qspi_controller.sv | 148 ++++++++++++++++-- logical/top_ahb_qspi/logical/top_ahb_qspi.sv | 36 +++-- makefile | 4 +- verif/cocotb/ahb_qspi_cocotb.v | 10 +- verif/cocotb/ahb_qspi_tests.py | 102 +++++++++++- verif/cocotb/makefile | 3 +- 10 files changed, 310 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 956a776..02d8c92 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ verif/cocotb/transcript verif/cocotb/sim_build/ verif/cocotb/__pycache__/ -verif/VIP/sst26wf040b.v +verif/VIP/SST26VF064B.v diff --git a/flist/IP/CG092_cache.flist b/flist/IP/CG092_cache.flist index 263c6ef..506a61e 100644 --- a/flist/IP/CG092_cache.flist +++ b/flist/IP/CG092_cache.flist @@ -2,7 +2,6 @@ // ============= Verilog library extensions =========== +libext+.v+.vlib -+incdir+$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/p_flash_cache_f0_bus_logic.v $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/p_flash_cache_f0_mrb.v @@ -10,8 +9,8 @@ $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/p_flash_cache_f0.v $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/p_flash_cache_f0_reg_block.v -/$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/cells/generic/p_flash_cache_f0_capt_sync.v -/$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/cells/generic/cdc_capt_sync.v +$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/cells/generic/p_flash_cache_f0_capt_sync.v +$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/cells/generic/cdc_capt_sync.v $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/modules/generic/p_flash_cache_f0_static_reg.v $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/models/modules/generic/static_reg.v diff --git a/flist/VIP/ahb_QSPI_VIP.flist b/flist/VIP/ahb_QSPI_VIP.flist index bcfee8f..24f202e 100644 --- a/flist/VIP/ahb_QSPI_VIP.flist +++ b/flist/VIP/ahb_QSPI_VIP.flist @@ -1,3 +1,3 @@ $(ARM_IP_LIBRARY_PATH)/latest/Corstone-101/logical/cmsdk_ahb_to_apb/verilog/cmsdk_ahb_to_apb.v -$(SOCLABS_AHB_QSPI_DIR)/verif/VIP/sst26wf040b.v \ No newline at end of file +$(SOCLABS_AHB_QSPI_DIR)/verif/VIP/SST26VF064B.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 e28ee78..4fe8d8c 100644 --- a/logical/apb_qspi_regs/logical/apb_qspi_regs.sv +++ b/logical/apb_qspi_regs/logical/apb_qspi_regs.sv @@ -24,34 +24,46 @@ module apb_qspi_regs( output wire [3:0] QSPI_N_RW_BYTES, input wire QSPI_BUSY, output wire QSPI_QIO_MODE, - output wire [24:0] QSPI_ADDR + output wire [21:0] QSPI_ADDR, + input wire [127:0] QSPI_RDATA, + output wire [127:0] QSPI_WDATA, + output wire XIP_ACTIVE ); // 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] -// +// QSPI_QIO_MODE[0] | |--> QSPI_QIO_MODE [0] +// XIP_ACTIVE [8] |------------------> XIP_ACTIVE [8] // // 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] +// 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_DUMMY_CYCLES [15:12] +// QSPI_N_RW_BYTES [19:16] | |<------>|---------------------> QSPI_N_RW_BYTES [19:16] + +// reg3 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_ADDR [21:0] |<-------------------------------------------------->|-> QSPI_ADDR [21:0] + reg [31:0] reg0; reg [31:0] reg1; reg [31:0] reg2; reg [31:0] reg3; +// reg 4-7 not used as directly from SPI +reg [31:0] reg8; +reg [31:0] reg9; +reg [31:0] reg10; +reg [31:0] reg11; assign QSPI_QIO_MODE = reg0[0]; +assign XIP_ACTIVE = reg0[8]; assign QSPI_CMD = reg2[7:0]; assign QSPI_ENABLE = reg2[8]; @@ -61,11 +73,23 @@ assign QSPI_ADDR_EN = reg2[11]; assign QSPI_DUMMY_CYCLES = reg2[15:12]; assign QSPI_N_RW_BYTES = reg2[19:16]; +assign QSPI_ADDR = reg3[21:0]; + +assign QSPI_WDATA[31:0] = {reg8[27:24],reg8[31:28],reg8[19:16],reg8[23:20],reg8[11:8],reg8[15:12],reg8[3:0],reg8[7:4]}; +assign QSPI_WDATA[63:32] = {reg9[27:24],reg9[31:28],reg9[19:16],reg9[23:20],reg9[11:8],reg9[15:12],reg9[3:0],reg9[7:4]}; +assign QSPI_WDATA[95:64] = {reg10[27:24],reg10[31:28],reg10[19:16],reg10[23:20],reg10[11:8],reg10[15:12],reg10[3:0],reg10[7:4]}; +assign QSPI_WDATA[127:96] = {reg11[27:24],reg11[31:28],reg11[19:16],reg11[23:20],reg11[11:8],reg11[15:12],reg11[3:0],reg11[7:4]}; + always @(posedge PCLK or negedge PRESETn) begin if(~PRESETn) begin reg0 = 32'd0; reg1 = 32'd0; reg2 = 32'd0; + reg3 = 32'd0; + reg8 = 32'd0; + reg9 = 32'd0; + reg10 = 32'd0; + reg11 = 32'd0; end else begin if(PSEL & PENABLE & PWRITE) begin case(PADDR) @@ -73,6 +97,10 @@ always @(posedge PCLK or negedge PRESETn) begin 10'h001: reg1 = PWDATA; 10'h002: reg2 = PWDATA; 10'h003: reg3 = PWDATA; + 10'h008: reg8 = PWDATA; + 10'h009: reg9 = PWDATA; + 10'h00A: reg10 = PWDATA; + 10'h00B: reg11 = PWDATA; endcase end if(QSPI_ENABLE_ACK) @@ -88,6 +116,14 @@ always @(PCLK, PADDR) begin 10'h001: PRDATA = reg1; 10'h002: PRDATA = reg2; 10'h003: PRDATA = reg3; + 10'h004: PRDATA = QSPI_RDATA[31:0]; + 10'h005: PRDATA = QSPI_RDATA[63:32]; + 10'h006: PRDATA = QSPI_RDATA[95:64]; + 10'h007: PRDATA = QSPI_RDATA[127:96]; + 10'h008: PRDATA = reg8; + 10'h009: PRDATA = reg9; + 10'h00A: PRDATA = reg10; + 10'h00B: PRDATA = reg11; endcase end end diff --git a/logical/qspi_controller/logical/qspi_controller.sv b/logical/qspi_controller/logical/qspi_controller.sv index 23035c8..e94c0e0 100644 --- a/logical/qspi_controller/logical/qspi_controller.sv +++ b/logical/qspi_controller/logical/qspi_controller.sv @@ -14,9 +14,9 @@ module qspi_controller ( 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 [21:0] QSPI_ADDR, + input wire [127:0] QSPI_WDATA, + output reg [127:0] QSPI_RDATA, input wire QSPI_QIO_MODE, // QSPI Interface @@ -25,6 +25,7 @@ module qspi_controller ( 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; @@ -56,13 +57,17 @@ 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; +reg [2:0] op_counter; +reg [4:0] addr_counter; +reg [2:0] data_counter; +reg [3:0] dummy_counter; +reg [4:0] byte_counter; +reg [7:0] op_code; +reg [23:0] addr_code; +reg [3:0] QSPI_IO_o_reg; +reg [127:0] data_in_reg; +reg [127:0] QSPI_WDATA_reg; + assign QSPI_IO_o = QSPI_IO_o_reg; always @(posedge QSPI_SCLK_i or negedge HRESETn) begin @@ -114,7 +119,26 @@ always @(*) begin end end ADDR: begin - + if(QSPI_QIO_MODE==1'b1 & addr_counter==3'h5) begin + 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 & addr_counter==3'h21) begin + 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 DUMMY: begin if(dummy_counter >= QSPI_DUMMY_CYCLES - 1'b1) begin @@ -127,11 +151,26 @@ always @(*) begin end end DATA_O: begin - + if(QSPI_QIO_MODE==1'b0) begin + + end else begin + if(byte_counter==QSPI_N_RW_BYTES) begin + if(data_counter==3'h1) + next_state = IDLE; + end + end end DATA_I: begin - if(byte_counter==QSPI_N_RW_BYTES+1'b1) begin - next_state = IDLE; + if(QSPI_QIO_MODE==1'b0) begin + if((byte_counter==QSPI_N_RW_BYTES+1'b1)) begin + if(data_counter==3'h6) + next_state = IDLE; + end + end else begin + if((byte_counter==QSPI_N_RW_BYTES)) begin + if(data_counter==3'h1) + next_state = IDLE; + end end end endcase @@ -153,11 +192,26 @@ always @(negedge QSPI_SCLK_i) begin end else if(current_state == DATA_I) begin QSPI_IO_e_int <= 1'b0; QSPI_SCLK_e <= 1'b1; + end else if(current_state == DATA_O) begin + QSPI_IO_e_int <= 1'b1; + QSPI_SCLK_e <= 1'b1; + end else if(current_state == ADDR) 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]<=addr_code[23:20]; + addr_code[23:0] <= {addr_code[19:0],4'h0}; + end else begin + QSPI_IO_o_reg[3:0]<={3'h7, addr_code[23]}; + addr_code[23:0] <= {addr_code[22:0], 1'b0}; + end + 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; + addr_code <= {2'b00,QSPI_ADDR}; QSPI_SCLK_e<=1'b0; QSPI_IO_o_reg<=4'hF; QSPI_IO_e_int <= 1'b1; @@ -165,6 +219,7 @@ always @(negedge QSPI_SCLK_i) begin end always @(posedge QSPI_SCLK_i) begin if(current_state==OP) begin + data_in_reg <= 128'd0; op_counter<=op_counter+1'b1; end else begin op_counter <= 3'h0; @@ -179,15 +234,26 @@ always @(posedge QSPI_SCLK_i) begin data_counter <= 3'h0; end end else begin - data_counter <= 3'h0; + data_counter <= 3'h7; 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}; + data_in_reg <= {data_in_reg[124:0], QSPI_IO_i}; + end else begin + data_in_reg <= {data_in_reg[126:0],QSPI_IO_i[1]}; + end + end + if(current_state == DATA_O) begin + if(QSPI_QIO_MODE==1'b1) begin + QSPI_IO_o_reg <= QSPI_WDATA_reg[3:0]; + QSPI_WDATA_reg <= {4'h0, QSPI_WDATA_reg[127:4]}; end else begin - data_in_reg <= {data_in_reg[6:0],QSPI_IO_i[1]}; + QSPI_IO_o_reg[0] <= QSPI_WDATA_reg[0]; + QSPI_WDATA_reg <= {1'b0, QSPI_WDATA_reg[127:1]}; end + end else begin + QSPI_WDATA_reg <= QSPI_WDATA; end if(current_state == DUMMY) begin @@ -196,6 +262,54 @@ always @(posedge QSPI_SCLK_i) begin dummy_counter <= 4'h0; end + if(current_state == ADDR) begin + addr_counter <= addr_counter + 1'b1; + end else begin + addr_counter <= 5'h00; + end + +end + +// RDATA latch +always @(posedge QSPI_nCS or negedge HRESETn) begin + if(~HRESETn) + QSPI_RDATA <= 128'd0; + else begin + if(QSPI_N_RW_BYTES==4'h0) + QSPI_RDATA <= {{120{1'b0}}, data_in_reg[7:0]}; + else if(QSPI_N_RW_BYTES==4'h1) + QSPI_RDATA <= {{112{1'b0}}, data_in_reg[15:0]}; + else if(QSPI_N_RW_BYTES==4'h2) + QSPI_RDATA <= {{104{1'b0}}, data_in_reg[23:0]}; + else if(QSPI_N_RW_BYTES==4'h3) + QSPI_RDATA <= {{96{1'b0}}, data_in_reg[31:0]}; + else if(QSPI_N_RW_BYTES==4'h4) + QSPI_RDATA <= {{88{1'b0}}, data_in_reg[39:0]}; + else if(QSPI_N_RW_BYTES==4'h5) + QSPI_RDATA <= {{80{1'b0}}, data_in_reg[47:0]}; + else if(QSPI_N_RW_BYTES==4'h6) + QSPI_RDATA <= {{72{1'b0}}, data_in_reg[55:0]}; + else if(QSPI_N_RW_BYTES==4'h7) + QSPI_RDATA <= {{64{1'b0}}, data_in_reg[63:0]}; + else if(QSPI_N_RW_BYTES==4'h8) + QSPI_RDATA <= {{56{1'b0}}, data_in_reg[71:0]}; + else if(QSPI_N_RW_BYTES==4'h9) + QSPI_RDATA <= {{48{1'b0}}, data_in_reg[79:0]}; + else if(QSPI_N_RW_BYTES==4'hA) + QSPI_RDATA <= {{40{1'b0}}, data_in_reg[87:0]}; + else if(QSPI_N_RW_BYTES==4'hB) + QSPI_RDATA <= {{32{1'b0}}, data_in_reg[95:0]}; + else if(QSPI_N_RW_BYTES==4'hC) + QSPI_RDATA <= {{24{1'b0}}, data_in_reg[103:0]}; + else if(QSPI_N_RW_BYTES==4'hD) + QSPI_RDATA <= {{16{1'b0}}, data_in_reg[111:0]}; + else if(QSPI_N_RW_BYTES==4'hE) + QSPI_RDATA <= {{8{1'b0}}, data_in_reg[120:0]}; + else if(QSPI_N_RW_BYTES==4'hF) + QSPI_RDATA <= data_in_reg[127:0]; + + end + end assign QSPI_nCS = ((QSPI_ENABLE==1'b1) ||(current_state!=IDLE) || (QSPI_SCLK_e==1'b1))?1'b0:1'b1; diff --git a/logical/top_ahb_qspi/logical/top_ahb_qspi.sv b/logical/top_ahb_qspi/logical/top_ahb_qspi.sv index 366df55..df0e778 100644 --- a/logical/top_ahb_qspi/logical/top_ahb_qspi.sv +++ b/logical/top_ahb_qspi/logical/top_ahb_qspi.sv @@ -159,15 +159,21 @@ cache_subsystem u_cache_subsystem( .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; +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; +wire [21:0] QSPI_ADDR; +wire [127:0] QSPI_RDATA; +wire [127:0] QSPI_WDATA; + + +wire XIP_ACTIVE; apb_qspi_regs u_apb_qspi_regs( .PCLK(PCLK), @@ -191,8 +197,12 @@ apb_qspi_regs u_apb_qspi_regs( .QSPI_ADDR_EN(QSPI_ADDR_EN), .QSPI_DUMMY_CYCLES(QSPI_DUMMY_CYCLES), .QSPI_N_RW_BYTES(QSPI_N_RW_BYTES), + .QSPI_ADDR(QSPI_ADDR), .QSPI_BUSY(~QSPI_nCS), - .QSPI_QIO_MODE(QSPI_QIO_MODE) + .QSPI_QIO_MODE(QSPI_QIO_MODE), + .QSPI_RDATA(QSPI_RDATA), + .QSPI_WDATA(QSPI_WDATA), + .XIP_ACTIVE(XIP_ACTIVE) ); ahb_qspi_interface #( @@ -228,10 +238,10 @@ qspi_controller u_qspi_controller( .QSPI_ADDR_EN(QSPI_ADDR_EN), .QSPI_DUMMY_CYCLES(QSPI_DUMMY_CYCLES), .QSPI_N_RW_BYTES(QSPI_N_RW_BYTES), + .QSPI_ADDR(QSPI_ADDR), .QSPI_QIO_MODE(QSPI_QIO_MODE), - .QSPI_ADDR(), - .QSPI_WDATA(), - .QSPI_RDATA(), + .QSPI_WDATA(QSPI_WDATA), + .QSPI_RDATA(QSPI_RDATA), .QSPI_SCLK(QSPI_SCLK), .QSPI_nCS(QSPI_nCS), diff --git a/makefile b/makefile index 74ac233..62b3db0 100644 --- a/makefile +++ b/makefile @@ -21,7 +21,9 @@ else endif get_flash_model: - @cd $(SOCLABS_AHB_QSPI_DIR)/verif/VIP; wget https://ww1.microchip.com/downloads/en/DeviceDoc/sst26wf040b.v + @cd $(SOCLABS_AHB_QSPI_DIR)/verif/VIP; wget https://ww1.microchip.com/downloads/en/DeviceDoc/SST26VF064B.zip + @cd $(SOCLABS_AHB_QSPI_DIR)/verif/VIP; unzip SST26VF064B.zip + @cd $(SOCLABS_AHB_QSPI_DIR)/verif/VIP; rm SST26VF064B.zip #Include flows include ./flows/makefile.simulate diff --git a/verif/cocotb/ahb_qspi_cocotb.v b/verif/cocotb/ahb_qspi_cocotb.v index 30a8796..f8cefd5 100644 --- a/verif/cocotb/ahb_qspi_cocotb.v +++ b/verif/cocotb/ahb_qspi_cocotb.v @@ -138,18 +138,10 @@ assign QSPI_IO_i[1] = QSPI_IO[1]; assign QSPI_IO_i[2] = QSPI_IO[2]; assign QSPI_IO_i[3] = QSPI_IO[3]; -sst26wf040b u_sst26wfxxxb( +sst26vf064b u_sst26vf064b( .SCK(QSPI_SCLK), .SIO(QSPI_IO), .CEb(QSPI_nCS) ); - //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 a95f4d8..313fc29 100644 --- a/verif/cocotb/ahb_qspi_tests.py +++ b/verif/cocotb/ahb_qspi_tests.py @@ -67,6 +67,9 @@ async def SPI_READ_JEDIC(dut, tb): while(int(data[0]['data'],16)&1): await ClockCycles(dut.HCLK,10) data = await tb.config_ahb_master.read(0x04,4) + ID = await tb.config_ahb_master.read(0x10,4) + print(ID) + assert int(ID[0]['data'],16) == 0x4326BF00 async def SET_QPI_MODE(dut,tb): await tb.config_ahb_master.write(0x08, 0x00000038) @@ -84,7 +87,10 @@ async def QPI_READ_JEDIC(dut, tb): while(int(data[0]['data'],16)&1): await ClockCycles(dut.HCLK,10) data = await tb.config_ahb_master.read(0x04,4) - + ID = await tb.config_ahb_master.read(0x10,4) + print(ID) + assert int(ID[0]['data'],16) == 0x4326BF00 + async def SPI_WRITE_ENABLE(dut, tb): await tb.config_ahb_master.write(0x08, 0x00000006) await tb.config_ahb_master.write(0x08, 0x00000106) @@ -93,7 +99,16 @@ async def SPI_WRITE_ENABLE(dut, tb): while(int(data[0]['data'],16)&1): await ClockCycles(dut.HCLK,2) data = await tb.config_ahb_master.read(0x04,4) - + +async def SPI_WRITE_DISABLE(dut, tb): + await tb.config_ahb_master.write(0x08, 0x00000004) + await tb.config_ahb_master.write(0x08, 0x00000104) + + 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) @@ -103,8 +118,19 @@ async def SPI_CLR_PROTECTION(dut, tb): await ClockCycles(dut.HCLK,2) data = await tb.config_ahb_master.read(0x04,4) +async def SPI_CHIP_ERASE(dut, tb): + await tb.config_ahb_master.write(0x08, 0x000000C7) + await tb.config_ahb_master.write(0x08, 0x000001C7) + + 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): + # Write Adress + await tb.config_ahb_master.write(0x0C, 0x000000) + await tb.config_ahb_master.write(0x08, 0x000008D8) await tb.config_ahb_master.write(0x08, 0x000009D8) @@ -112,7 +138,66 @@ async def SPI_BLOCK_ERASE(dut, tb): while(int(data[0]['data'],16)&1): await ClockCycles(dut.HCLK,2) data = await tb.config_ahb_master.read(0x04,4) + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + while(SPI_STAT&1): + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + await Timer(time=1, units='ms') +async def SPI_READ_STAT_REG(dut,tb): + await tb.config_ahb_master.write(0x08, 0x00001005) + await tb.config_ahb_master.write(0x08, 0x00001305) + 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) + data = await tb.config_ahb_master.read(0x10,4) + return (int(data[0]['data'],16)) + +async def SPI_READ_SLOW(dut, tb): + # Write Adress + await tb.config_ahb_master.write(0x0C, 0x000000) + + await tb.config_ahb_master.write(0x08, 0x00001003) + await tb.config_ahb_master.write(0x08, 0x00001303) + 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) + rData = await tb.config_ahb_master.read(0x10,4) + print(rData) + +async def QPI_READ(dut,tb): + # Write Adress + await tb.config_ahb_master.write(0x0C, 0x000000) + + await tb.config_ahb_master.write(0x08, 0x36A0B) + await tb.config_ahb_master.write(0x08, 0x36B0B) + 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) + rData = await tb.config_ahb_master.read(0x10,4) + print(rData) + +async def QPI_PAGE_PROGRAM(dut, tb): + # Write Adress + await tb.config_ahb_master.write(0x0C, 0x000000) + # Write Data + await tb.config_ahb_master.write(0x20, 0x84736251) + await tb.config_ahb_master.write(0x24, 0xF0F0F0F0) + await tb.config_ahb_master.write(0x28, 0xF0F0F0F0) + await tb.config_ahb_master.write(0x2C, 0xF0F0F0F0) + + await tb.config_ahb_master.write(0x08, 0x30C02) + await tb.config_ahb_master.write(0x08, 0x30D02) + 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) + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + while(SPI_STAT&1): + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + await Timer(time=10, units='us') @cocotb.test() @@ -126,7 +211,18 @@ async def QSPI_TESTS(dut): await QPI_READ_JEDIC(dut, tb) await SPI_WRITE_ENABLE(dut, tb) await SPI_CLR_PROTECTION(dut, tb) - await SPI_CHIP_ERASE(dut, tb) + await SPI_WRITE_ENABLE(dut, tb) + + await QPI_PAGE_PROGRAM(dut, tb) + + await SPI_WRITE_DISABLE(dut,tb) + await QPI_READ(dut, tb) + + #await SPI_WRITE_ENABLE(dut, tb) + #await SPI_CLR_PROTECTION(dut, tb) + #await SPI_WRITE_ENABLE(dut, tb) + #await SPI_BLOCK_ERASE(dut, tb) + #await ClockCycles(dut.HCLK,50) \ No newline at end of file diff --git a/verif/cocotb/makefile b/verif/cocotb/makefile index 90adc08..e5ec2d9 100644 --- a/verif/cocotb/makefile +++ b/verif/cocotb/makefile @@ -20,7 +20,7 @@ TOPLEVEL_LANG = verilog -SIM ?= questa +SIM ?= icarus WAVES ?= 0 GUI ?= 0 @@ -37,6 +37,7 @@ ifeq ($(SIM), icarus) PLUSARGS += -fst COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v))) + COMPILE_ARGS += -I $(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/ ifeq ($(WAVES), 1) VERILOG_SOURCES += iverilog_dump.v -- GitLab