From 55704f5c6582dcaa986f4cbb57017b6fa83b828b Mon Sep 17 00:00:00 2001 From: Daniel Newbrook <dwn1c21@soton.ac.uk> Date: Wed, 11 Jun 2025 21:49:45 +0100 Subject: [PATCH] Fix CDC issues when clock div greater than 2 --- .../logical/ahb_qspi_interface.sv | 6 ++-- .../qspi_controller/logical/qspi_clock_div.v | 2 +- .../logical/qspi_controller.sv | 18 +++++++--- verif/cocotb/ahb_qspi_tests.py | 36 ++++++++++++++++--- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv b/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv index e45a804..8f73eb9 100644 --- a/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv +++ b/logical/ahb_qspi_interface/logical/ahb_qspi_interface.sv @@ -120,11 +120,12 @@ always @(posedge HCLK or negedge HRESETn) 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) + if(AHB_QSPI_ENABLE_ACK) begin AHB_QSPI_ENABLE <= 1'b0; + qspi_started <= 1'b1; + end if(qspi_started==1'b1) begin if(AHB_QSPI_BUSY==1'b0) begin HRDATA <= AHB_QSPI_RDATA_i; @@ -132,6 +133,7 @@ always @(posedge HCLK or negedge HRESETn) begin end end end else begin + AHB_QSPI_ENABLE <= 1'b0; qspi_started <= 1'b0; qspi_ready <=1'b0; AHB_QSPI_ADDR <= {HADDR[ADDR_W-1:4],4'b0000}; diff --git a/logical/qspi_controller/logical/qspi_clock_div.v b/logical/qspi_controller/logical/qspi_clock_div.v index 7ece179..d4761af 100644 --- a/logical/qspi_controller/logical/qspi_clock_div.v +++ b/logical/qspi_controller/logical/qspi_clock_div.v @@ -21,8 +21,8 @@ always @(posedge HCLK or negedge HRESETn) begin 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 QSPI_SCLK_reg <= ~QSPI_SCLK_reg; + end else begin QSPI_CLK_DIV_COUNTER <= QSPI_CLK_DIV_COUNTER + 1; end end else begin diff --git a/logical/qspi_controller/logical/qspi_controller.sv b/logical/qspi_controller/logical/qspi_controller.sv index 6e239ef..628079d 100644 --- a/logical/qspi_controller/logical/qspi_controller.sv +++ b/logical/qspi_controller/logical/qspi_controller.sv @@ -52,6 +52,16 @@ reg [3:0] QSPI_IO_o_reg; reg [127:0] data_in_reg; reg [21:0] last_QSPI_ADDR; +reg QSPI_enable_sync; + +always @(posedge QSPI_SCLK_i or negedge HRESETn) begin + if(~HRESETn)begin + QSPI_enable_sync <= 1'b0; + end else begin + QSPI_enable_sync <= QSPI_ENABLE; + end +end + reg [127:0] QSPI_WDATA_reg; assign QSPI_IO_o = QSPI_IO_o_reg; @@ -67,9 +77,9 @@ end always_comb begin case(current_state) IDLE: begin - if(QSPI_ENABLE==1'b1 && QSPI_NO_CMD==1'b0) begin + if(QSPI_enable_sync==1'b1 && QSPI_NO_CMD==1'b0) begin next_state = OP; - end else if(QSPI_ENABLE==1'b1 && QSPI_NO_CMD==1'b1) begin + end else if(QSPI_enable_sync==1'b1 && QSPI_NO_CMD==1'b1) begin if(last_QSPI_ADDR==QSPI_ADDR) next_state = NO_FETCH; else @@ -82,7 +92,7 @@ always_comb begin end NO_FETCH: begin QSPI_ENABLE_ACK = 1'b1; - if(QSPI_ENABLE==1'b0) + if(QSPI_enable_sync==1'b0) next_state = IDLE; end OP: begin @@ -374,7 +384,7 @@ always_comb begin end end -assign QSPI_nCS = ((QSPI_ENABLE==1'b1) ||(current_state!=IDLE) || (QSPI_SCLK_e==1'b1))?1'b0:1'b1; +assign QSPI_nCS = ((QSPI_enable_sync==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; diff --git a/verif/cocotb/ahb_qspi_tests.py b/verif/cocotb/ahb_qspi_tests.py index 9fd5858..e756259 100644 --- a/verif/cocotb/ahb_qspi_tests.py +++ b/verif/cocotb/ahb_qspi_tests.py @@ -27,8 +27,8 @@ class TB: self.log.setLevel(logging.DEBUG) self.dut.HRESETn.setimmediatevalue(0) cocotb.start_soon(Clock(dut.HCLK, 10, 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) + self.config_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"config", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST"}), dut.HCLK, dut.HRESETn, 500) + self.data_ahb_master = AHBLiteMaster(AHBBus.from_prefix(dut,"data", optional_signals = {"hsel":"HSEL", "hready_in":"HREADY_IN", "hburst":"HBURST"}), dut.HCLK, dut.HRESETn, 500) async def cycle_reset(self): await ClockCycles(self.dut.HCLK,1) @@ -228,7 +228,6 @@ async def QSPI_READ_TESTS(dut): tb.log.info("Read %d x 16-bytes over AHB (uncached)",n_reads) start_time_uncached = cocotb.utils.get_sim_time(units='ns') for i in range(0,n_reads*4): - tb.log.info("Read %d ",i) rdata = await tb.data_ahb_master.read(i*4 + base_addr,4) assert int(rdata[0]['data'],16)==data[i%4] end_time_uncached = cocotb.utils.get_sim_time(units='ns') @@ -243,6 +242,32 @@ async def QSPI_READ_TESTS(dut): end_time_cached = cocotb.utils.get_sim_time(units='ns') dt_cached = end_time_cached - start_time_cached + await tb.config_ahb_master.write(0x34, 0x05) + tb.log.info("Clock divider changed") + + await tb.config_ahb_master.write(CACHE_CONFIG_ADDR, 0x0) + tb.log.info("Disable Cache") + CACHE_CONFIG_tmp = await tb.config_ahb_master.read(CACHE_CONFIG_ADDR,4) + CACHE_CONFIG = int(CACHE_CONFIG_tmp[0]['data'],16) + assert CACHE_CONFIG == 0x0 + + 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+0x00,4) + 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') + + + tb.log.info("Read 512x 16-bytes over AHB (uncached)") + start_time_slow = cocotb.utils.get_sim_time(units='ns') + for i in range(0,n_reads*4): + rdata = await tb.data_ahb_master.read(i*4+ base_addr,4) + assert int(rdata[0]['data'],16)==data[i%4] + end_time_slow = cocotb.utils.get_sim_time(units='ns') + dt_slow = end_time_slow - start_time_slow + await tb.config_ahb_master.write(0x00, 0x01) @@ -254,15 +279,18 @@ async def QSPI_READ_TESTS(dut): BW = n_reads*4/(dt*1e-3) BW_uncached = n_reads*4/(dt_uncached*1e-3) BW_cached = n_reads*4/(dt_cached*1e-3) - + BW_slow = n_reads*4/(dt_slow*1e-3) + tb.log.info("dt APB: %f ns", dt) tb.log.info("dt caching: %f ns", dt_uncached) tb.log.info("dt cached: %f ns", dt_cached) + tb.log.info("dt slow: %f ns", dt_slow) tb.log.info("Bandwidth APB: %f MB/s", BW) tb.log.info("Bandwidth caching: %f MB/s", BW_uncached) tb.log.info("Bandwidth cached: %f MB/s", BW_cached) + tb.log.info("Bandwidth slow: %f MB/s", BW_slow) @cocotb.test() -- GitLab