diff --git a/flist/Top/ahb_QSPI.flist b/flist/Top/ahb_QSPI.flist index c5e8b57fbda078808f97527fc872425fea107a50..a2a9b0e4a6b18583f854d8d3fac7537743fa4da2 100644 --- a/flist/Top/ahb_QSPI.flist +++ b/flist/Top/ahb_QSPI.flist @@ -1,10 +1,11 @@ -$(SOCLABS_AHB_QSPI_DIR)/logical/top_ahb_qspi/logical/top_ahb_qspi.sv -$(SOCLABS_AHB_QSPI_DIR)/logical/apb_qspi_regs/logical/apb_qspi_regs.sv -$(SOCLABS_AHB_QSPI_DIR)/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv +$(SOCLABS_AHB_QSPI_DIR)/logical/top_ahb_qspi/logical/top_ahb_qspi.v +$(SOCLABS_AHB_QSPI_DIR)/logical/apb_qspi_regs/logical/apb_qspi_regs.v +$(SOCLABS_AHB_QSPI_DIR)/logical/ahb_qspi_interface/logical/ahb_qspi_interface.v -$(SOCLABS_AHB_QSPI_DIR)/logical/qspi_controller/logical/qspi_controller.sv +$(SOCLABS_AHB_QSPI_DIR)/logical/qspi_controller/logical/qspi_controller.v +$(SOCLABS_AHB_QSPI_DIR)/logical/qspi_controller/logical/qspi_controller_mux.v $(SOCLABS_AHB_QSPI_DIR)/logical/cache_subsytem/logical/cache_subsystem.v -f $(SOCLABS_AHB_QSPI_DIR)/flist/IP/CG092_cache.flist diff --git a/flows/makefile.lint b/flows/makefile.lint new file mode 100644 index 0000000000000000000000000000000000000000..8f21a44a2388bb5c0bd4fefd2299c9eab00f0a2a --- /dev/null +++ b/flows/makefile.lint @@ -0,0 +1,31 @@ +#----------------------------------------------------------------------------- +# NanoSoC Lint Design Makefile +# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +# +# Contributors +# +# David Mapstone (d.a.mapstone@soton.ac.uk) +# +# Copyright (C) 2021-3, SoC Labs (www.soclabs.org) +#----------------------------------------------------------------------------- + +# Include Lint Checks +include $(SOCLABS_SOCTOOLS_FLOW_DIR)/resources/hal/makefile.hal_checks + +# Lint-related Directories +LINT_DIR = $(SOCLABS_AHB_QSPI_DIR)/lint/ahb_qspi +LINT_INFO_DIR = $(SOCLABS_AHB_QSPI_DIR)/hal + +# HAL Black Box FIles + +# HAL Waivers +HAL_WAIVE = -design_info $(LINT_INFO_DIR)/ahb_qspi.waive + +# Top-level Module to Lint +LINT_TOP ?= top_ahb_qspi +LINT_FLIST ?= $(SOCLABS_AHB_QSPI_DIR)/flist/Top/ahb_QSPI.flist + +# Target from Running Verilator Lint Tool +lint_verilator: + @rm -rf $(LINT_DIR) + @mkdir -p $(LINT_DIR)- @cd $(LINT_DIR); verilator --lint-only -f $(LINT_FLIST) -I$(ARM_IP_LIBRARY_PATH)/CG092/CG092-BU-50000-r2p0-00rel0/p_flash_cache_f0/logical/p_flash_cache_f0/verilog/ --top-module $(LINT_TOP) diff --git a/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv b/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv deleted file mode 100644 index 06d3391027a0b8fe5c7ea9f380d1f807aee4c1d0..0000000000000000000000000000000000000000 --- a/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv +++ /dev/null @@ -1,77 +0,0 @@ - -module ahb_qspi_interface #( - parameter ADDR_W = 32, - parameter DATA_W = 32 - )( - input wire HCLK, - input wire HRESETn, - - // AHB Signals - input wire [ADDR_W-1:0] HADDR, - input wire [1:0] HTRANS, - input wire HWRITE, - input wire [2:0] HSIZE, - input wire [2:0] HBURST, - input wire [3:0] HPROT, - input wire [DATA_W-1:0] HWDATA, - input wire HSELx, - output wire [DATA_W-1:0] HRDATA, - input wire HREADY, - output wire HREADYOUT, - output wire HRESP -); - -assign HREADYOUT = 1'b0; -assign HRESP = 1'b0; -// AHB FSM -enum {IDLE, WAIT_READ, WAIT_WRITE, WRITE, READ} current_state, next_state; - -// AHB lite last regs -reg last_HSEL; -reg [31:0] last_HADDR; -reg last_HWRITE; -reg [1:0] last_HTRANS; - -// -reg qspi_ready; - -always @(posedge HCLK or negedge HRESETn) begin - if(~HRESETn) begin - last_HSEL <= 1'b0; - last_HADDR <= 32'd0; - last_HWRITE <= 1'b0; - last_HTRANS <= 2'b00; - - current_state <= IDLE; - qspi_ready <= 1'b0; - end else begin - last_HSEL <= HSELx; - last_HADDR <= HADDR; - last_HWRITE <= HWRITE; - last_HTRANS <= HTRANS; - - current_state <= next_state; - end -end - -always @(*) begin - next_state = IDLE; - case(current_state) - IDLE: if(HSELx & HWRITE & ~qspi_ready) - next_state = WAIT_WRITE; - else if(HSELx & ~qspi_ready) - next_state = WAIT_READ; - WAIT_WRITE: if(qspi_ready) - next_state = WRITE; - else - next_state = WAIT_WRITE; - WAIT_READ: if(qspi_ready) - next_state = READ; - else - next_state = WAIT_READ; - READ: next_state = IDLE; - WRITE: next_state = IDLE; - endcase -end - -endmodule \ No newline at end of file diff --git a/logical/ahb_qspi_interface/logical/ahb_qspi_interface.v b/logical/ahb_qspi_interface/logical/ahb_qspi_interface.v new file mode 100644 index 0000000000000000000000000000000000000000..32a07f4f9ada452fb98c629a6dcf1fe4a83a3a03 --- /dev/null +++ b/logical/ahb_qspi_interface/logical/ahb_qspi_interface.v @@ -0,0 +1,134 @@ + +module ahb_qspi_interface #( + parameter ADDR_W = 32, + parameter DATA_W = 32 + )( + input wire HCLK, + input wire HRESETn, + + // AHB Signals + input wire [ADDR_W-1:0] HADDR, + input wire [1:0] HTRANS, + input wire HWRITE, + input wire [2:0] HSIZE, + input wire [2:0] HBURST, + input wire [3:0] HPROT, + input wire [DATA_W-1:0] HWDATA, + input wire HSELx, + output reg [DATA_W-1:0] HRDATA, + input wire HREADY, + output wire HREADYOUT, + output wire HRESP, + + output wire [7:0] AHB_QSPI_CMD, + output reg AHB_QSPI_ENABLE, + output wire AHB_QSPI_READ, + output wire AHB_QSPI_WRITE, + output wire AHB_QSPI_ADDR_EN, + output wire [3:0] AHB_QSPI_DUMMY_CYCLES, + output wire [3:0] AHB_QSPI_N_RW_BYTES, + output reg [21:0] AHB_QSPI_ADDR, + output wire [127:0] AHB_QSPI_WDATA, + + input wire AHB_QSPI_ENABLE_ACK, + input wire AHB_QSPI_BUSY, + input wire [127:0] AHB_QSPI_RDATA + + +); + +assign HRESP = 1'b0; + +assign AHB_QSPI_CMD = 8'h0B; +assign AHB_QSPI_ADDR_EN = 1'b1; +assign AHB_QSPI_DUMMY_CYCLES = 4'h4; +assign AHB_QSPI_N_RW_BYTES = 4'hF; +assign AHB_QSPI_READ=1'b1; +assign AHB_QSPI_WRITE=1'b0; +assign AHB_QSPI_WDATA = HWDATA; + +// AHB FSM +enum {IDLE, WAIT_READ, WAIT_WRITE, WRITE, READ} current_state, next_state; + +// AHB lite last regs +reg last_HSEL; +reg [ADDR_W-1:0] last_HADDR; +reg last_HWRITE; +reg [1:0] last_HTRANS; + +// +reg qspi_ready; +reg qspi_started; + +assign HREADYOUT = qspi_ready; //(current_state==IDLE)? 1'b1 : qspi_ready; + +always @(posedge HCLK or negedge HRESETn) begin + if(~HRESETn) begin + last_HSEL <= 1'b0; + last_HADDR <= {ADDR_W{1'b0}}; + last_HWRITE <= 1'b0; + last_HTRANS <= 2'b00; + + current_state <= IDLE; + end else begin + last_HSEL <= HSELx; + last_HADDR <= HADDR; + last_HWRITE <= HWRITE; + last_HTRANS <= HTRANS; + + current_state <= next_state; + end +end + +always @(*) begin + next_state = IDLE; + case(current_state) + IDLE: if(HSELx & HWRITE & ~qspi_ready) + next_state = WAIT_WRITE; + else if(HSELx & ~qspi_ready) + next_state = WAIT_READ; + WAIT_WRITE: if(qspi_ready) + next_state = WRITE; + else + next_state = WAIT_WRITE; + WAIT_READ: if(qspi_ready) + next_state = READ; + else + next_state = WAIT_READ; + READ: next_state = IDLE; + WRITE: next_state = IDLE; + endcase +end + +always @(posedge HCLK or negedge HRESETn) begin + if(~HRESETn) begin + AHB_QSPI_ENABLE <= 1'b0; + qspi_ready <= 1'b0; + qspi_started <= 1'b0; + AHB_QSPI_ADDR <= 22'd0; + end else begin + if(current_state == WAIT_READ) begin + if(AHB_QSPI_BUSY!=1'b1) begin + if(qspi_started==1'b0) begin + AHB_QSPI_ENABLE <= 1'b1; + qspi_started <= 1'b1; + end + end + if(AHB_QSPI_ENABLE_ACK) + AHB_QSPI_ENABLE <= 1'b0; + if(qspi_started==1'b1) begin + if(AHB_QSPI_BUSY==1'b0) begin + HRDATA <= AHB_QSPI_RDATA; + qspi_ready <= 1'b1; + end + end + end else begin + qspi_started <= 1'b0; + qspi_ready <=1'b0; + AHB_QSPI_ADDR <= HADDR; + end + end + +end + +endmodule \ 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.v similarity index 86% rename from logical/apb_qspi_regs/logical/apb_qspi_regs.sv rename to logical/apb_qspi_regs/logical/apb_qspi_regs.v index 4fe8d8cfbaee4f538e532a381f3bda2fab2506f2..857944e79bceaf25c1e1baa2ad78afe1ac8b5c7c 100644 --- a/logical/apb_qspi_regs/logical/apb_qspi_regs.sv +++ b/logical/apb_qspi_regs/logical/apb_qspi_regs.v @@ -27,13 +27,18 @@ module apb_qspi_regs( output wire [21:0] QSPI_ADDR, input wire [127:0] QSPI_RDATA, output wire [127:0] QSPI_WDATA, - output wire XIP_ACTIVE + output wire XIP_ACTIVE, + output wire QSPI_CONT_READ, + output wire [7:0] QSPI_MODE_CODE, + output wire QSPI_NO_CMD ); // Registers // 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] // XIP_ACTIVE [8] |------------------> XIP_ACTIVE [8] -// +// QSPI_MODE_CODE[23:16] +// QSPI_CONT_READ[24] +// QSPI_NO_CMD[25] // reg1 Status @@ -64,6 +69,9 @@ reg [31:0] reg11; assign QSPI_QIO_MODE = reg0[0]; assign XIP_ACTIVE = reg0[8]; +assign QSPI_MODE_CODE = reg0[23:16]; +assign QSPI_CONT_READ = reg0[24]; +assign QSPI_NO_CMD = reg0[25]; assign QSPI_CMD = reg2[7:0]; assign QSPI_ENABLE = reg2[8]; @@ -116,10 +124,10 @@ 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'h004: PRDATA = {QSPI_RDATA[7:0],QSPI_RDATA[15:8],QSPI_RDATA[23:16],QSPI_RDATA[31:24]}; + 10'h005: PRDATA = {QSPI_RDATA[39:32], QSPI_RDATA[47:40], QSPI_RDATA[55:48], QSPI_RDATA[63:56]}; + 10'h006: PRDATA = {QSPI_RDATA[71:64], QSPI_RDATA[79:72], QSPI_RDATA[87:80], QSPI_RDATA[95:88]}; + 10'h007: PRDATA = {QSPI_RDATA[103:96], QSPI_RDATA[111:104], QSPI_RDATA[119:112], QSPI_RDATA[127:120]}; 10'h008: PRDATA = reg8; 10'h009: PRDATA = reg9; 10'h00A: PRDATA = reg10; diff --git a/logical/cache_subsytem/logical/cache_subsystem.v b/logical/cache_subsytem/logical/cache_subsystem.v index 33556210c43bd9653ab7f70a78243816fe26e8dc..118857cf1be46498cde687d3360f1359a1b4161f 100644 --- a/logical/cache_subsytem/logical/cache_subsystem.v +++ b/logical/cache_subsytem/logical/cache_subsystem.v @@ -80,12 +80,15 @@ wire RAMTAG1CS; wire [10:0] RAMTAG1WDATA; wire [10:0] RAMTAG1RDATA; +wire RAMPWRUPACK; +wire RAMPWRUPREQ; +reg PWR_DELAY; p_flash_cache_f0 #( .AW(22), .CW(12), .CACHE_WAY(2), - .RESET_ALL_REGS(0), + .RESET_ALL_REGS(1), .GEN_STAT_LOGIC(1), .LINEW(4) ) u_cache_controller( @@ -119,8 +122,8 @@ p_flash_cache_f0 #( .HRDATAS(HRDATAS), .HRESPS(HRESPS), // CACHE RAM POWER UP - .RAMPWRUPREQ(), - .RAMPWRUPACK(), + .RAMPWRUPREQ(RAMPWRUPREQ), + .RAMPWRUPACK(RAMPWRUPACK), // TAG RAM way 0 .RAMTAG0ADDR(RAMTAG0ADDR), .RAMTAG0WE(RAMTAG0WE), @@ -170,6 +173,14 @@ p_flash_cache_f0 #( .CACHEHIT(CACHEHIT) ); +always @(posedge HCLK or negedge HRESETn) begin + if(~HRESETn) + PWR_DELAY <= 1'b0; + else + PWR_DELAY <= RAMPWRUPREQ; +end +assign RAMPWRUPACK = PWR_DELAY; + cache_ram #( .ADDR_W(8) ) u_way0_cache_ram ( diff --git a/logical/qspi_controller/logical/qspi_controller.sv b/logical/qspi_controller/logical/qspi_controller.v similarity index 71% rename from logical/qspi_controller/logical/qspi_controller.sv rename to logical/qspi_controller/logical/qspi_controller.v index e94c0e0134f61508833fe7ae6415cd2eac65eb5f..404850dfe7097d5aeb33c642f6ca5d07ff615e6e 100644 --- a/logical/qspi_controller/logical/qspi_controller.sv +++ b/logical/qspi_controller/logical/qspi_controller.v @@ -18,6 +18,9 @@ module qspi_controller ( input wire [127:0] QSPI_WDATA, output reg [127:0] QSPI_RDATA, input wire QSPI_QIO_MODE, + input wire QSPI_CONT_READ, + input wire [7:0] QSPI_MODE_CODE, + input wire QSPI_NO_CMD, // QSPI Interface output wire QSPI_SCLK, @@ -42,7 +45,9 @@ always @(posedge HCLK or negedge HRESETn) begin QSPI_CLK_DIV_COUNTER<=8'h00; QSPI_SCLK_reg <= 1'b0; end else begin - if(QSPI_CLK_DIV!=8'h00) begin + if(QSPI_CLK_DIV==8'h01) begin + QSPI_SCLK_reg <= ~QSPI_SCLK_reg; + end else 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 @@ -55,17 +60,20 @@ always @(posedge HCLK or negedge HRESETn) begin end end -enum {IDLE, OP, ADDR, DUMMY, DATA_O, DATA_I} current_state, next_state; +enum {IDLE, OP, ADDR, MODE, DUMMY, DATA_O, DATA_I} current_state, next_state; reg [2:0] op_counter; reg [4:0] addr_counter; +reg mode_counter; reg [2:0] data_counter; reg [3:0] dummy_counter; -reg [4:0] byte_counter; +reg [3:0] byte_counter; reg [7:0] op_code; reg [23:0] addr_code; +reg [7:0] qspi_mode_reg; 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; @@ -81,8 +89,10 @@ end always @(*) begin case(current_state) IDLE: begin - if(QSPI_ENABLE) begin + if(QSPI_ENABLE==1'b1 && QSPI_NO_CMD==1'b0) begin next_state = OP; + end else if(QSPI_ENABLE==1'b1 && QSPI_NO_CMD==1'b1) begin + next_state = ADDR; end else begin next_state = IDLE; QSPI_ENABLE_ACK = 1'b0; @@ -119,9 +129,13 @@ 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; + QSPI_ENABLE_ACK = 1'b1; + if(QSPI_QIO_MODE==1'b1 & addr_counter==5'h05) begin + QSPI_ENABLE_ACK = 1'b0; + if(QSPI_CONT_READ) + next_state = MODE; + else if(QSPI_DUMMY_CYCLES>4'h0) + next_state = DUMMY; else if(QSPI_READ) next_state = DATA_I; else if(QSPI_WRITE) @@ -129,9 +143,10 @@ always @(*) begin else next_state = IDLE; end - else if(QSPI_QIO_MODE==1'b0 & addr_counter==3'h21) begin + else if(QSPI_QIO_MODE==1'b0 & addr_counter==5'h21) begin + QSPI_ENABLE_ACK = 1'b0; if(QSPI_DUMMY_CYCLES>4'h0) - next_state <= DUMMY; + next_state = DUMMY; else if(QSPI_READ) next_state = DATA_I; else if(QSPI_WRITE) @@ -140,6 +155,21 @@ always @(*) begin next_state = IDLE; end end + MODE: begin + if(QSPI_QIO_MODE==1'b1 & mode_counter == 1'b0) 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) begin + next_state = IDLE; + end + end DUMMY: begin if(dummy_counter >= QSPI_DUMMY_CYCLES - 1'b1) begin if(QSPI_WRITE) @@ -155,14 +185,14 @@ always @(*) begin end else begin if(byte_counter==QSPI_N_RW_BYTES) begin - if(data_counter==3'h1) + if(data_counter==3'h0) next_state = IDLE; end end end DATA_I: begin if(QSPI_QIO_MODE==1'b0) begin - if((byte_counter==QSPI_N_RW_BYTES+1'b1)) begin + if((byte_counter==QSPI_N_RW_BYTES)) begin if(data_counter==3'h6) next_state = IDLE; end @@ -195,6 +225,14 @@ always @(negedge QSPI_SCLK_i) begin end else if(current_state == DATA_O) begin QSPI_IO_e_int <= 1'b1; QSPI_SCLK_e <= 1'b1; + 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 + QSPI_IO_o_reg[0] <= QSPI_WDATA_reg[0]; + QSPI_WDATA_reg <= {1'b0, QSPI_WDATA_reg[127:1]}; + end + end else if(current_state == ADDR) begin QSPI_IO_e_int <= 1'b1; QSPI_SCLK_e <= 1'b1; @@ -205,17 +243,35 @@ always @(negedge QSPI_SCLK_i) 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; + dummy_counter <= dummy_counter + 1'b1; + end else if(current_state == MODE) begin + QSPI_IO_e_int <=1'b1; + QSPI_SCLK_e <= 1'b1; + if(QSPI_QIO_MODE==1'b1) begin + QSPI_IO_o_reg <= qspi_mode_reg[7:4]; + qspi_mode_reg <= {qspi_mode_reg[3:0], 4'b0}; + end end else begin op_code <= QSPI_CMD; addr_code <= {2'b00,QSPI_ADDR}; + qspi_mode_reg <= QSPI_MODE_CODE; QSPI_SCLK_e<=1'b0; QSPI_IO_o_reg<=4'hF; QSPI_IO_e_int <= 1'b1; end + + if(current_state != DATA_O) begin + QSPI_WDATA_reg <= QSPI_WDATA; + end + + if(current_state != DUMMY) begin + dummy_counter <= 4'h0; + end + + end always @(posedge QSPI_SCLK_i) begin if(current_state==OP) begin @@ -229,37 +285,20 @@ always @(posedge QSPI_SCLK_i) begin 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 + 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'h7; - byte_counter <= 4'h0; + byte_counter <= 4'hF; end if(current_state == DATA_I) begin if(QSPI_QIO_MODE==1'b1) begin - 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]}; + data_in_reg <= {data_in_reg[123:0], QSPI_IO_i}; end else begin - QSPI_IO_o_reg[0] <= QSPI_WDATA_reg[0]; - QSPI_WDATA_reg <= {1'b0, QSPI_WDATA_reg[127:1]}; + data_in_reg <= {data_in_reg[126:0], QSPI_IO_i[1]}; end - end else begin - QSPI_WDATA_reg <= QSPI_WDATA; - end - - if(current_state == DUMMY) begin - dummy_counter <= dummy_counter + 1'b1; - end else begin - dummy_counter <= 4'h0; end if(current_state == ADDR) begin @@ -268,6 +307,12 @@ always @(posedge QSPI_SCLK_i) begin addr_counter <= 5'h00; end + if(current_state == MODE) begin + mode_counter <= mode_counter + 1'b1; + end else begin + mode_counter <= 1'b1; + end + end // RDATA latch @@ -276,37 +321,37 @@ always @(posedge QSPI_nCS or negedge HRESETn) begin QSPI_RDATA <= 128'd0; else begin if(QSPI_N_RW_BYTES==4'h0) - QSPI_RDATA <= {{120{1'b0}}, data_in_reg[7:0]}; + 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]}; + 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]}; + QSPI_RDATA <= {{88{1'b0}}, data_in_reg[31:0], data_in_reg[39:32]}; else if(QSPI_N_RW_BYTES==4'h5) - QSPI_RDATA <= {{80{1'b0}}, data_in_reg[47:0]}; + QSPI_RDATA <= {{80{1'b0}}, data_in_reg[31:0], data_in_reg[47:32]}; else if(QSPI_N_RW_BYTES==4'h6) - QSPI_RDATA <= {{72{1'b0}}, data_in_reg[55:0]}; + QSPI_RDATA <= {{72{1'b0}}, data_in_reg[31:0], data_in_reg[55:32]}; else if(QSPI_N_RW_BYTES==4'h7) - QSPI_RDATA <= {{64{1'b0}}, data_in_reg[63:0]}; + QSPI_RDATA <= {{64{1'b0}}, data_in_reg[31:0], data_in_reg[63:32]}; else if(QSPI_N_RW_BYTES==4'h8) - QSPI_RDATA <= {{56{1'b0}}, data_in_reg[71:0]}; + QSPI_RDATA <= {{56{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[71:64]}; else if(QSPI_N_RW_BYTES==4'h9) - QSPI_RDATA <= {{48{1'b0}}, data_in_reg[79:0]}; + QSPI_RDATA <= {{48{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[79:64]}; else if(QSPI_N_RW_BYTES==4'hA) - QSPI_RDATA <= {{40{1'b0}}, data_in_reg[87:0]}; + QSPI_RDATA <= {{40{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[87:64]}; else if(QSPI_N_RW_BYTES==4'hB) - QSPI_RDATA <= {{32{1'b0}}, data_in_reg[95:0]}; + QSPI_RDATA <= {{32{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[95:64]}; else if(QSPI_N_RW_BYTES==4'hC) - QSPI_RDATA <= {{24{1'b0}}, data_in_reg[103:0]}; + QSPI_RDATA <= {{24{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[95:64], data_in_reg[103:96]}; else if(QSPI_N_RW_BYTES==4'hD) - QSPI_RDATA <= {{16{1'b0}}, data_in_reg[111:0]}; + QSPI_RDATA <= {{16{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[95:64], data_in_reg[111:96]}; else if(QSPI_N_RW_BYTES==4'hE) - QSPI_RDATA <= {{8{1'b0}}, data_in_reg[120:0]}; + QSPI_RDATA <= {{8{1'b0}}, data_in_reg[31:0], data_in_reg[63:32], data_in_reg[95:64], data_in_reg[119:96]}; else if(QSPI_N_RW_BYTES==4'hF) - QSPI_RDATA <= data_in_reg[127:0]; + QSPI_RDATA <= {data_in_reg[31:0], data_in_reg[63:32], data_in_reg[95:64], data_in_reg[127:96]}; end diff --git a/logical/qspi_controller/logical/qspi_controller_mux.v b/logical/qspi_controller/logical/qspi_controller_mux.v new file mode 100644 index 0000000000000000000000000000000000000000..1c6ae10b041b44e6252d4d4bcfa7eba856898e0c --- /dev/null +++ b/logical/qspi_controller/logical/qspi_controller_mux.v @@ -0,0 +1,68 @@ +module qspi_controller_mux( + input wire XIP_ACTIVE, + + input wire [7:0] AHB_QSPI_CMD, + input wire AHB_QSPI_ENABLE, + input wire AHB_QSPI_READ, + input wire AHB_QSPI_WRITE, + input wire AHB_QSPI_ADDR_EN, + input wire [3:0] AHB_QSPI_DUMMY_CYCLES, + input wire [3:0] AHB_QSPI_N_RW_BYTES, + input wire [21:0] AHB_QSPI_ADDR, + input wire [127:0] AHB_QSPI_WDATA, + + output wire AHB_QSPI_ENABLE_ACK, + output wire AHB_QSPI_BUSY, + output wire [127:0] AHB_QSPI_RDATA, + + + input wire [7:0] APB_QSPI_CMD, + input wire APB_QSPI_ENABLE, + input wire APB_QSPI_READ, + input wire APB_QSPI_WRITE, + input wire APB_QSPI_ADDR_EN, + input wire [3:0] APB_QSPI_DUMMY_CYCLES, + input wire [3:0] APB_QSPI_N_RW_BYTES, + input wire [21:0] APB_QSPI_ADDR, + input wire [127:0] APB_QSPI_WDATA, + + output wire APB_QSPI_ENABLE_ACK, + output wire APB_QSPI_BUSY, + output wire [127:0] APB_QSPI_RDATA, + + output wire [7:0] QSPI_CMD, + output wire QSPI_ENABLE, + 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, + output wire [21:0] QSPI_ADDR, + output wire [127:0] QSPI_WDATA, + + input wire QSPI_ENABLE_ACK, + input wire QSPI_BUSY, + input wire [127:0] QSPI_RDATA + +); + + +assign QSPI_CMD = (XIP_ACTIVE==1'b1)? AHB_QSPI_CMD : APB_QSPI_CMD; +assign QSPI_ENABLE = (XIP_ACTIVE==1'b1)? AHB_QSPI_ENABLE: APB_QSPI_ENABLE; +assign QSPI_READ = (XIP_ACTIVE==1'b1)? AHB_QSPI_READ : APB_QSPI_READ; +assign QSPI_WRITE = (XIP_ACTIVE==1'b1)? AHB_QSPI_WRITE : APB_QSPI_WRITE; +assign QSPI_ADDR_EN = (XIP_ACTIVE==1'b1)? AHB_QSPI_ADDR_EN : APB_QSPI_ADDR_EN; +assign QSPI_DUMMY_CYCLES = (XIP_ACTIVE==1'b1)? AHB_QSPI_DUMMY_CYCLES : APB_QSPI_DUMMY_CYCLES; +assign QSPI_N_RW_BYTES = (XIP_ACTIVE==1'b1)? AHB_QSPI_N_RW_BYTES : APB_QSPI_N_RW_BYTES; +assign QSPI_ADDR = (XIP_ACTIVE==1'b1)? AHB_QSPI_ADDR : APB_QSPI_ADDR; +assign QSPI_WDATA = (XIP_ACTIVE==1'b1)? AHB_QSPI_WDATA : APB_QSPI_WDATA; + +assign AHB_QSPI_ENABLE_ACK = (XIP_ACTIVE==1'b1) ? QSPI_ENABLE_ACK : 1'b0; +assign AHB_QSPI_BUSY = (XIP_ACTIVE==1'b1) ? QSPI_BUSY : 1'b1; +assign AHB_QSPI_RDATA = (XIP_ACTIVE==1'b1) ? QSPI_RDATA : 128'd0; + +assign APB_QSPI_ENABLE_ACK = (XIP_ACTIVE==1'b0) ? QSPI_ENABLE_ACK : 1'b0; +assign APB_QSPI_BUSY = (XIP_ACTIVE==1'b0) ? QSPI_BUSY : 1'b1; +assign APB_QSPI_RDATA = (XIP_ACTIVE==1'b0) ? QSPI_RDATA : 128'd0; + +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.v similarity index 62% rename from logical/top_ahb_qspi/logical/top_ahb_qspi.sv rename to logical/top_ahb_qspi/logical/top_ahb_qspi.v index df0e7784f55c8232499d2478230fc45ccf4d7a9a..daa7173d68366ec23527083e993dad5b8718529a 100644 --- a/logical/top_ahb_qspi/logical/top_ahb_qspi.sv +++ b/logical/top_ahb_qspi/logical/top_ahb_qspi.v @@ -128,14 +128,14 @@ cache_subsystem u_cache_subsystem( .HSELS(HSELx), .HADDRS(HADDR[21:0]), .HBURSTS(HBURST), - .HMASTLOCKS(), + .HMASTLOCKS(1'b1), .HTRANSS(HTRANS), .HSIZES(HSIZE), .HPROTS(HPROT), .HWRITES(HWRITE), .HWDATAS(HWDATA), .HREADYS(HREADY), - .HMASTERS(), + .HMASTERS(1'b0), .HREADYOUTS(HREADYOUT), .HRDATAS(HRDATA), .HRESPS(HRESP), @@ -159,21 +159,96 @@ 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 [7:0] QSPI_CMD; +wire QSPI_ENABLE; +wire QSPI_READ; +wire QSPI_WRITE; +wire QSPI_ADDR_EN; +wire [3:0] QSPI_DUMMY_CYCLES; +wire [3:0] QSPI_N_RW_BYTES; +wire [21:0] QSPI_ADDR; +wire [127:0] QSPI_WDATA; +wire QSPI_ENABLE_ACK; +wire QSPI_BUSY; +wire [127:0] QSPI_RDATA; + +wire [7:0] AHB_QSPI_CMD; +wire AHB_QSPI_ENABLE; +wire AHB_QSPI_READ; +wire AHB_QSPI_WRITE; +wire AHB_QSPI_ADDR_EN; +wire [3:0] AHB_QSPI_DUMMY_CYCLES; +wire [3:0] AHB_QSPI_N_RW_BYTES; +wire [21:0] AHB_QSPI_ADDR; +wire [127:0] AHB_QSPI_WDATA; +wire AHB_QSPI_ENABLE_ACK; +wire AHB_QSPI_BUSY; +wire [127:0] AHB_QSPI_RDATA; + +wire [7:0] APB_QSPI_CMD; +wire APB_QSPI_ENABLE; +wire APB_QSPI_READ; +wire APB_QSPI_WRITE; +wire APB_QSPI_ADDR_EN; +wire [3:0] APB_QSPI_DUMMY_CYCLES; +wire [3:0] APB_QSPI_N_RW_BYTES; +wire [21:0] APB_QSPI_ADDR; +wire [127:0] APB_QSPI_WDATA; +wire APB_QSPI_ENABLE_ACK; +wire APB_QSPI_BUSY; +wire [127:0] APB_QSPI_RDATA; + +// Config from APB 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 QSPI_CONT_READ; +wire [7:0] QSPI_MODE_CODE; +wire QSPI_NO_CMD; +wire XIP_ACTIVE; -wire XIP_ACTIVE; +qspi_controller_mux u_qspi_controller_mux( + .XIP_ACTIVE(XIP_ACTIVE), + + .AHB_QSPI_CMD(AHB_QSPI_CMD), + .AHB_QSPI_ENABLE(AHB_QSPI_ENABLE), + .AHB_QSPI_READ(AHB_QSPI_READ), + .AHB_QSPI_WRITE(AHB_QSPI_WRITE), + .AHB_QSPI_ADDR_EN(AHB_QSPI_ADDR_EN), + .AHB_QSPI_DUMMY_CYCLES(AHB_QSPI_DUMMY_CYCLES), + .AHB_QSPI_N_RW_BYTES(AHB_QSPI_N_RW_BYTES), + .AHB_QSPI_ADDR(AHB_QSPI_ADDR), + .AHB_QSPI_WDATA(AHB_QSPI_WDATA), + .AHB_QSPI_ENABLE_ACK(AHB_QSPI_ENABLE_ACK), + .AHB_QSPI_BUSY(AHB_QSPI_BUSY), + .AHB_QSPI_RDATA(AHB_QSPI_RDATA), + + .APB_QSPI_CMD(APB_QSPI_CMD), + .APB_QSPI_ENABLE(APB_QSPI_ENABLE), + .APB_QSPI_READ(APB_QSPI_READ), + .APB_QSPI_WRITE(APB_QSPI_WRITE), + .APB_QSPI_ADDR_EN(APB_QSPI_ADDR_EN), + .APB_QSPI_DUMMY_CYCLES(APB_QSPI_DUMMY_CYCLES), + .APB_QSPI_N_RW_BYTES(APB_QSPI_N_RW_BYTES), + .APB_QSPI_ADDR(APB_QSPI_ADDR), + .APB_QSPI_WDATA(APB_QSPI_WDATA), + .APB_QSPI_ENABLE_ACK(APB_QSPI_ENABLE_ACK), + .APB_QSPI_BUSY(APB_QSPI_BUSY), + .APB_QSPI_RDATA(APB_QSPI_RDATA), + + .QSPI_CMD(QSPI_CMD), + .QSPI_ENABLE(QSPI_ENABLE), + .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_ADDR(QSPI_ADDR), + .QSPI_WDATA(QSPI_WDATA), + .QSPI_ENABLE_ACK(QSPI_ENABLE_ACK), + .QSPI_BUSY(~QSPI_nCS), + .QSPI_RDATA(QSPI_RDATA) +); apb_qspi_regs u_apb_qspi_regs( .PCLK(PCLK), @@ -189,20 +264,23 @@ apb_qspi_regs u_apb_qspi_regs( .PREADY(qspi_pready), .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_ADDR(QSPI_ADDR), - .QSPI_BUSY(~QSPI_nCS), + .QSPI_CMD(APB_QSPI_CMD), + .QSPI_ENABLE(APB_QSPI_ENABLE), + .QSPI_ENABLE_ACK(APB_QSPI_ENABLE_ACK), + .QSPI_READ(APB_QSPI_READ), + .QSPI_WRITE(APB_QSPI_WRITE), + .QSPI_ADDR_EN(APB_QSPI_ADDR_EN), + .QSPI_DUMMY_CYCLES(APB_QSPI_DUMMY_CYCLES), + .QSPI_N_RW_BYTES(APB_QSPI_N_RW_BYTES), + .QSPI_ADDR(APB_QSPI_ADDR), + .QSPI_BUSY(APB_QSPI_BUSY), .QSPI_QIO_MODE(QSPI_QIO_MODE), - .QSPI_RDATA(QSPI_RDATA), - .QSPI_WDATA(QSPI_WDATA), - .XIP_ACTIVE(XIP_ACTIVE) + .QSPI_RDATA(APB_QSPI_RDATA), + .QSPI_WDATA(APB_QSPI_WDATA), + .XIP_ACTIVE(XIP_ACTIVE), + .QSPI_CONT_READ(QSPI_CONT_READ), + .QSPI_MODE_CODE(QSPI_MODE_CODE), + .QSPI_NO_CMD(QSPI_NO_CMD) ); ahb_qspi_interface #( @@ -222,13 +300,25 @@ ahb_qspi_interface #( .HRDATA(flash_HRDATAM), .HREADY(flash_HREADYM), .HREADYOUT(flash_HREADYOUTM), - .HRESP(flash_HRESPM) + .HRESP(flash_HRESPM), + .AHB_QSPI_CMD(AHB_QSPI_CMD), + .AHB_QSPI_ENABLE(AHB_QSPI_ENABLE), + .AHB_QSPI_READ(AHB_QSPI_READ), + .AHB_QSPI_WRITE(AHB_QSPI_WRITE), + .AHB_QSPI_ADDR_EN(AHB_QSPI_ADDR_EN), + .AHB_QSPI_DUMMY_CYCLES(AHB_QSPI_DUMMY_CYCLES), + .AHB_QSPI_N_RW_BYTES(AHB_QSPI_N_RW_BYTES), + .AHB_QSPI_ADDR(AHB_QSPI_ADDR), + .AHB_QSPI_WDATA(AHB_QSPI_WDATA), + .AHB_QSPI_ENABLE_ACK(AHB_QSPI_ENABLE_ACK), + .AHB_QSPI_BUSY(AHB_QSPI_BUSY), + .AHB_QSPI_RDATA(AHB_QSPI_RDATA) ); qspi_controller u_qspi_controller( .HCLK(HCLK), .HRESETn(HRESETn), - .QSPI_CLK_DIV(8'h02), + .QSPI_CLK_DIV(8'h01), .QSPI_SPI_MODE(2'b00), .QSPI_CMD(QSPI_CMD), .QSPI_ENABLE(QSPI_ENABLE), @@ -242,6 +332,9 @@ qspi_controller u_qspi_controller( .QSPI_QIO_MODE(QSPI_QIO_MODE), .QSPI_WDATA(QSPI_WDATA), .QSPI_RDATA(QSPI_RDATA), + .QSPI_CONT_READ(QSPI_CONT_READ), + .QSPI_MODE_CODE(QSPI_MODE_CODE), + .QSPI_NO_CMD(QSPI_NO_CMD), .QSPI_SCLK(QSPI_SCLK), .QSPI_nCS(QSPI_nCS), diff --git a/makefile b/makefile index 62b3db077afcbbc4ef0e2103b20a58d673bb6761..6cf9f96d6bc12b097a31b9a865b053c9e1bd44f2 100644 --- a/makefile +++ b/makefile @@ -27,5 +27,5 @@ get_flash_model: #Include flows include ./flows/makefile.simulate - +include ./flows/makefile.lint export BP210_DIR \ No newline at end of file diff --git a/verif/README.md b/verif/README.md index 907d63fa66d6b2d46ec5497f6d2cddc8c66e61e3..90d5a80782813920d327d697f8c09fd627aac599 100644 --- a/verif/README.md +++ b/verif/README.md @@ -20,10 +20,10 @@ Configuration Read - [ ] (0x03) Read Memory -- [ ] (0x0B) High speed Read -- [ ] (0x6B) SQOR: SPI Quad Ouptut Read +- [x] (0x0B) High speed Read +- [ ] (0x6B) SQOR: SPI Quad Output Read - [ ] (0xEB) SQIOR: SPI Quad I/O Read -- [ ] (0x3B) SDOR: SPI Dual Ouptut Read +- [ ] (0x3B) SDOR: SPI Dual Output Read - [ ] (0xBB) SDIOR: SPI Dual I/O Read - [ ] (0xC0) SB: Set Burst Length - [ ] (0x0C) RBSQI: SQI Read Burst with Wrap @@ -42,7 +42,7 @@ Write - [ ] (0x20) SE: Erase 4 KBytes of memory array - [ ] (0xD8) BE: Erase 64, 32, or 8 KBytes of memory array - [ ] (0xC7) CE: Full chip erase -- [ ] (0x02) PP: Page program +- [x] (0x02) PP: Page program - [ ] (0x32) SPI Quad page program - [ ] (0xB0) WRSU: Suspend program/erase - [ ] (0x30) WRRE: Resume Program/erase diff --git a/verif/cocotb/ahb_qspi_cocotb.v b/verif/cocotb/ahb_qspi_cocotb.v index f8cefd5c725df7d6980400751d0c588fc636bff8..119ef53a56429af893686de30e76c45e7e686976 100644 --- a/verif/cocotb/ahb_qspi_cocotb.v +++ b/verif/cocotb/ahb_qspi_cocotb.v @@ -1,4 +1,4 @@ -`timescale 1ns/1ps +`timescale 1ns/10ps module ahb_qspi_cocotb( input wire HCLK, @@ -10,7 +10,6 @@ module ahb_qspi_cocotb( input wire config_HWRITE, input wire [2:0] config_HSIZE, input wire [2:0] config_HBURST, - input wire [3:0] config_HPROT, input wire [32-1:0] config_HWDATA, input wire config_HSEL, output wire [32-1:0] config_HRDATA, @@ -23,7 +22,6 @@ module ahb_qspi_cocotb( input wire data_HWRITE, input wire [2:0] data_HSIZE, input wire [2:0] data_HBURST, - input wire [3:0] data_HPROT, input wire [32-1:0] data_HWDATA, input wire data_HSEL, output wire [32-1:0] data_HRDATA, @@ -37,8 +35,10 @@ begin $dumpfile("ahb_qspi.vcd"); $dumpvars; end - - +wire [3:0] config_HPROT; +wire [3:0] data_HPROT; +assign config_HPROT = 4'b0010; +assign data_HPROT = 4'b1000; wire [15:0] PADDR; wire [2:0] PPROT; wire PSEL; diff --git a/verif/cocotb/ahb_qspi_tests.py b/verif/cocotb/ahb_qspi_tests.py index 313fc29d69fc2a759d223047d0e641f97d09fb0c..db7677951498280dd8419af6fb7bd61a08f4c36a 100644 --- a/verif/cocotb/ahb_qspi_tests.py +++ b/verif/cocotb/ahb_qspi_tests.py @@ -22,9 +22,9 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - cocotb.start_soon(Clock(dut.HCLK, 4.166, units="ns").start()) - self.config_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"config", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST", "hprot":"HPROT"}), dut.HCLK, dut.HRESETn) - self.data_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"data", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST", "hprot":"HPROT"}), dut.HCLK, dut.HRESETn) + cocotb.start_soon(Clock(dut.HCLK, 5, units="ns").start()) + self.config_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"config", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST"}), dut.HCLK, dut.HRESETn) + self.data_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"data", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST"}), dut.HCLK, dut.HRESETn) async def cycle_reset(self): self.dut.HRESETn.setimmediatevalue(0) @@ -33,16 +33,11 @@ class TB: await ClockCycles(self.dut.HCLK,10) -@cocotb.test() -async def CACHE_CONFIG(dut): - tb = TB(dut) - await tb.cycle_reset() - data = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR,4) - # 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) +async def CACHE_READ(dut,tb): + data = await tb.data_ahb_master.read(0x00,4) + return int(data[0]['data'],16) + async def SPI_RESET(dut,tb): await tb.config_ahb_master.write(0x08, 0x00000066) await tb.config_ahb_master.write(0x08, 0x00000166) @@ -68,8 +63,7 @@ async def SPI_READ_JEDIC(dut, tb): 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 + return int(ID[0]['data'],16) async def SET_QPI_MODE(dut,tb): await tb.config_ahb_master.write(0x08, 0x00000038) @@ -80,6 +74,15 @@ async def SET_QPI_MODE(dut,tb): await ClockCycles(dut.HCLK,2) data = await tb.config_ahb_master.read(0x04,4) +async def LEAVE_QPI_MODE(dut, tb): + await tb.config_ahb_master.write(0x08, 0x000000FF) + await tb.config_ahb_master.write(0x08, 0x000001FF) + + 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) @@ -88,8 +91,7 @@ async def QPI_READ_JEDIC(dut, tb): 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 + return int(ID[0]['data'],16) async def SPI_WRITE_ENABLE(dut, tb): await tb.config_ahb_master.write(0x08, 0x00000006) @@ -139,7 +141,7 @@ async def SPI_BLOCK_ERASE(dut, tb): 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): + while(SPI_STAT&(1<<24)): SPI_STAT = await SPI_READ_STAT_REG(dut, tb) await Timer(time=1, units='ms') @@ -166,63 +168,249 @@ async def SPI_READ_SLOW(dut, tb): rData = await tb.config_ahb_master.read(0x10,4) print(rData) -async def QPI_READ(dut,tb): +async def QPI_READ_WORDS(dut,tb, addr =0, n_words=1, cont_read = False): # Write Adress - await tb.config_ahb_master.write(0x0C, 0x000000) + await tb.config_ahb_master.write(0x0C, addr) + + if(cont_read==True): + QSPI_CTRL_REG = await tb.config_ahb_master.read(0x00,4) + QSPI_CTRL_REG = int(QSPI_CTRL_REG[0]['data'],16) + QSPI_CTRL_REG = QSPI_CTRL_REG | ((0xA0<<16) + (1<<24)) + await tb.config_ahb_master.write(0x00, QSPI_CTRL_REG) + QSPI_DUMMY_CYCLES = 4 + else: + QSPI_DUMMY_CYCLES = 6 - await tb.config_ahb_master.write(0x08, 0x36A0B) - await tb.config_ahb_master.write(0x08, 0x36B0B) + + QSPI_CMD = 0x0B + QSPI_READ = 1 + QSPI_WRITE = 0 + QSPI_ADDR_EN = 1 + QSPI_N_RW_BYTES = n_words*4 - 1 + + QSPI_INSTR = QSPI_CMD + QSPI_INSTR += QSPI_READ<<9 + QSPI_INSTR += QSPI_WRITE<<10 + QSPI_INSTR += QSPI_ADDR_EN<<11 + QSPI_INSTR += QSPI_DUMMY_CYCLES<<12 + QSPI_INSTR += QSPI_N_RW_BYTES << 16 + + await tb.config_ahb_master.write(0x08, QSPI_INSTR) + QSPI_INSTR = QSPI_INSTR ^ (1<<8) + await tb.config_ahb_master.write(0x08, QSPI_INSTR) + 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) + + apb_r_addrs=[0x10, 0x14, 0x18, 0x1C] + rData = [] + for i in range(0,n_words): + rData_temp = await tb.config_ahb_master.read(apb_r_addrs[i],4) + rData.append(int(rData_temp[0]['data'],16)) + return rData -async def QPI_PAGE_PROGRAM(dut, tb): +async def QPI_PAGE_PROGRAM(dut, tb, addr = 0, words=0, n_words = 1): # Write Adress - await tb.config_ahb_master.write(0x0C, 0x000000) + await tb.config_ahb_master.write(0x0C, addr) # 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) + + apb_addrs = [0x20, 0x24, 0x28, 0x2C] + + for i in range(0,n_words): + await tb.config_ahb_master.write(apb_addrs[i], words[i]) + + QSPI_CMD = 0x02 + QSPI_READ = 0 + QSPI_WRITE = 1 + QSPI_ADDR_EN = 1 + QSPI_DUMMY_CYCLES = 0 + QSPI_N_RW_BYTES = n_words*4 - 1 + + QSPI_INSTR = QSPI_CMD + QSPI_INSTR += QSPI_READ<<9 + QSPI_INSTR += QSPI_WRITE<<10 + QSPI_INSTR += QSPI_ADDR_EN<<11 + QSPI_INSTR += QSPI_DUMMY_CYCLES<<12 + QSPI_INSTR += QSPI_N_RW_BYTES << 16 - await tb.config_ahb_master.write(0x08, 0x30C02) - await tb.config_ahb_master.write(0x08, 0x30D02) + await tb.config_ahb_master.write(0x08, QSPI_INSTR) + QSPI_INSTR = QSPI_INSTR ^ (1<<8) + await tb.config_ahb_master.write(0x08, QSPI_INSTR) + 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): + while(SPI_STAT&(1<<24)): SPI_STAT = await SPI_READ_STAT_REG(dut, tb) - await Timer(time=10, units='us') + await Timer(time=100, units='us') + + @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) + + ID = 0x4326BF00 + rID = await SPI_READ_JEDIC(dut, tb) + print(rID) + assert rID == ID + await SET_QPI_MODE(dut, tb) await tb.config_ahb_master.write(0x00,0x1) - await QPI_READ_JEDIC(dut, tb) + rID = await QPI_READ_JEDIC(dut, tb) + print(rID) + assert rID == ID + await SPI_WRITE_ENABLE(dut, tb) + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + WEL = SPI_STAT & (1<<25) + assert WEL != 0 + await SPI_CLR_PROTECTION(dut, tb) await SPI_WRITE_ENABLE(dut, tb) + SPI_STAT = await SPI_READ_STAT_REG(dut, tb) + WEL = SPI_STAT & (1<<25) + assert WEL != 0 + + # Write and read 32-bit word + data = [0x18273456] + await QPI_PAGE_PROGRAM(dut, tb, words=data, n_words=1) + + await SPI_WRITE_DISABLE(dut,tb) + rdata = await QPI_READ_WORDS(dut, tb, n_words=1) + assert rdata == data + + # Write and read 2x 32=bit words + data = [0x01234567, 0x89ABCDEF] + await SPI_WRITE_ENABLE(dut, tb) + await QPI_PAGE_PROGRAM(dut, tb, addr=0x100, words=data, n_words=2) + + await SPI_WRITE_DISABLE(dut,tb) + rdata = await QPI_READ_WORDS(dut, tb, addr=0x100, n_words=2) + assert rdata == data + + # Write and read 3x 32=bit words + data = [0x13243546, 0x97867564, 0x01234567] + await SPI_WRITE_ENABLE(dut, tb) + await QPI_PAGE_PROGRAM(dut, tb, addr=0x200, words=data, n_words=3) - await QPI_PAGE_PROGRAM(dut, tb) + await SPI_WRITE_DISABLE(dut,tb) + rdata = await QPI_READ_WORDS(dut, tb, addr=0x200, n_words=3) + assert rdata == data + + # Write and read 4x 32=bit words + data = [0x13243546, 0x97867564, 0x89ABCDEF, 0x01234567] + await SPI_WRITE_ENABLE(dut, tb) + await QPI_PAGE_PROGRAM(dut, tb, addr=0x300, words=data, n_words=4) await SPI_WRITE_DISABLE(dut,tb) - await QPI_READ(dut, tb) + rdata = await QPI_READ_WORDS(dut, tb, addr=0x300, n_words=4) + assert rdata == data + + await LEAVE_QPI_MODE(dut, tb) + await tb.config_ahb_master.write(0x00,0x1) + + + + +@cocotb.test() +async def QSPI_READ_TESTS(dut): + tb = TB(dut) + await tb.cycle_reset() - #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) + await SPI_RESET(dut, tb) + + ID = 0x4326BF00 + rID = await SPI_READ_JEDIC(dut, tb) + print(rID) + assert rID == ID + + await SET_QPI_MODE(dut, tb) + await tb.config_ahb_master.write(0x00,0x1) + rID = await QPI_READ_JEDIC(dut, tb) + print(rID) + assert rID == ID + + rDATA = await QPI_READ_WORDS(dut, tb, addr=0x10000, n_words=4, cont_read=True) + QSPI_CTRL_REG = await tb.config_ahb_master.read(0x00,4) + QSPI_CTRL_REG = int(QSPI_CTRL_REG[0]['data'],16) + QSPI_CTRL_REG = QSPI_CTRL_REG | (1<<25) + await tb.config_ahb_master.write(0x00, QSPI_CTRL_REG) + + n_reads = 64 + + start_time = cocotb.utils.get_sim_time(units='ns') + for i in range(0,n_reads): + rDATA = await QPI_READ_WORDS(dut, tb, addr=0x10000, n_words=4, cont_read=True) + end_time = cocotb.utils.get_sim_time(units='ns') + dt= end_time-start_time + + QSPI_CTRL_REG = await tb.config_ahb_master.read(0x00,4) + QSPI_CTRL_REG = int(QSPI_CTRL_REG[0]['data'],16) + QSPI_CTRL_REG = QSPI_CTRL_REG | (1<<8) + await tb.config_ahb_master.write(0x00, QSPI_CTRL_REG) - \ No newline at end of file + CACHE_STATUS_tmp = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR+0x04,4) + CACHE_STATUS = int(CACHE_STATUS_tmp[0]['data'],16) + assert CACHE_STATUS==0 + + await tb.config_ahb_master.write(CACHE_CONFIG_ADDR, 0x21) + + CACHE_STATUS_tmp = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR+0x04,4) + CACHE_STATUS = int(CACHE_STATUS_tmp[0]['data'],16) + while((CACHE_STATUS&(0x3))==0): + CACHE_STATUS_tmp = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR+0x04,4) + CACHE_STATUS = int(CACHE_STATUS_tmp[0]['data'],16) + await Timer(time=10, units='us') + print(CACHE_STATUS) + + + + + start_time_uncached = cocotb.utils.get_sim_time(units='ns') + for i in range(0,n_reads): + data = await tb.data_ahb_master.read(i*4,4) + end_time_uncached = cocotb.utils.get_sim_time(units='ns') + dt_uncached = end_time_uncached - start_time_uncached + + start_time_cached = cocotb.utils.get_sim_time(units='ns') + for i in range(0,n_reads): + data = await tb.data_ahb_master.read(i*4,4) + end_time_cached = cocotb.utils.get_sim_time(units='ns') + dt_cached = end_time_cached - start_time_cached + + + await tb.config_ahb_master.write(0x00, 0x01) + + await tb.config_ahb_master.write(0x08, 0x0FF) + await tb.config_ahb_master.write(0x08, 0x1FF) + await tb.config_ahb_master.write(0x08, 0x0FF) + await tb.config_ahb_master.write(0x08, 0x1FF) + tb.log.info("Time taken = %f", dt) + BW = n_reads*4*32/(8*dt*1e-3) + BW_uncached = n_reads*4*32/(8*dt_uncached*1e-3) + BW_cached = n_reads*4*32/(8*dt_cached*1e-3) + + tb.log.info("Bandwidth: %f MB/s", BW) + tb.log.info("Bandwidth caching: %f MB/s", BW_uncached) + tb.log.info("Bandwidth cached: %f MB/s", BW_cached) + + +@cocotb.test() +async def CACHE_CONFIG(dut): + tb = TB(dut) + await tb.cycle_reset() + data = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR,4) + # 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)