From ccd47477004798aa8bbb4e3dd02138943a673a73 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Thu, 21 May 2026 23:15:58 +0200 Subject: [PATCH 1/5] Add PeakRDL config register generation --- Bender.yml | 2 + Makefile | 3 + docs/regs/hyperbus_cfg_regs.md | 275 ++++++++ include/hyperbus_cfg_regs.h | 164 +++++ scripts/gen_regs.sh | 46 ++ src/regs/hyperbus_cfg_regblock.sv | 933 ++++++++++++++++++++++++++ src/regs/hyperbus_cfg_regblock_pkg.sv | 192 ++++++ src/regs/hyperbus_cfg_regs.rdl | 101 +++ 8 files changed, 1716 insertions(+) create mode 100644 docs/regs/hyperbus_cfg_regs.md create mode 100644 include/hyperbus_cfg_regs.h create mode 100755 scripts/gen_regs.sh create mode 100644 src/regs/hyperbus_cfg_regblock.sv create mode 100644 src/regs/hyperbus_cfg_regblock_pkg.sv create mode 100644 src/regs/hyperbus_cfg_regs.rdl diff --git a/Bender.yml b/Bender.yml index de23acc..04062ce 100644 --- a/Bender.yml +++ b/Bender.yml @@ -41,6 +41,7 @@ sources: files: - src/hyperbus_delay.sv + - src/regs/hyperbus_cfg_regblock_pkg.sv - src/hyperbus_pkg.sv - src/hyperbus_clk_gen.sv - src/hyperbus_clock_diff_out.sv @@ -48,6 +49,7 @@ sources: - src/hyperbus_phy2r.sv - src/hyperbus_ddr_out.sv - src/hyperbus_trx.sv + - src/regs/hyperbus_cfg_regblock.sv - src/hyperbus_cfg_regs.sv - src/hyperbus_phy.sv - src/hyperbus_phy_if.sv diff --git a/Makefile b/Makefile index 5a927dc..2d85965 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,9 @@ all: build run clean: sim_clean +update-regs: + bash scripts/gen_regs.sh + # Ensure half-built targets are purged .DELETE_ON_ERROR: diff --git a/docs/regs/hyperbus_cfg_regs.md b/docs/regs/hyperbus_cfg_regs.md new file mode 100644 index 0000000..8e995aa --- /dev/null +++ b/docs/regs/hyperbus_cfg_regs.md @@ -0,0 +1,275 @@ + + +## hyperbus_cfg_regs address map + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x50 + +|Offset| Identifier |Name| +|------|---------------------|----| +| 0x00 | t_latency_access | — | +| 0x04 |en_latency_additional| — | +| 0x08 | t_burst_max | — | +| 0x0C |t_read_write_recovery| — | +| 0x10 | t_rx_clk_delay | — | +| 0x14 | t_tx_clk_delay | — | +| 0x18 | address_mask_msb | — | +| 0x1C | address_space | — | +| 0x20 | phys_in_use | — | +| 0x24 | which_phy | — | +| 0x28 | t_csh_cycles | — | +| 0x2C | csn_to_ck_cycles | — | +| 0x30 | chip0_base | — | +| 0x34 | chip0_bound | — | +| 0x38 | chip1_base | — | +| 0x3C | chip1_bound | — | +| 0x40 | chip2_base | — | +| 0x44 | chip2_bound | — | +| 0x48 | chip3_base | — | +| 0x4C | chip3_bound | — | + +### t_latency_access register + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x4 + +

Initial latency cycles before read or write data.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 3:0| value | rw | 0x6 | — | + +### en_latency_additional register + +- Absolute Address: 0x4 +- Base Offset: 0x4 +- Size: 0x4 + +

Enable additional latency cycles when requested by RWDS.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 0 | value | rw | 0x0 | — | + +### t_burst_max register + +- Absolute Address: 0x8 +- Base Offset: 0x8 +- Size: 0x4 + +

Maximum continuous burst length before the PHY restarts a transfer.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +|15:0| value | rw |0x15E| — | + +### t_read_write_recovery register + +- Absolute Address: 0xC +- Base Offset: 0xC +- Size: 0x4 + +

Recovery cycles inserted between read and write phases.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 3:0| value | rw | 0x6 | — | + +### t_rx_clk_delay register + +- Absolute Address: 0x10 +- Base Offset: 0x10 +- Size: 0x4 + +

RX sampling delay-line tap setting.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 7:0| value | rw | 0x10| — | + +### t_tx_clk_delay register + +- Absolute Address: 0x14 +- Base Offset: 0x14 +- Size: 0x4 + +

TX clock delay-line tap setting.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 7:0| value | rw | 0x10| — | + +### address_mask_msb register + +- Absolute Address: 0x18 +- Base Offset: 0x18 +- Size: 0x4 + +

Most-significant address bit used by frontend address packing.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 4:0| value | rw | 0x19| — | + +### address_space register + +- Absolute Address: 0x1C +- Base Offset: 0x1C +- Size: 0x4 + +

Select HyperRAM or HyperFlash address-space interpretation.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 0 | value | rw | 0x0 | — | + +### phys_in_use register + +- Absolute Address: 0x20 +- Base Offset: 0x20 +- Size: 0x4 + +

Select whether one or both PHY lanes are active.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 0 | value | rw | 0x1 | — | + +### which_phy register + +- Absolute Address: 0x24 +- Base Offset: 0x24 +- Size: 0x4 + +

Select the PHY lane used when only one PHY is active.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 0 | value | rw | 0x1 | — | + +### t_csh_cycles register + +- Absolute Address: 0x28 +- Base Offset: 0x28 +- Size: 0x4 + +

Chip-select high time between transfers.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 3:0| value | rw | 0x1 | — | + +### csn_to_ck_cycles register + +- Absolute Address: 0x2C +- Base Offset: 0x2C +- Size: 0x4 + +

Delay cycles from chip-select assertion to clock start.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +| 3:0| value | rw | 0x0 | — | + +### chip0_base register + +- Absolute Address: 0x30 +- Base Offset: 0x30 +- Size: 0x4 + +

Inclusive base address for chip-select 0 decoding.

+ +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +|31:0| value | rw | 0x0 | — | + +### chip0_bound register + +- Absolute Address: 0x34 +- Base Offset: 0x34 +- Size: 0x4 + +

Exclusive bound address for chip-select 0 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x10000| — | + +### chip1_base register + +- Absolute Address: 0x38 +- Base Offset: 0x38 +- Size: 0x4 + +

Inclusive base address for chip-select 1 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x10000| — | + +### chip1_bound register + +- Absolute Address: 0x3C +- Base Offset: 0x3C +- Size: 0x4 + +

Exclusive bound address for chip-select 1 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x20000| — | + +### chip2_base register + +- Absolute Address: 0x40 +- Base Offset: 0x40 +- Size: 0x4 + +

Inclusive base address for chip-select 2 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x20000| — | + +### chip2_bound register + +- Absolute Address: 0x44 +- Base Offset: 0x44 +- Size: 0x4 + +

Exclusive bound address for chip-select 2 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x30000| — | + +### chip3_base register + +- Absolute Address: 0x48 +- Base Offset: 0x48 +- Size: 0x4 + +

Inclusive base address for chip-select 3 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x30000| — | + +### chip3_bound register + +- Absolute Address: 0x4C +- Base Offset: 0x4C +- Size: 0x4 + +

Exclusive bound address for chip-select 3 decoding.

+ +|Bits|Identifier|Access| Reset |Name| +|----|----------|------|-------|----| +|31:0| value | rw |0x40000| — | diff --git a/include/hyperbus_cfg_regs.h b/include/hyperbus_cfg_regs.h new file mode 100644 index 0000000..795ce1b --- /dev/null +++ b/include/hyperbus_cfg_regs.h @@ -0,0 +1,164 @@ +// Generated by PeakRDL-cheader - A free and open-source header generator +// https://github.com/SystemRDL/PeakRDL-cheader + +#ifndef HYPERBUS_CFG_REGS_H +#define HYPERBUS_CFG_REGS_H + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include + +// reg - hyperbus_cfg_regs::t_latency_access +#define HYPERBUS_CFG_REGS__T_LATENCY_ACCESS__VALUE_bm 0xf +#define HYPERBUS_CFG_REGS__T_LATENCY_ACCESS__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_LATENCY_ACCESS__VALUE_bw 4 +#define HYPERBUS_CFG_REGS__T_LATENCY_ACCESS__VALUE_reset 0x6 + +// reg - hyperbus_cfg_regs::en_latency_additional +#define HYPERBUS_CFG_REGS__EN_LATENCY_ADDITIONAL__VALUE_bm 0x1 +#define HYPERBUS_CFG_REGS__EN_LATENCY_ADDITIONAL__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__EN_LATENCY_ADDITIONAL__VALUE_bw 1 +#define HYPERBUS_CFG_REGS__EN_LATENCY_ADDITIONAL__VALUE_reset 0x0 + +// reg - hyperbus_cfg_regs::t_burst_max +#define HYPERBUS_CFG_REGS__T_BURST_MAX__VALUE_bm 0xffff +#define HYPERBUS_CFG_REGS__T_BURST_MAX__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_BURST_MAX__VALUE_bw 16 +#define HYPERBUS_CFG_REGS__T_BURST_MAX__VALUE_reset 0x15e + +// reg - hyperbus_cfg_regs::t_read_write_recovery +#define HYPERBUS_CFG_REGS__T_READ_WRITE_RECOVERY__VALUE_bm 0xf +#define HYPERBUS_CFG_REGS__T_READ_WRITE_RECOVERY__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_READ_WRITE_RECOVERY__VALUE_bw 4 +#define HYPERBUS_CFG_REGS__T_READ_WRITE_RECOVERY__VALUE_reset 0x6 + +// reg - hyperbus_cfg_regs::t_rx_clk_delay +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bm 0xff +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bw 8 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_reset 0x10 + +// reg - hyperbus_cfg_regs::t_tx_clk_delay +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bm 0xff +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bw 8 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_reset 0x10 + +// reg - hyperbus_cfg_regs::address_mask_msb +#define HYPERBUS_CFG_REGS__ADDRESS_MASK_MSB__VALUE_bm 0x1f +#define HYPERBUS_CFG_REGS__ADDRESS_MASK_MSB__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__ADDRESS_MASK_MSB__VALUE_bw 5 +#define HYPERBUS_CFG_REGS__ADDRESS_MASK_MSB__VALUE_reset 0x19 + +// reg - hyperbus_cfg_regs::address_space +#define HYPERBUS_CFG_REGS__ADDRESS_SPACE__VALUE_bm 0x1 +#define HYPERBUS_CFG_REGS__ADDRESS_SPACE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__ADDRESS_SPACE__VALUE_bw 1 +#define HYPERBUS_CFG_REGS__ADDRESS_SPACE__VALUE_reset 0x0 + +// reg - hyperbus_cfg_regs::phys_in_use +#define HYPERBUS_CFG_REGS__PHYS_IN_USE__VALUE_bm 0x1 +#define HYPERBUS_CFG_REGS__PHYS_IN_USE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__PHYS_IN_USE__VALUE_bw 1 +#define HYPERBUS_CFG_REGS__PHYS_IN_USE__VALUE_reset 0x1 + +// reg - hyperbus_cfg_regs::which_phy +#define HYPERBUS_CFG_REGS__WHICH_PHY__VALUE_bm 0x1 +#define HYPERBUS_CFG_REGS__WHICH_PHY__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__WHICH_PHY__VALUE_bw 1 +#define HYPERBUS_CFG_REGS__WHICH_PHY__VALUE_reset 0x1 + +// reg - hyperbus_cfg_regs::t_csh_cycles +#define HYPERBUS_CFG_REGS__T_CSH_CYCLES__VALUE_bm 0xf +#define HYPERBUS_CFG_REGS__T_CSH_CYCLES__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__T_CSH_CYCLES__VALUE_bw 4 +#define HYPERBUS_CFG_REGS__T_CSH_CYCLES__VALUE_reset 0x1 + +// reg - hyperbus_cfg_regs::csn_to_ck_cycles +#define HYPERBUS_CFG_REGS__CSN_TO_CK_CYCLES__VALUE_bm 0xf +#define HYPERBUS_CFG_REGS__CSN_TO_CK_CYCLES__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CSN_TO_CK_CYCLES__VALUE_bw 4 +#define HYPERBUS_CFG_REGS__CSN_TO_CK_CYCLES__VALUE_reset 0x0 + +// reg - hyperbus_cfg_regs::chip0_base +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_reset 0x0 + +// reg - hyperbus_cfg_regs::chip0_bound +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_reset 0x10000 + +// reg - hyperbus_cfg_regs::chip1_base +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_reset 0x10000 + +// reg - hyperbus_cfg_regs::chip1_bound +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_reset 0x20000 + +// reg - hyperbus_cfg_regs::chip2_base +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_reset 0x20000 + +// reg - hyperbus_cfg_regs::chip2_bound +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_reset 0x30000 + +// reg - hyperbus_cfg_regs::chip3_base +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_reset 0x30000 + +// reg - hyperbus_cfg_regs::chip3_bound +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bm 0xffffffff +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bp 0 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_reset 0x40000 + +// addrmap - hyperbus_cfg_regs +typedef struct __attribute__ ((__packed__)) { + uint32_t t_latency_access; + uint32_t en_latency_additional; + uint32_t t_burst_max; + uint32_t t_read_write_recovery; + uint32_t t_rx_clk_delay; + uint32_t t_tx_clk_delay; + uint32_t address_mask_msb; + uint32_t address_space; + uint32_t phys_in_use; + uint32_t which_phy; + uint32_t t_csh_cycles; + uint32_t csn_to_ck_cycles; + uint32_t chip0_base; + uint32_t chip0_bound; + uint32_t chip1_base; + uint32_t chip1_bound; + uint32_t chip2_base; + uint32_t chip2_bound; + uint32_t chip3_base; + uint32_t chip3_bound; +} hyperbus_cfg_regs_t; + + +static_assert(sizeof(hyperbus_cfg_regs_t) == 0x50, "Packing error"); + +#ifdef __cplusplus +} +#endif + +#endif /* HYPERBUS_CFG_REGS_H */ diff --git a/scripts/gen_regs.sh b/scripts/gen_regs.sh new file mode 100755 index 0000000..3d625fc --- /dev/null +++ b/scripts/gen_regs.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright 2026 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +UV_CACHE_DIR="${UV_CACHE_DIR:-/tmp/uv-cache}" +UV_TOOL_DIR="${UV_TOOL_DIR:-/tmp/uv-tools}" +export UV_CACHE_DIR +export UV_TOOL_DIR + +RDL="${ROOT}/src/regs/hyperbus_cfg_regs.rdl" + +mkdir -p "${ROOT}/include" "${ROOT}/docs/regs" +rm -rf "${ROOT}/docs/regs/hyperbus_cfg_regs" + +uvx --from peakrdl-cli \ + --with peakrdl-regblock \ + --with peakrdl-cheader \ + --with peakrdl-markdown \ + peakrdl regblock \ + --cpuif apb4-flat \ + --default-reset arst_n \ + --module-name hyperbus_cfg_regblock \ + --package-name hyperbus_cfg_regblock_pkg \ + --addr-width 7 \ + -o "${ROOT}/src/regs" \ + "${RDL}" + +uvx --from peakrdl-cli \ + --with peakrdl-regblock \ + --with peakrdl-cheader \ + --with peakrdl-markdown \ + peakrdl c-header \ + -o "${ROOT}/include/hyperbus_cfg_regs.h" \ + "${RDL}" + +uvx --from peakrdl-cli \ + --with peakrdl-regblock \ + --with peakrdl-cheader \ + --with peakrdl-markdown \ + peakrdl markdown \ + -o "${ROOT}/docs/regs/hyperbus_cfg_regs.md" \ + "${RDL}" diff --git a/src/regs/hyperbus_cfg_regblock.sv b/src/regs/hyperbus_cfg_regblock.sv new file mode 100644 index 0000000..5cbcc73 --- /dev/null +++ b/src/regs/hyperbus_cfg_regblock.sv @@ -0,0 +1,933 @@ +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module hyperbus_cfg_regblock ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [6:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + output hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [6:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[6:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + + // Read & write latencies are balanced. Stalls not required + assign cpuif_req_stall_rd = '0; + assign cpuif_req_stall_wr = '0; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic t_latency_access; + logic en_latency_additional; + logic t_burst_max; + logic t_read_write_recovery; + logic t_rx_clk_delay; + logic t_tx_clk_delay; + logic address_mask_msb; + logic address_space; + logic phys_in_use; + logic which_phy; + logic t_csh_cycles; + logic csn_to_ck_cycles; + logic chip0_base; + logic chip0_bound; + logic chip1_base; + logic chip1_bound; + logic chip2_base; + logic chip2_bound; + logic chip3_base; + logic chip3_bound; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_err; + logic [6:0] decoded_addr; + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + automatic logic is_valid_addr; + automatic logic is_valid_rw; + is_valid_addr = '1; // No valid address check + is_valid_rw = '1; // No valid RW check + decoded_reg_strb.t_latency_access = cpuif_req_masked & (cpuif_addr == 7'h0); + decoded_reg_strb.en_latency_additional = cpuif_req_masked & (cpuif_addr == 7'h4); + decoded_reg_strb.t_burst_max = cpuif_req_masked & (cpuif_addr == 7'h8); + decoded_reg_strb.t_read_write_recovery = cpuif_req_masked & (cpuif_addr == 7'hc); + decoded_reg_strb.t_rx_clk_delay = cpuif_req_masked & (cpuif_addr == 7'h10); + decoded_reg_strb.t_tx_clk_delay = cpuif_req_masked & (cpuif_addr == 7'h14); + decoded_reg_strb.address_mask_msb = cpuif_req_masked & (cpuif_addr == 7'h18); + decoded_reg_strb.address_space = cpuif_req_masked & (cpuif_addr == 7'h1c); + decoded_reg_strb.phys_in_use = cpuif_req_masked & (cpuif_addr == 7'h20); + decoded_reg_strb.which_phy = cpuif_req_masked & (cpuif_addr == 7'h24); + decoded_reg_strb.t_csh_cycles = cpuif_req_masked & (cpuif_addr == 7'h28); + decoded_reg_strb.csn_to_ck_cycles = cpuif_req_masked & (cpuif_addr == 7'h2c); + decoded_reg_strb.chip0_base = cpuif_req_masked & (cpuif_addr == 7'h30); + decoded_reg_strb.chip0_bound = cpuif_req_masked & (cpuif_addr == 7'h34); + decoded_reg_strb.chip1_base = cpuif_req_masked & (cpuif_addr == 7'h38); + decoded_reg_strb.chip1_bound = cpuif_req_masked & (cpuif_addr == 7'h3c); + decoded_reg_strb.chip2_base = cpuif_req_masked & (cpuif_addr == 7'h40); + decoded_reg_strb.chip2_bound = cpuif_req_masked & (cpuif_addr == 7'h44); + decoded_reg_strb.chip3_base = cpuif_req_masked & (cpuif_addr == 7'h48); + decoded_reg_strb.chip3_bound = cpuif_req_masked & (cpuif_addr == 7'h4c); + decoded_err = '0; + end + + // Pass down signals to next stage + assign decoded_addr = cpuif_addr; + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + typedef struct { + struct { + struct { + logic [3:0] next; + logic load_next; + } value; + } t_latency_access; + struct { + struct { + logic next; + logic load_next; + } value; + } en_latency_additional; + struct { + struct { + logic [15:0] next; + logic load_next; + } value; + } t_burst_max; + struct { + struct { + logic [3:0] next; + logic load_next; + } value; + } t_read_write_recovery; + struct { + struct { + logic [7:0] next; + logic load_next; + } value; + } t_rx_clk_delay; + struct { + struct { + logic [7:0] next; + logic load_next; + } value; + } t_tx_clk_delay; + struct { + struct { + logic [4:0] next; + logic load_next; + } value; + } address_mask_msb; + struct { + struct { + logic next; + logic load_next; + } value; + } address_space; + struct { + struct { + logic next; + logic load_next; + } value; + } phys_in_use; + struct { + struct { + logic next; + logic load_next; + } value; + } which_phy; + struct { + struct { + logic [3:0] next; + logic load_next; + } value; + } t_csh_cycles; + struct { + struct { + logic [3:0] next; + logic load_next; + } value; + } csn_to_ck_cycles; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip0_base; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip0_bound; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip1_base; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip1_bound; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip2_base; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip2_bound; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip3_base; + struct { + struct { + logic [31:0] next; + logic load_next; + } value; + } chip3_bound; + } field_combo_t; + field_combo_t field_combo; + + typedef struct { + struct { + struct { + logic [3:0] value; + } value; + } t_latency_access; + struct { + struct { + logic value; + } value; + } en_latency_additional; + struct { + struct { + logic [15:0] value; + } value; + } t_burst_max; + struct { + struct { + logic [3:0] value; + } value; + } t_read_write_recovery; + struct { + struct { + logic [7:0] value; + } value; + } t_rx_clk_delay; + struct { + struct { + logic [7:0] value; + } value; + } t_tx_clk_delay; + struct { + struct { + logic [4:0] value; + } value; + } address_mask_msb; + struct { + struct { + logic value; + } value; + } address_space; + struct { + struct { + logic value; + } value; + } phys_in_use; + struct { + struct { + logic value; + } value; + } which_phy; + struct { + struct { + logic [3:0] value; + } value; + } t_csh_cycles; + struct { + struct { + logic [3:0] value; + } value; + } csn_to_ck_cycles; + struct { + struct { + logic [31:0] value; + } value; + } chip0_base; + struct { + struct { + logic [31:0] value; + } value; + } chip0_bound; + struct { + struct { + logic [31:0] value; + } value; + } chip1_base; + struct { + struct { + logic [31:0] value; + } value; + } chip1_bound; + struct { + struct { + logic [31:0] value; + } value; + } chip2_base; + struct { + struct { + logic [31:0] value; + } value; + } chip2_bound; + struct { + struct { + logic [31:0] value; + } value; + } chip3_base; + struct { + struct { + logic [31:0] value; + } value; + } chip3_bound; + } field_storage_t; + field_storage_t field_storage; + + // Field: hyperbus_cfg_regs.t_latency_access.value + always_comb begin + automatic logic [3:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_latency_access.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_latency_access && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_latency_access.value.value & ~decoded_wr_biten[3:0]) | (decoded_wr_data[3:0] & decoded_wr_biten[3:0]); + load_next_c = '1; + end + field_combo.t_latency_access.value.next = next_c; + field_combo.t_latency_access.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_latency_access.value.value <= 4'h6; + end else begin + if(field_combo.t_latency_access.value.load_next) begin + field_storage.t_latency_access.value.value <= field_combo.t_latency_access.value.next; + end + end + end + assign hwif_out.t_latency_access.value.value = field_storage.t_latency_access.value.value; + // Field: hyperbus_cfg_regs.en_latency_additional.value + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.en_latency_additional.value.value; + load_next_c = '0; + if(decoded_reg_strb.en_latency_additional && decoded_req_is_wr) begin // SW write + next_c = (field_storage.en_latency_additional.value.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.en_latency_additional.value.next = next_c; + field_combo.en_latency_additional.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.en_latency_additional.value.value <= 1'h0; + end else begin + if(field_combo.en_latency_additional.value.load_next) begin + field_storage.en_latency_additional.value.value <= field_combo.en_latency_additional.value.next; + end + end + end + assign hwif_out.en_latency_additional.value.value = field_storage.en_latency_additional.value.value; + // Field: hyperbus_cfg_regs.t_burst_max.value + always_comb begin + automatic logic [15:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_burst_max.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_burst_max && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_burst_max.value.value & ~decoded_wr_biten[15:0]) | (decoded_wr_data[15:0] & decoded_wr_biten[15:0]); + load_next_c = '1; + end + field_combo.t_burst_max.value.next = next_c; + field_combo.t_burst_max.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_burst_max.value.value <= 16'h15e; + end else begin + if(field_combo.t_burst_max.value.load_next) begin + field_storage.t_burst_max.value.value <= field_combo.t_burst_max.value.next; + end + end + end + assign hwif_out.t_burst_max.value.value = field_storage.t_burst_max.value.value; + // Field: hyperbus_cfg_regs.t_read_write_recovery.value + always_comb begin + automatic logic [3:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_read_write_recovery.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_read_write_recovery && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_read_write_recovery.value.value & ~decoded_wr_biten[3:0]) | (decoded_wr_data[3:0] & decoded_wr_biten[3:0]); + load_next_c = '1; + end + field_combo.t_read_write_recovery.value.next = next_c; + field_combo.t_read_write_recovery.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_read_write_recovery.value.value <= 4'h6; + end else begin + if(field_combo.t_read_write_recovery.value.load_next) begin + field_storage.t_read_write_recovery.value.value <= field_combo.t_read_write_recovery.value.next; + end + end + end + assign hwif_out.t_read_write_recovery.value.value = field_storage.t_read_write_recovery.value.value; + // Field: hyperbus_cfg_regs.t_rx_clk_delay.value + always_comb begin + automatic logic [7:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_rx_clk_delay.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_rx_clk_delay && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_rx_clk_delay.value.value & ~decoded_wr_biten[7:0]) | (decoded_wr_data[7:0] & decoded_wr_biten[7:0]); + load_next_c = '1; + end + field_combo.t_rx_clk_delay.value.next = next_c; + field_combo.t_rx_clk_delay.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_rx_clk_delay.value.value <= 8'h10; + end else begin + if(field_combo.t_rx_clk_delay.value.load_next) begin + field_storage.t_rx_clk_delay.value.value <= field_combo.t_rx_clk_delay.value.next; + end + end + end + assign hwif_out.t_rx_clk_delay.value.value = field_storage.t_rx_clk_delay.value.value; + // Field: hyperbus_cfg_regs.t_tx_clk_delay.value + always_comb begin + automatic logic [7:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_tx_clk_delay.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_tx_clk_delay && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_tx_clk_delay.value.value & ~decoded_wr_biten[7:0]) | (decoded_wr_data[7:0] & decoded_wr_biten[7:0]); + load_next_c = '1; + end + field_combo.t_tx_clk_delay.value.next = next_c; + field_combo.t_tx_clk_delay.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_tx_clk_delay.value.value <= 8'h10; + end else begin + if(field_combo.t_tx_clk_delay.value.load_next) begin + field_storage.t_tx_clk_delay.value.value <= field_combo.t_tx_clk_delay.value.next; + end + end + end + assign hwif_out.t_tx_clk_delay.value.value = field_storage.t_tx_clk_delay.value.value; + // Field: hyperbus_cfg_regs.address_mask_msb.value + always_comb begin + automatic logic [4:0] next_c; + automatic logic load_next_c; + next_c = field_storage.address_mask_msb.value.value; + load_next_c = '0; + if(decoded_reg_strb.address_mask_msb && decoded_req_is_wr) begin // SW write + next_c = (field_storage.address_mask_msb.value.value & ~decoded_wr_biten[4:0]) | (decoded_wr_data[4:0] & decoded_wr_biten[4:0]); + load_next_c = '1; + end + field_combo.address_mask_msb.value.next = next_c; + field_combo.address_mask_msb.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.address_mask_msb.value.value <= 5'h19; + end else begin + if(field_combo.address_mask_msb.value.load_next) begin + field_storage.address_mask_msb.value.value <= field_combo.address_mask_msb.value.next; + end + end + end + assign hwif_out.address_mask_msb.value.value = field_storage.address_mask_msb.value.value; + // Field: hyperbus_cfg_regs.address_space.value + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.address_space.value.value; + load_next_c = '0; + if(decoded_reg_strb.address_space && decoded_req_is_wr) begin // SW write + next_c = (field_storage.address_space.value.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.address_space.value.next = next_c; + field_combo.address_space.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.address_space.value.value <= 1'h0; + end else begin + if(field_combo.address_space.value.load_next) begin + field_storage.address_space.value.value <= field_combo.address_space.value.next; + end + end + end + assign hwif_out.address_space.value.value = field_storage.address_space.value.value; + // Field: hyperbus_cfg_regs.phys_in_use.value + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.phys_in_use.value.value; + load_next_c = '0; + if(decoded_reg_strb.phys_in_use && decoded_req_is_wr) begin // SW write + next_c = (field_storage.phys_in_use.value.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.phys_in_use.value.next = next_c; + field_combo.phys_in_use.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.phys_in_use.value.value <= 1'h1; + end else begin + if(field_combo.phys_in_use.value.load_next) begin + field_storage.phys_in_use.value.value <= field_combo.phys_in_use.value.next; + end + end + end + assign hwif_out.phys_in_use.value.value = field_storage.phys_in_use.value.value; + // Field: hyperbus_cfg_regs.which_phy.value + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.which_phy.value.value; + load_next_c = '0; + if(decoded_reg_strb.which_phy && decoded_req_is_wr) begin // SW write + next_c = (field_storage.which_phy.value.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.which_phy.value.next = next_c; + field_combo.which_phy.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.which_phy.value.value <= 1'h1; + end else begin + if(field_combo.which_phy.value.load_next) begin + field_storage.which_phy.value.value <= field_combo.which_phy.value.next; + end + end + end + assign hwif_out.which_phy.value.value = field_storage.which_phy.value.value; + // Field: hyperbus_cfg_regs.t_csh_cycles.value + always_comb begin + automatic logic [3:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_csh_cycles.value.value; + load_next_c = '0; + if(decoded_reg_strb.t_csh_cycles && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_csh_cycles.value.value & ~decoded_wr_biten[3:0]) | (decoded_wr_data[3:0] & decoded_wr_biten[3:0]); + load_next_c = '1; + end + field_combo.t_csh_cycles.value.next = next_c; + field_combo.t_csh_cycles.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_csh_cycles.value.value <= 4'h1; + end else begin + if(field_combo.t_csh_cycles.value.load_next) begin + field_storage.t_csh_cycles.value.value <= field_combo.t_csh_cycles.value.next; + end + end + end + assign hwif_out.t_csh_cycles.value.value = field_storage.t_csh_cycles.value.value; + // Field: hyperbus_cfg_regs.csn_to_ck_cycles.value + always_comb begin + automatic logic [3:0] next_c; + automatic logic load_next_c; + next_c = field_storage.csn_to_ck_cycles.value.value; + load_next_c = '0; + if(decoded_reg_strb.csn_to_ck_cycles && decoded_req_is_wr) begin // SW write + next_c = (field_storage.csn_to_ck_cycles.value.value & ~decoded_wr_biten[3:0]) | (decoded_wr_data[3:0] & decoded_wr_biten[3:0]); + load_next_c = '1; + end + field_combo.csn_to_ck_cycles.value.next = next_c; + field_combo.csn_to_ck_cycles.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.csn_to_ck_cycles.value.value <= 4'h0; + end else begin + if(field_combo.csn_to_ck_cycles.value.load_next) begin + field_storage.csn_to_ck_cycles.value.value <= field_combo.csn_to_ck_cycles.value.next; + end + end + end + assign hwif_out.csn_to_ck_cycles.value.value = field_storage.csn_to_ck_cycles.value.value; + // Field: hyperbus_cfg_regs.chip0_base.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip0_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip0_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip0_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip0_base.value.next = next_c; + field_combo.chip0_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip0_base.value.value <= 32'h0; + end else begin + if(field_combo.chip0_base.value.load_next) begin + field_storage.chip0_base.value.value <= field_combo.chip0_base.value.next; + end + end + end + assign hwif_out.chip0_base.value.value = field_storage.chip0_base.value.value; + // Field: hyperbus_cfg_regs.chip0_bound.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip0_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip0_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip0_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip0_bound.value.next = next_c; + field_combo.chip0_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip0_bound.value.value <= 32'h10000; + end else begin + if(field_combo.chip0_bound.value.load_next) begin + field_storage.chip0_bound.value.value <= field_combo.chip0_bound.value.next; + end + end + end + assign hwif_out.chip0_bound.value.value = field_storage.chip0_bound.value.value; + // Field: hyperbus_cfg_regs.chip1_base.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip1_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip1_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip1_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip1_base.value.next = next_c; + field_combo.chip1_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip1_base.value.value <= 32'h10000; + end else begin + if(field_combo.chip1_base.value.load_next) begin + field_storage.chip1_base.value.value <= field_combo.chip1_base.value.next; + end + end + end + assign hwif_out.chip1_base.value.value = field_storage.chip1_base.value.value; + // Field: hyperbus_cfg_regs.chip1_bound.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip1_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip1_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip1_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip1_bound.value.next = next_c; + field_combo.chip1_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip1_bound.value.value <= 32'h20000; + end else begin + if(field_combo.chip1_bound.value.load_next) begin + field_storage.chip1_bound.value.value <= field_combo.chip1_bound.value.next; + end + end + end + assign hwif_out.chip1_bound.value.value = field_storage.chip1_bound.value.value; + // Field: hyperbus_cfg_regs.chip2_base.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip2_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip2_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip2_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip2_base.value.next = next_c; + field_combo.chip2_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip2_base.value.value <= 32'h20000; + end else begin + if(field_combo.chip2_base.value.load_next) begin + field_storage.chip2_base.value.value <= field_combo.chip2_base.value.next; + end + end + end + assign hwif_out.chip2_base.value.value = field_storage.chip2_base.value.value; + // Field: hyperbus_cfg_regs.chip2_bound.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip2_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip2_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip2_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip2_bound.value.next = next_c; + field_combo.chip2_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip2_bound.value.value <= 32'h30000; + end else begin + if(field_combo.chip2_bound.value.load_next) begin + field_storage.chip2_bound.value.value <= field_combo.chip2_bound.value.next; + end + end + end + assign hwif_out.chip2_bound.value.value = field_storage.chip2_bound.value.value; + // Field: hyperbus_cfg_regs.chip3_base.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip3_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip3_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip3_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip3_base.value.next = next_c; + field_combo.chip3_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip3_base.value.value <= 32'h30000; + end else begin + if(field_combo.chip3_base.value.load_next) begin + field_storage.chip3_base.value.value <= field_combo.chip3_base.value.next; + end + end + end + assign hwif_out.chip3_base.value.value = field_storage.chip3_base.value.value; + // Field: hyperbus_cfg_regs.chip3_bound.value + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip3_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip3_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip3_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.chip3_bound.value.next = next_c; + field_combo.chip3_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip3_bound.value.value <= 32'h40000; + end else begin + if(field_combo.chip3_bound.value.load_next) begin + field_storage.chip3_bound.value.value <= field_combo.chip3_bound.value.next; + end + end + end + assign hwif_out.chip3_bound.value.value = field_storage.chip3_bound.value.value; + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + + logic [6:0] rd_mux_addr; + assign rd_mux_addr = decoded_addr; + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + always_comb begin + automatic logic [31:0] readback_data_var; + readback_data_var = '0; + if(rd_mux_addr == 7'h0) begin + readback_data_var[3:0] = field_storage.t_latency_access.value.value; + end + if(rd_mux_addr == 7'h4) begin + readback_data_var[0] = field_storage.en_latency_additional.value.value; + end + if(rd_mux_addr == 7'h8) begin + readback_data_var[15:0] = field_storage.t_burst_max.value.value; + end + if(rd_mux_addr == 7'hc) begin + readback_data_var[3:0] = field_storage.t_read_write_recovery.value.value; + end + if(rd_mux_addr == 7'h10) begin + readback_data_var[7:0] = field_storage.t_rx_clk_delay.value.value; + end + if(rd_mux_addr == 7'h14) begin + readback_data_var[7:0] = field_storage.t_tx_clk_delay.value.value; + end + if(rd_mux_addr == 7'h18) begin + readback_data_var[4:0] = field_storage.address_mask_msb.value.value; + end + if(rd_mux_addr == 7'h1c) begin + readback_data_var[0] = field_storage.address_space.value.value; + end + if(rd_mux_addr == 7'h20) begin + readback_data_var[0] = field_storage.phys_in_use.value.value; + end + if(rd_mux_addr == 7'h24) begin + readback_data_var[0] = field_storage.which_phy.value.value; + end + if(rd_mux_addr == 7'h28) begin + readback_data_var[3:0] = field_storage.t_csh_cycles.value.value; + end + if(rd_mux_addr == 7'h2c) begin + readback_data_var[3:0] = field_storage.csn_to_ck_cycles.value.value; + end + if(rd_mux_addr == 7'h30) begin + readback_data_var[31:0] = field_storage.chip0_base.value.value; + end + if(rd_mux_addr == 7'h34) begin + readback_data_var[31:0] = field_storage.chip0_bound.value.value; + end + if(rd_mux_addr == 7'h38) begin + readback_data_var[31:0] = field_storage.chip1_base.value.value; + end + if(rd_mux_addr == 7'h3c) begin + readback_data_var[31:0] = field_storage.chip1_bound.value.value; + end + if(rd_mux_addr == 7'h40) begin + readback_data_var[31:0] = field_storage.chip2_base.value.value; + end + if(rd_mux_addr == 7'h44) begin + readback_data_var[31:0] = field_storage.chip2_bound.value.value; + end + if(rd_mux_addr == 7'h48) begin + readback_data_var[31:0] = field_storage.chip3_base.value.value; + end + if(rd_mux_addr == 7'h4c) begin + readback_data_var[31:0] = field_storage.chip3_bound.value.value; + end + readback_data = readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr; + readback_err = '0; + end + + assign cpuif_rd_ack = readback_done; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; +endmodule diff --git a/src/regs/hyperbus_cfg_regblock_pkg.sv b/src/regs/hyperbus_cfg_regblock_pkg.sv new file mode 100644 index 0000000..59572c7 --- /dev/null +++ b/src/regs/hyperbus_cfg_regblock_pkg.sv @@ -0,0 +1,192 @@ +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +package hyperbus_cfg_regblock_pkg; + + localparam HYPERBUS_CFG_REGBLOCK_DATA_WIDTH = 32; + localparam HYPERBUS_CFG_REGBLOCK_MIN_ADDR_WIDTH = 7; + localparam HYPERBUS_CFG_REGBLOCK_SIZE = 'h50; + + typedef struct { + logic [3:0] value; + } hyperbus_cfg_regs__t_latency_access__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_latency_access__value__out_t value; + } hyperbus_cfg_regs__t_latency_access__out_t; + + typedef struct { + logic value; + } hyperbus_cfg_regs__en_latency_additional__value__out_t; + + typedef struct { + hyperbus_cfg_regs__en_latency_additional__value__out_t value; + } hyperbus_cfg_regs__en_latency_additional__out_t; + + typedef struct { + logic [15:0] value; + } hyperbus_cfg_regs__t_burst_max__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_burst_max__value__out_t value; + } hyperbus_cfg_regs__t_burst_max__out_t; + + typedef struct { + logic [3:0] value; + } hyperbus_cfg_regs__t_read_write_recovery__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_read_write_recovery__value__out_t value; + } hyperbus_cfg_regs__t_read_write_recovery__out_t; + + typedef struct { + logic [7:0] value; + } hyperbus_cfg_regs__t_rx_clk_delay__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_rx_clk_delay__value__out_t value; + } hyperbus_cfg_regs__t_rx_clk_delay__out_t; + + typedef struct { + logic [7:0] value; + } hyperbus_cfg_regs__t_tx_clk_delay__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_tx_clk_delay__value__out_t value; + } hyperbus_cfg_regs__t_tx_clk_delay__out_t; + + typedef struct { + logic [4:0] value; + } hyperbus_cfg_regs__address_mask_msb__value__out_t; + + typedef struct { + hyperbus_cfg_regs__address_mask_msb__value__out_t value; + } hyperbus_cfg_regs__address_mask_msb__out_t; + + typedef struct { + logic value; + } hyperbus_cfg_regs__address_space__value__out_t; + + typedef struct { + hyperbus_cfg_regs__address_space__value__out_t value; + } hyperbus_cfg_regs__address_space__out_t; + + typedef struct { + logic value; + } hyperbus_cfg_regs__phys_in_use__value__out_t; + + typedef struct { + hyperbus_cfg_regs__phys_in_use__value__out_t value; + } hyperbus_cfg_regs__phys_in_use__out_t; + + typedef struct { + logic value; + } hyperbus_cfg_regs__which_phy__value__out_t; + + typedef struct { + hyperbus_cfg_regs__which_phy__value__out_t value; + } hyperbus_cfg_regs__which_phy__out_t; + + typedef struct { + logic [3:0] value; + } hyperbus_cfg_regs__t_csh_cycles__value__out_t; + + typedef struct { + hyperbus_cfg_regs__t_csh_cycles__value__out_t value; + } hyperbus_cfg_regs__t_csh_cycles__out_t; + + typedef struct { + logic [3:0] value; + } hyperbus_cfg_regs__csn_to_ck_cycles__value__out_t; + + typedef struct { + hyperbus_cfg_regs__csn_to_ck_cycles__value__out_t value; + } hyperbus_cfg_regs__csn_to_ck_cycles__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip0_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip0_base__value__out_t value; + } hyperbus_cfg_regs__chip0_base__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip0_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip0_bound__value__out_t value; + } hyperbus_cfg_regs__chip0_bound__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip1_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip1_base__value__out_t value; + } hyperbus_cfg_regs__chip1_base__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip1_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip1_bound__value__out_t value; + } hyperbus_cfg_regs__chip1_bound__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip2_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip2_base__value__out_t value; + } hyperbus_cfg_regs__chip2_base__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip2_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip2_bound__value__out_t value; + } hyperbus_cfg_regs__chip2_bound__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip3_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip3_base__value__out_t value; + } hyperbus_cfg_regs__chip3_base__out_t; + + typedef struct { + logic [31:0] value; + } hyperbus_cfg_regs__chip3_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip3_bound__value__out_t value; + } hyperbus_cfg_regs__chip3_bound__out_t; + + typedef struct { + hyperbus_cfg_regs__t_latency_access__out_t t_latency_access; + hyperbus_cfg_regs__en_latency_additional__out_t en_latency_additional; + hyperbus_cfg_regs__t_burst_max__out_t t_burst_max; + hyperbus_cfg_regs__t_read_write_recovery__out_t t_read_write_recovery; + hyperbus_cfg_regs__t_rx_clk_delay__out_t t_rx_clk_delay; + hyperbus_cfg_regs__t_tx_clk_delay__out_t t_tx_clk_delay; + hyperbus_cfg_regs__address_mask_msb__out_t address_mask_msb; + hyperbus_cfg_regs__address_space__out_t address_space; + hyperbus_cfg_regs__phys_in_use__out_t phys_in_use; + hyperbus_cfg_regs__which_phy__out_t which_phy; + hyperbus_cfg_regs__t_csh_cycles__out_t t_csh_cycles; + hyperbus_cfg_regs__csn_to_ck_cycles__out_t csn_to_ck_cycles; + hyperbus_cfg_regs__chip0_base__out_t chip0_base; + hyperbus_cfg_regs__chip0_bound__out_t chip0_bound; + hyperbus_cfg_regs__chip1_base__out_t chip1_base; + hyperbus_cfg_regs__chip1_bound__out_t chip1_bound; + hyperbus_cfg_regs__chip2_base__out_t chip2_base; + hyperbus_cfg_regs__chip2_bound__out_t chip2_bound; + hyperbus_cfg_regs__chip3_base__out_t chip3_base; + hyperbus_cfg_regs__chip3_bound__out_t chip3_bound; + } hyperbus_cfg_regs__out_t; +endpackage diff --git a/src/regs/hyperbus_cfg_regs.rdl b/src/regs/hyperbus_cfg_regs.rdl new file mode 100644 index 0000000..5c27572 --- /dev/null +++ b/src/regs/hyperbus_cfg_regs.rdl @@ -0,0 +1,101 @@ +addrmap hyperbus_cfg_regs { + reg { + desc = "Initial latency cycles before read or write data."; + field { sw = rw; hw = r; reset = 4'h6; } value[3:0]; + } t_latency_access @ 0x00; + + reg { + desc = "Enable additional latency cycles when requested by RWDS."; + field { sw = rw; hw = r; reset = 1'b0; } value; + } en_latency_additional @ 0x04; + + reg { + desc = "Maximum continuous burst length before the PHY restarts a transfer."; + field { sw = rw; hw = r; reset = 16'd350; } value[15:0]; + } t_burst_max @ 0x08; + + reg { + desc = "Recovery cycles inserted between read and write phases."; + field { sw = rw; hw = r; reset = 4'h6; } value[3:0]; + } t_read_write_recovery @ 0x0c; + + reg { + desc = "RX sampling delay-line tap setting."; + field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; + } t_rx_clk_delay @ 0x10; + + reg { + desc = "TX clock delay-line tap setting."; + field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; + } t_tx_clk_delay @ 0x14; + + reg { + desc = "Most-significant address bit used by frontend address packing."; + field { sw = rw; hw = r; reset = 5'd25; } value[4:0]; + } address_mask_msb @ 0x18; + + reg { + desc = "Select HyperRAM or HyperFlash address-space interpretation."; + field { sw = rw; hw = r; reset = 1'b0; } value; + } address_space @ 0x1c; + + reg { + desc = "Select whether one or both PHY lanes are active."; + field { sw = rw; hw = r; reset = 1'b1; } value; + } phys_in_use @ 0x20; + + reg { + desc = "Select the PHY lane used when only one PHY is active."; + field { sw = rw; hw = r; reset = 1'b1; } value; + } which_phy @ 0x24; + + reg { + desc = "Chip-select high time between transfers."; + field { sw = rw; hw = r; reset = 4'h1; } value[3:0]; + } t_csh_cycles @ 0x28; + + reg { + desc = "Delay cycles from chip-select assertion to clock start."; + field { sw = rw; hw = r; reset = 4'h0; } value[3:0]; + } csn_to_ck_cycles @ 0x2c; + + reg { + desc = "Inclusive base address for chip-select 0 decoding."; + field { sw = rw; hw = r; reset = 32'h0000_0000; } value[31:0]; + } chip0_base @ 0x30; + + reg { + desc = "Exclusive bound address for chip-select 0 decoding."; + field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; + } chip0_bound @ 0x34; + + reg { + desc = "Inclusive base address for chip-select 1 decoding."; + field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; + } chip1_base @ 0x38; + + reg { + desc = "Exclusive bound address for chip-select 1 decoding."; + field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; + } chip1_bound @ 0x3c; + + reg { + desc = "Inclusive base address for chip-select 2 decoding."; + field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; + } chip2_base @ 0x40; + + reg { + desc = "Exclusive bound address for chip-select 2 decoding."; + field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; + } chip2_bound @ 0x44; + + reg { + desc = "Inclusive base address for chip-select 3 decoding."; + field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; + } chip3_base @ 0x48; + + reg { + desc = "Exclusive bound address for chip-select 3 decoding."; + field { sw = rw; hw = r; reset = 32'h0004_0000; } value[31:0]; + } chip3_bound @ 0x4c; +}; From 14cef0ec339bcb1b397c65c0bbec02edf06005bb Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Thu, 21 May 2026 23:16:18 +0200 Subject: [PATCH 2/5] Use generated HyperBus config registers --- src/hyperbus.sv | 28 ++--- src/hyperbus_axi.sv | 27 ++--- src/hyperbus_cfg_regs.sv | 242 ++++++++++++++++++++++--------------- src/hyperbus_phy.sv | 32 ++--- src/hyperbus_phy_if.sv | 2 +- src/hyperbus_pkg.sv | 75 +++++++----- src/hyperbus_synth_wrap.sv | 1 - test/dut_if.sv | 1 - test/fixture_hyperbus.sv | 1 - 9 files changed, 231 insertions(+), 178 deletions(-) diff --git a/src/hyperbus.sv b/src/hyperbus.sv index da287fa..ff0faa6 100644 --- a/src/hyperbus.sv +++ b/src/hyperbus.sv @@ -21,18 +21,13 @@ module hyperbus #( parameter type axi_ar_chan_t = logic, parameter type axi_r_chan_t = logic, parameter type axi_aw_chan_t = logic, - parameter int unsigned RegAddrWidth = -1, parameter int unsigned RegDataWidth = -1, - parameter int unsigned MinFreqMHz = 100, parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, parameter type axi_rule_t = logic, // The below have sensible defaults, but should be set on integration! parameter int unsigned RxFifoLogDepth = 3, parameter int unsigned TxFifoLogDepth = 3, - parameter logic [RegDataWidth-1:0] RstChipBase = 'h0, // Base address for all chips - parameter logic [RegDataWidth-1:0] RstChipSpace = 'h1_0000, // 64 KiB: Current maximum HyperBus device size - parameter hyperbus_pkg::hyper_cfg_t RstCfg = hyperbus_pkg::gen_RstCfg(NumPhys,MinFreqMHz), parameter int unsigned PhyStartupCycles = 300 * 200, /* us*MHz */ // Conservative maximum frequency estimate parameter int unsigned SyncStages = 2 ) ( @@ -85,9 +80,10 @@ module hyperbus #( logic clk_phy_0, clk_phy_90, rst_phy; // Register file - hyperbus_pkg::hyper_cfg_t cfg; - axi_rule_t [NumChips-1:0] chip_rules; - logic trans_active; + hyperbus_pkg::frontend_cfg_t frontend_cfg; + hyperbus_pkg::phy_cfg_t phy_cfg; + axi_rule_t [NumChips-1:0] chip_rules; + logic trans_active; // AXI slave hyper_rx_t axi_rx; @@ -121,20 +117,17 @@ module hyperbus #( hyperbus_cfg_regs #( .NumChips ( NumChips ), .NumPhys ( NumPhys ), - .RegAddrWidth ( RegAddrWidth ), .RegDataWidth ( RegDataWidth ), .reg_req_t ( reg_req_t ), .reg_rsp_t ( reg_rsp_t ), - .rule_t ( axi_rule_t ), - .RstChipBase ( RstChipBase ), - .RstChipSpace ( RstChipSpace ), - .RstCfg ( RstCfg ) + .rule_t ( axi_rule_t ) ) i_cfg_regs ( .clk_i ( clk_sys_i ), .rst_ni ( rst_sys_ni ), .reg_req_i ( reg_req_i ), .reg_rsp_o ( reg_rsp_o ), - .cfg_o ( cfg ), + .frontend_cfg_o ( frontend_cfg ), + .phy_cfg_o ( phy_cfg ), .chip_rules_o ( chip_rules ), .trans_active_i ( trans_active ) ); @@ -173,11 +166,8 @@ module hyperbus #( .trans_valid_o ( axi_trans_valid ), .trans_ready_i ( axi_trans_ready ), + .frontend_cfg_i ( frontend_cfg ), .chip_rules_i ( chip_rules ), - .which_phy_i ( cfg.which_phy ), - .phys_in_use_i ( cfg.phys_in_use ), - .addr_mask_msb_i ( cfg.address_mask_msb ), - .addr_space_i ( cfg.address_space ), .trans_active_o ( trans_active ) ); @@ -214,7 +204,7 @@ module hyperbus #( .rst_phy_ni ( rst_phy ), .test_mode_i ( test_mode_i ), - .cfg_i ( cfg ), + .cfg_i ( phy_cfg ), .rx_o ( phy_rx ), .rx_valid_o ( phy_rx_valid ), diff --git a/src/hyperbus_axi.sv b/src/hyperbus_axi.sv index 78b3c7d..bac8778 100644 --- a/src/hyperbus_axi.sv +++ b/src/hyperbus_axi.sv @@ -44,11 +44,8 @@ module hyperbus_axi #( output logic trans_valid_o, input logic trans_ready_i, - input rule_t [NumChips-1:0] chip_rules_i, - input logic phys_in_use_i, - input logic which_phy_i, - input logic [4:0] addr_mask_msb_i, - input logic addr_space_i, + input hyperbus_pkg::frontend_cfg_t frontend_cfg_i, + input rule_t [NumChips-1:0] chip_rules_i, output logic trans_active_o ); @@ -163,7 +160,7 @@ module hyperbus_axi #( logic [1:0] phys_in_use; - assign phys_in_use = (NumPhys==2) ? (phys_in_use_i + 1) : 1; + assign phys_in_use = (NumPhys==2) ? (frontend_cfg_i.phys_in_use + 1) : 1; // ============================ // Serialize requests @@ -305,12 +302,12 @@ module hyperbus_axi #( // AX channel: forward, converting unmasked byte to masked word addresses assign trans_o.write = rr_out_req_write; assign trans_o.burst_type = 1'b1; // Wrapping bursts not (yet) supported - assign trans_o.address_space = addr_space_i; + assign trans_o.address_space = frontend_cfg_i.address_space; assign trans_o.address = (NumPhys == 2) ? - (phys_in_use_i ? - ((rr_out_req_ax.addr & ((32'b1 << addr_mask_msb_i) - 1)) >> 2) : - (((rr_out_req_ax.addr & ((32'b1 << addr_mask_msb_i) - 1)) >> 2) << 1)) : - ((rr_out_req_ax.addr & ((32'b1 << addr_mask_msb_i) - 1)) >> 1); + (frontend_cfg_i.phys_in_use ? + ((rr_out_req_ax.addr & ((32'b1 << frontend_cfg_i.address_mask_msb) - 1)) >> 2) : + (((rr_out_req_ax.addr & ((32'b1 << frontend_cfg_i.address_mask_msb) - 1)) >> 2) << 1)) : + ((rr_out_req_ax.addr & ((32'b1 << frontend_cfg_i.address_mask_msb) - 1)) >> 1); // Convert burst length from decremented, unaligned beats to non-decremented, aligned 16-bit words always_comb begin @@ -365,11 +362,11 @@ module hyperbus_axi #( s_rx_error = rx_i.error; s_rx_data_lower_d = s_rx_data_lower_q; merge_r_d = merge_r_q; - if( (NumPhys==2) & (~phys_in_use_i) ) begin + if( (NumPhys==2) & (~frontend_cfg_i.phys_in_use) ) begin if(rx_valid_i & s_rx_ready) begin merge_r_d = merge_r_q + 1; end - if(~which_phy_i) + if(~frontend_cfg_i.which_phy) s_rx_data = { rx_i.data[PhyDataWidth/2-1:0] , s_rx_data_lower_q }; else s_rx_data = { rx_i.data[PhyDataWidth-1:PhyDataWidth/2] , s_rx_data_lower_q }; @@ -378,7 +375,7 @@ module hyperbus_axi #( s_rx_last = rx_i.last & merge_r_q; s_rx_error = rx_i.error; if(~merge_r_q) begin - if(~which_phy_i) + if(~frontend_cfg_i.which_phy) s_rx_data_lower_d = rx_i.data[PhyDataWidth/2-1:0]; else s_rx_data_lower_d = rx_i.data[PhyDataWidth-1:PhyDataWidth/2]; @@ -469,7 +466,7 @@ module hyperbus_axi #( tx_valid_o = s_tx_valid; s_tx_ready = tx_ready_i; split_w_d = split_w_q; - if( (NumPhys==2) & (~phys_in_use_i) ) begin + if( (NumPhys==2) & (~frontend_cfg_i.phys_in_use) ) begin if(s_tx_valid & tx_ready_i) begin split_w_d = split_w_q+1; end diff --git a/src/hyperbus_cfg_regs.sv b/src/hyperbus_cfg_regs.sv index 70ac78e..46310a5 100644 --- a/src/hyperbus_cfg_regs.sv +++ b/src/hyperbus_cfg_regs.sv @@ -7,15 +7,10 @@ module hyperbus_cfg_regs #( parameter int unsigned NumChips = -1, parameter int unsigned NumPhys = -1, - parameter int unsigned RegAddrWidth = -1, parameter int unsigned RegDataWidth = -1, parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, - parameter type rule_t = logic, - parameter logic [RegDataWidth-1:0] RstChipBase = -1, // Base address for all chips - parameter logic [RegDataWidth-1:0] RstChipSpace = -1, // 64 KiB: Current maximum HyperBus device size - parameter int unsigned MinFreqMHz = 100, - parameter hyperbus_pkg::hyper_cfg_t RstCfg = hyperbus_pkg::gen_RstCfg(NumPhys,MinFreqMHz) + parameter type rule_t = logic ) ( input logic clk_i, input logic rst_ni, @@ -23,113 +18,168 @@ module hyperbus_cfg_regs #( input reg_req_t reg_req_i, output reg_rsp_t reg_rsp_o, - output hyperbus_pkg::hyper_cfg_t cfg_o, + output hyperbus_pkg::frontend_cfg_t frontend_cfg_o, + output hyperbus_pkg::phy_cfg_t phy_cfg_o, output rule_t [NumChips-1:0] chip_rules_o, input trans_active_i ); `include "common_cells/registers.svh" - // Internal Parameters - localparam int unsigned NumBaseRegs = 12; - localparam int unsigned NumRegs = 2*NumChips + NumBaseRegs; - localparam int unsigned RegsBits = cf_math_pkg::idx_width(NumRegs); - localparam int unsigned RegStrbWidth = RegDataWidth/8; - - // Data and index types - typedef logic [RegsBits-1:0] reg_idx_t; - typedef logic [RegDataWidth-1:0] reg_data_t; - - // Local signals - hyperbus_pkg::hyper_cfg_t cfg_d, cfg_q, cfg_rstval; - reg_data_t [NumChips-1:0][1:0] crange_d, crange_q, crange_rstval; - reg_idx_t sel_reg; - logic sel_reg_mapped; - reg_data_t wmask; - - assign sel_reg = reg_req_i.addr[$clog2(RegStrbWidth) +: RegsBits]; - assign sel_reg_mapped = (sel_reg < NumRegs); - - assign reg_rsp_o.ready = ~trans_active_i; // Config writeable unless currently in transfer - assign reg_rsp_o.error = ~sel_reg_mapped; - - // Read from register - always_comb begin : proc_comb_read - reg_data_t [NumRegs-1:0] rfield; - reg_rsp_o.rdata = '0; - if (sel_reg_mapped) begin - rfield = { - crange_q, - reg_data_t'(cfg_q.csn_to_ck_cycles), - reg_data_t'(cfg_q.t_csh_cycles), - reg_data_t'(cfg_q.which_phy), - reg_data_t'(cfg_q.phys_in_use), - reg_data_t'(cfg_q.address_space), - reg_data_t'(cfg_q.address_mask_msb), - reg_data_t'(cfg_q.t_tx_clk_delay), - reg_data_t'(cfg_q.t_rx_clk_delay), - reg_data_t'(cfg_q.t_read_write_recovery), - reg_data_t'(cfg_q.t_burst_max), - reg_data_t'(cfg_q.en_latency_additional), - reg_data_t'(cfg_q.t_latency_access) - }; - reg_rsp_o.rdata = rfield[sel_reg]; + localparam int unsigned NumChipsMax = 4; + localparam int unsigned NumRegs = 2*NumChipsMax + 12; + localparam int unsigned RegsBits = cf_math_pkg::idx_width(NumRegs); + localparam int unsigned RegStrbWidth = RegDataWidth/8; + + typedef logic [RegsBits-1:0] reg_idx_t; + typedef logic [RegDataWidth-1:0] reg_data_t; + typedef logic [6:0] cfg_addr_t; + typedef logic [31:0] cfg_data_t; + typedef logic [3:0] cfg_strb_t; + + typedef struct packed { + cfg_addr_t addr; + logic write; + cfg_data_t wdata; + cfg_strb_t wstrb; + logic valid; + } cfg_reg_req_t; + + typedef struct packed { + cfg_data_t rdata; + logic error; + logic ready; + } cfg_reg_rsp_t; + + typedef struct packed { + cfg_addr_t paddr; + logic [2:0] pprot; + logic psel; + logic penable; + logic pwrite; + cfg_data_t pwdata; + cfg_strb_t pstrb; + } cfg_apb_req_t; + + typedef struct packed { + logic pready; + cfg_data_t prdata; + logic pslverr; + } cfg_apb_rsp_t; + + hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t cfg_hwif_out; + rule_t [NumChipsMax-1:0] chip_rules_all; + + reg_idx_t sel_reg; + logic sel_reg_mapped; + logic cfg_access_active_d, cfg_access_active_q; + logic cfg_access_open; + + cfg_reg_req_t cfg_reg_req; + cfg_reg_rsp_t cfg_reg_rsp; + cfg_apb_req_t cfg_apb_req; + cfg_apb_rsp_t cfg_apb_rsp; + + assign sel_reg = reg_req_i.addr[$clog2(RegStrbWidth) +: RegsBits]; + assign sel_reg_mapped = (sel_reg < NumRegs); + assign cfg_access_open = ~trans_active_i | cfg_access_active_q; + + assign reg_rsp_o.ready = cfg_access_open & + (~reg_req_i.valid | ~sel_reg_mapped | cfg_reg_rsp.ready); + assign reg_rsp_o.error = ~sel_reg_mapped | cfg_reg_rsp.error; + assign reg_rsp_o.rdata = sel_reg_mapped ? RegDataWidth'(cfg_reg_rsp.rdata) : '0; + + assign cfg_reg_req.valid = reg_req_i.valid & sel_reg_mapped & cfg_access_open; + assign cfg_reg_req.addr = {sel_reg, 2'b00}; + assign cfg_reg_req.write = reg_req_i.write; + assign cfg_reg_req.wdata = 32'(reg_req_i.wdata); + assign cfg_reg_req.wstrb = cfg_strb_t'(reg_req_i.wstrb); + + always_comb begin + cfg_access_active_d = cfg_access_active_q; + if (!cfg_access_active_q && cfg_reg_req.valid) begin + cfg_access_active_d = 1'b1; + end + if (cfg_access_active_q && cfg_reg_rsp.ready) begin + cfg_access_active_d = 1'b0; end end - // Generate write mask - for (genvar i = 0; unsigned'(i) < RegStrbWidth; ++i ) begin : gen_wmask - assign wmask[8*i +: 8] = {8{reg_req_i.wstrb[i]}}; - end + `FFARN(cfg_access_active_q, cfg_access_active_d, 1'b0, clk_i, rst_ni); - // Write to register - always_comb begin : proc_comb_write - logic chip_reg; - logic [$clog2(NumChips)-1:0] sel_chip; - cfg_d = cfg_q; - crange_d = crange_q; - if (reg_req_i.valid & reg_req_i.write & sel_reg_mapped) begin - case (sel_reg) - 'h0: cfg_d.t_latency_access = (~wmask & cfg_q.t_latency_access ) | (wmask & reg_req_i.wdata); - 'h1: cfg_d.en_latency_additional = (~wmask & cfg_q.en_latency_additional ) | (wmask & reg_req_i.wdata); - 'h2: cfg_d.t_burst_max = (~wmask & cfg_q.t_burst_max ) | (wmask & reg_req_i.wdata); - 'h3: cfg_d.t_read_write_recovery = (~wmask & cfg_q.t_read_write_recovery ) | (wmask & reg_req_i.wdata); - 'h4: cfg_d.t_rx_clk_delay = (~wmask & cfg_q.t_rx_clk_delay ) | (wmask & reg_req_i.wdata); - 'h5: cfg_d.t_tx_clk_delay = (~wmask & cfg_q.t_tx_clk_delay ) | (wmask & reg_req_i.wdata); - 'h6: cfg_d.address_mask_msb = (~wmask & cfg_q.address_mask_msb ) | (wmask & reg_req_i.wdata); - 'h7: cfg_d.address_space = (~wmask & cfg_q.address_space ) | (wmask & reg_req_i.wdata); - 'h8: cfg_d.phys_in_use = (NumPhys==1) ? 0 : ( (~wmask & cfg_q.phys_in_use ) | (wmask & reg_req_i.wdata) ); - 'h9: cfg_d.which_phy = (NumPhys==1) ? 0 : ( (~wmask & cfg_q.which_phy ) | (wmask & reg_req_i.wdata) ); - 'ha: cfg_d.t_csh_cycles = (~wmask & cfg_q.t_csh_cycles ) | (wmask & reg_req_i.wdata); - 'hb: cfg_d.csn_to_ck_cycles = (~wmask & cfg_q.csn_to_ck_cycles ) | (wmask & reg_req_i.wdata); - default: begin - {sel_chip, chip_reg} = sel_reg - NumBaseRegs; - crange_d[sel_chip][chip_reg] = (~wmask & crange_q[sel_chip][chip_reg]) | (wmask & reg_req_i.wdata); + always_comb begin + chip_rules_all = '0; + for (int unsigned i = 0; i < NumChipsMax; i++) begin + chip_rules_all[i].idx = unsigned'(i); + unique case (i) + 0: begin + chip_rules_all[i].start_addr = cfg_hwif_out.chip0_base.value.value; + chip_rules_all[i].end_addr = cfg_hwif_out.chip0_bound.value.value; + end + 1: begin + chip_rules_all[i].start_addr = cfg_hwif_out.chip1_base.value.value; + chip_rules_all[i].end_addr = cfg_hwif_out.chip1_bound.value.value; + end + 2: begin + chip_rules_all[i].start_addr = cfg_hwif_out.chip2_base.value.value; + chip_rules_all[i].end_addr = cfg_hwif_out.chip2_bound.value.value; + end + 3: begin + chip_rules_all[i].start_addr = cfg_hwif_out.chip3_base.value.value; + chip_rules_all[i].end_addr = cfg_hwif_out.chip3_bound.value.value; end - endcase // sel_reg + default:; + endcase end end - for (genvar i = 0; unsigned'(i) < NumChips; i++) begin : gen_crange_rstval - assign crange_rstval[i][0] = RstChipBase + (RstChipSpace * i); - assign crange_rstval[i][1] = RstChipBase + (RstChipSpace * (i+1)); // Address decoder: end noninclusive - end - - // Registers - `FFARN(cfg_q, cfg_d, RstCfg, clk_i, rst_ni); - `FFARN(crange_q, crange_d, crange_rstval, clk_i, rst_ni); - - // Outputs - assign cfg_o = cfg_q; - for (genvar i = 0; unsigned'(i) < NumChips; ++i) begin : gen_crange_out - assign chip_rules_o[i].idx = unsigned'(i); // No overlap: keep indices sequential - assign chip_rules_o[i].start_addr = crange_q[i][0]; - assign chip_rules_o[i].end_addr = crange_q[i][1]; + reg_to_apb #( + .reg_req_t ( cfg_reg_req_t ), + .reg_rsp_t ( cfg_reg_rsp_t ), + .apb_req_t ( cfg_apb_req_t ), + .apb_rsp_t ( cfg_apb_rsp_t ) + ) i_reg_to_apb ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .reg_req_i ( cfg_reg_req ), + .reg_rsp_o ( cfg_reg_rsp ), + .apb_req_o ( cfg_apb_req ), + .apb_rsp_i ( cfg_apb_rsp ) + ); + + hyperbus_cfg_regblock i_cfg_regblock ( + .clk ( clk_i ), + .arst_n ( rst_ni ), + .s_apb_psel ( cfg_apb_req.psel ), + .s_apb_penable ( cfg_apb_req.penable ), + .s_apb_pwrite ( cfg_apb_req.pwrite ), + .s_apb_pprot ( cfg_apb_req.pprot ), + .s_apb_paddr ( cfg_apb_req.paddr ), + .s_apb_pwdata ( cfg_apb_req.pwdata ), + .s_apb_pstrb ( cfg_apb_req.pstrb ), + .s_apb_pready ( cfg_apb_rsp.pready ), + .s_apb_prdata ( cfg_apb_rsp.prdata ), + .s_apb_pslverr ( cfg_apb_rsp.pslverr ), + .hwif_out ( cfg_hwif_out ) + ); + + assign frontend_cfg_o = hyperbus_pkg::hwif_to_frontend_cfg(cfg_hwif_out, NumPhys == 1); + assign phy_cfg_o = hyperbus_pkg::hwif_to_phy_cfg(cfg_hwif_out, NumPhys == 1); + + for (genvar i = 0; unsigned'(i) < NumChipsMax; i++) begin : gen_chip_rules + if (i < NumChips) begin : gen_active + assign chip_rules_o[i] = chip_rules_all[i]; + end else begin : gen_inactive + logic unused_chip_rule; + assign unused_chip_rule = ^chip_rules_all[i]; + end end // pragma translate_off `ifndef VERILATOR - initial assert (RegDataWidth >= 16 && $countones(RegDataWidth) == 1) - else $error("RegDataWidth must be a power of two bigger than 16."); + initial assert (RegDataWidth == 32) + else $error("Generated HyperBus config registers require 32-bit RegDataWidth."); + initial assert (NumChips <= NumChipsMax) + else $error("Generated HyperBus config registers support up to four chips."); `endif // pragma translate_on diff --git a/src/hyperbus_phy.sv b/src/hyperbus_phy.sv index a5b2cab..95340f0 100644 --- a/src/hyperbus_phy.sv +++ b/src/hyperbus_phy.sv @@ -20,7 +20,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( input logic rst_ni, input logic test_mode_i, // Config registers - input hyper_cfg_t cfg_i, + input phy_cfg_t cfg_i, // PHY control status output logic busy_o, // Transactions @@ -131,7 +131,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( .tx_data_oe_i ( trx_tx_data_oe ), .tx_rwds_i ( trx_tx_rwds ), .tx_rwds_oe_i ( trx_tx_rwds_oe ), - .rx_clk_delay_i ( cfg_i.t_rx_clk_delay ), + .rx_clk_delay_i ( cfg_i.chip.t_rx_clk_delay ), .rx_clk_set_i ( trx_rx_clk_set ), .rx_clk_reset_i ( trx_rx_clk_reset ), .rx_data_o ( trx_rx_data ), @@ -219,8 +219,8 @@ module hyperbus_phy import hyperbus_pkg::*; #( // Auxiliary control signals assign ctl_write_zero_lat = tf_q.address_space & tf_q.write; - // cfg_i.en_latency_additional overwrites the sampled RWDS value. - assign ctl_add_latency = trx_rwds_sample | cfg_i.en_latency_additional; + // cfg_i.chip.en_latency_additional overwrites the sampled RWDS value. + assign ctl_add_latency = trx_rwds_sample | cfg_i.chip.en_latency_additional; assign ctl_tf_burst_last = (tf_q.burst == 1) || (tf_q.burst == phys_in_use); assign ctl_tf_burst_done = (tf_q.burst == 0); @@ -270,11 +270,11 @@ module hyperbus_phy import hyperbus_pkg::*; #( cs_d = trans_cs_i; add_latency_d = 1'b0; - if(cfg_i.csn_to_ck_cycles != 0) begin + if(cfg_i.chip.csn_to_ck_cycles != 0) begin // assert CS but delay hyper_ck to allow more time // for memory to drive RWDS (to satisfy t_DSV) state_d = DelayCK; - timer_d = cfg_i.csn_to_ck_cycles -1; + timer_d = cfg_i.chip.csn_to_ck_cycles -1; end else begin // max throughput when memory RWDS signal arrives early state_d = SendCA; @@ -303,10 +303,10 @@ module hyperbus_phy import hyperbus_pkg::*; #( trx_rwds_sample_ena = ~ctl_write_zero_lat; if (ctl_timer_zero) begin if (ctl_write_zero_lat) begin - timer_d = cfg_i.t_burst_max; + timer_d = cfg_i.chip.t_burst_max; state_d = Write; end else begin - timer_d = TimerWidth'(cfg_i.t_latency_access); + timer_d = TimerWidth'(cfg_i.chip.t_latency_access); add_latency_d = ctl_add_latency; state_d = WaitLatAccess; end @@ -323,7 +323,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( if (~add_latency_q) begin // Substract cycle for last CA and another for state delay if(ctl_timer_two) begin - timer_d = cfg_i.t_burst_max; + timer_d = cfg_i.chip.t_burst_max; // Switch to write or read phase and already start // turnaround of tri-state driver (depending on latency // config and if read or write transaction). @@ -343,7 +343,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( end else if (ctl_timer_one) begin // instead of going to 0, add another latency count state_d = WaitAddLatAccess; - timer_d = TimerWidth'(cfg_i.t_latency_access); + timer_d = TimerWidth'(cfg_i.chip.t_latency_access); add_latency_d = 1'b0; end end @@ -353,7 +353,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( trx_clk_ena = 1'b1; trx_tx_data_oe = 1'b1; if (ctl_timer_two) begin - timer_d = cfg_i.t_burst_max; + timer_d = cfg_i.chip.t_burst_max; if (tf_q.write) begin state_d = Write; trx_tx_data_oe = 1'b1; @@ -374,13 +374,13 @@ module hyperbus_phy import hyperbus_pkg::*; #( tf_d.burst = tf_q.burst - phys_in_use; tf_d.address = tf_q.address + 1; if (ctl_tf_burst_last) begin - timer_d = cfg_i.t_csh_cycles; + timer_d = cfg_i.chip.t_csh_cycles; state_d = WaitXfer; end end // Force-terminate access on burst time limit if (ctl_timer_one) begin - timer_d = cfg_i.t_csh_cycles; + timer_d = cfg_i.chip.t_csh_cycles; state_d = WaitXfer; end end @@ -396,13 +396,13 @@ module hyperbus_phy import hyperbus_pkg::*; #( tf_d.address = tf_q.address + 1; if (ctl_tf_burst_last) begin b_pending_set = 1'b1; - timer_d = cfg_i.t_csh_cycles; + timer_d = cfg_i.chip.t_csh_cycles; state_d = WaitXfer; end end // Force-terminate access on burst time limit if (ctl_timer_one) begin - timer_d = cfg_i.t_csh_cycles; + timer_d = cfg_i.chip.t_csh_cycles; state_d = WaitXfer; end end @@ -410,7 +410,7 @@ module hyperbus_phy import hyperbus_pkg::*; #( // Wait for FFed Clock and output to stop // May have to be prolonged for potential future devices with t_CSH > 0 if (ctl_timer_zero) begin - timer_d = cfg_i.t_read_write_recovery; + timer_d = cfg_i.chip.t_read_write_recovery; state_d = WaitRWR; end end diff --git a/src/hyperbus_phy_if.sv b/src/hyperbus_phy_if.sv index ac165af..baf51f7 100644 --- a/src/hyperbus_phy_if.sv +++ b/src/hyperbus_phy_if.sv @@ -22,7 +22,7 @@ module hyperbus_phy_if import hyperbus_pkg::*; #( input logic rst_phy_ni, input logic test_mode_i, // Config registers - input hyper_cfg_t cfg_i, + input phy_cfg_t cfg_i, // Transactions input logic trans_valid_i, output logic trans_ready_o, diff --git a/src/hyperbus_pkg.sv b/src/hyperbus_pkg.sv index 3f97a7a..664e647 100644 --- a/src/hyperbus_pkg.sv +++ b/src/hyperbus_pkg.sv @@ -15,14 +15,57 @@ package hyperbus_pkg; logic [15:0] t_burst_max; logic [3:0] t_read_write_recovery; logic [7:0] t_rx_clk_delay; - logic [7:0] t_tx_clk_delay; + logic [3:0] t_csh_cycles; // configurable t_CSH for high-frequency operation (200 MHz HyperRAM) + logic [3:0] csn_to_ck_cycles; // delay hyper_ck after CS is asserted (more time for t_DSV) + } chip_phy_cfg_t; + + typedef struct packed { logic [4:0] address_mask_msb; logic address_space; logic phys_in_use; logic which_phy; - logic [3:0] t_csh_cycles; // configurable t_CSH for high-frequency operation (200 MHz HyperRAM) - logic [3:0] csn_to_ck_cycles; // delay hyper_ck after CS is asserted (more time for t_DSV) - } hyper_cfg_t; + } frontend_cfg_t; + + typedef struct packed { + chip_phy_cfg_t chip; + logic [7:0] t_tx_clk_delay; + logic phys_in_use; + logic which_phy; + } phy_cfg_t; + + function automatic frontend_cfg_t hwif_to_frontend_cfg( + input hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t hwif, + input logic num_phys_one + ); + frontend_cfg_t cfg; + + cfg.address_mask_msb = hwif.address_mask_msb.value.value; + cfg.address_space = hwif.address_space.value.value; + cfg.phys_in_use = num_phys_one ? 1'b0 : hwif.phys_in_use.value.value; + cfg.which_phy = num_phys_one ? 1'b0 : hwif.which_phy.value.value; + + return cfg; + endfunction + + function automatic phy_cfg_t hwif_to_phy_cfg( + input hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t hwif, + input logic num_phys_one + ); + phy_cfg_t cfg; + + cfg.chip.t_latency_access = hwif.t_latency_access.value.value; + cfg.chip.en_latency_additional = hwif.en_latency_additional.value.value; + cfg.chip.t_burst_max = hwif.t_burst_max.value.value; + cfg.chip.t_read_write_recovery = hwif.t_read_write_recovery.value.value; + cfg.chip.t_rx_clk_delay = hwif.t_rx_clk_delay.value.value; + cfg.chip.t_csh_cycles = hwif.t_csh_cycles.value.value; + cfg.chip.csn_to_ck_cycles = hwif.csn_to_ck_cycles.value.value; + cfg.t_tx_clk_delay = hwif.t_tx_clk_delay.value.value; + cfg.phys_in_use = num_phys_one ? 1'b0 : hwif.phys_in_use.value.value; + cfg.which_phy = num_phys_one ? 1'b0 : hwif.which_phy.value.value; + + return cfg; + endfunction typedef struct packed { logic write; // transaction is a write @@ -60,28 +103,4 @@ package hyperbus_pkg; logic [2:0] addr_lower; } hyper_phy_ca_t; - - // Register reset values - function automatic hyper_cfg_t gen_RstCfg(input int unsigned NumPhys, input int unsigned MinFreqMhz); - // MinFreqMHz = 100 is spec-compliant and should not be changed. - // It can be lowered if this frequency is not reachable in operation (this may not work with certain HyperBus devices). - // >200 is outside the spec and is unlikely to work with any HyperBus devices - automatic hyper_cfg_t cfg = hyper_cfg_t'{ - t_latency_access: 'h6, - en_latency_additional: 'b0, - t_burst_max: ((MinFreqMhz*35)/10), // t_{csm}: At lowest legal clock (100 MHz) 3.5us (0.5us safety margin) - t_read_write_recovery: 'h6, - t_rx_clk_delay: 'h10, - t_tx_clk_delay: 'h10, - address_mask_msb: 'd25, // 2^(address mask MSB) = single chip size [bytes] - address_space: 'b0, - phys_in_use: NumPhys-1, - which_phy: NumPhys-1, - t_csh_cycles: 'h1, - csn_to_ck_cycles: 4'h0 // additional cycles from CS_N going low to start of hyper_ck - }; - - return cfg; - endfunction - endpackage diff --git a/src/hyperbus_synth_wrap.sv b/src/hyperbus_synth_wrap.sv index 8b1935e..e7fc312 100644 --- a/src/hyperbus_synth_wrap.sv +++ b/src/hyperbus_synth_wrap.sv @@ -145,7 +145,6 @@ module hyperbus_lint_wrap #( .axi_ar_chan_t ( ar_chan_t ), .axi_r_chan_t ( r_chan_t ), .axi_aw_chan_t ( aw_chan_t ), - .RegAddrWidth ( RegAddrWidth ), .RegDataWidth ( RegDataWidth ), .reg_req_t ( reg_req_t ), .reg_rsp_t ( reg_rsp_t ), diff --git a/test/dut_if.sv b/test/dut_if.sv index 232b541..e63d9e9 100644 --- a/test/dut_if.sv +++ b/test/dut_if.sv @@ -137,7 +137,6 @@ module dut_if .axi_b_chan_t ( axi_b_chan_t ), .axi_ar_chan_t ( axi_ar_chan_t ), .axi_r_chan_t ( axi_r_chan_t ), - .RegAddrWidth ( RegAw ), .RegDataWidth ( RegDw ), .reg_req_t ( reg_req_t ), .reg_rsp_t ( reg_rsp_t ), diff --git a/test/fixture_hyperbus.sv b/test/fixture_hyperbus.sv index 9bd24b5..3967143 100644 --- a/test/fixture_hyperbus.sv +++ b/test/fixture_hyperbus.sv @@ -180,7 +180,6 @@ module fixture_hyperbus #( .axi_b_chan_t ( b_chan_t ), .axi_ar_chan_t ( ar_chan_t ), .axi_r_chan_t ( r_chan_t ), - .RegAddrWidth ( RegAw ), .RegDataWidth ( RegDw ), .reg_req_t ( reg_req_t ), .reg_rsp_t ( reg_rsp_t ), From 00bd978b094de9749fcf017c124da83d2db5666c Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Tue, 23 Jun 2026 17:08:23 +0200 Subject: [PATCH 3/5] Use named RDL register declarations --- src/regs/hyperbus_cfg_regs.rdl | 101 ++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/src/regs/hyperbus_cfg_regs.rdl b/src/regs/hyperbus_cfg_regs.rdl index 5c27572..5e49b7d 100644 --- a/src/regs/hyperbus_cfg_regs.rdl +++ b/src/regs/hyperbus_cfg_regs.rdl @@ -1,101 +1,122 @@ addrmap hyperbus_cfg_regs { - reg { + reg t_latency_access { desc = "Initial latency cycles before read or write data."; field { sw = rw; hw = r; reset = 4'h6; } value[3:0]; - } t_latency_access @ 0x00; + }; - reg { + reg en_latency_additional { desc = "Enable additional latency cycles when requested by RWDS."; field { sw = rw; hw = r; reset = 1'b0; } value; - } en_latency_additional @ 0x04; + }; - reg { + reg t_burst_max { desc = "Maximum continuous burst length before the PHY restarts a transfer."; field { sw = rw; hw = r; reset = 16'd350; } value[15:0]; - } t_burst_max @ 0x08; + }; - reg { + reg t_read_write_recovery { desc = "Recovery cycles inserted between read and write phases."; field { sw = rw; hw = r; reset = 4'h6; } value[3:0]; - } t_read_write_recovery @ 0x0c; + }; - reg { + reg t_rx_clk_delay { desc = "RX sampling delay-line tap setting."; field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; - } t_rx_clk_delay @ 0x10; + }; - reg { + reg t_tx_clk_delay { desc = "TX clock delay-line tap setting."; field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; - } t_tx_clk_delay @ 0x14; + }; - reg { + reg address_mask_msb { desc = "Most-significant address bit used by frontend address packing."; field { sw = rw; hw = r; reset = 5'd25; } value[4:0]; - } address_mask_msb @ 0x18; + }; - reg { + reg address_space { desc = "Select HyperRAM or HyperFlash address-space interpretation."; field { sw = rw; hw = r; reset = 1'b0; } value; - } address_space @ 0x1c; + }; - reg { + reg phys_in_use { desc = "Select whether one or both PHY lanes are active."; field { sw = rw; hw = r; reset = 1'b1; } value; - } phys_in_use @ 0x20; + }; - reg { + reg which_phy { desc = "Select the PHY lane used when only one PHY is active."; field { sw = rw; hw = r; reset = 1'b1; } value; - } which_phy @ 0x24; + }; - reg { + reg t_csh_cycles { desc = "Chip-select high time between transfers."; field { sw = rw; hw = r; reset = 4'h1; } value[3:0]; - } t_csh_cycles @ 0x28; + }; - reg { + reg csn_to_ck_cycles { desc = "Delay cycles from chip-select assertion to clock start."; field { sw = rw; hw = r; reset = 4'h0; } value[3:0]; - } csn_to_ck_cycles @ 0x2c; + }; - reg { + reg chip0_base { desc = "Inclusive base address for chip-select 0 decoding."; field { sw = rw; hw = r; reset = 32'h0000_0000; } value[31:0]; - } chip0_base @ 0x30; + }; - reg { + reg chip0_bound { desc = "Exclusive bound address for chip-select 0 decoding."; field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; - } chip0_bound @ 0x34; + }; - reg { + reg chip1_base { desc = "Inclusive base address for chip-select 1 decoding."; field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; - } chip1_base @ 0x38; + }; - reg { + reg chip1_bound { desc = "Exclusive bound address for chip-select 1 decoding."; field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; - } chip1_bound @ 0x3c; + }; - reg { + reg chip2_base { desc = "Inclusive base address for chip-select 2 decoding."; field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; - } chip2_base @ 0x40; + }; - reg { + reg chip2_bound { desc = "Exclusive bound address for chip-select 2 decoding."; field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; - } chip2_bound @ 0x44; + }; - reg { + reg chip3_base { desc = "Inclusive base address for chip-select 3 decoding."; field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; - } chip3_base @ 0x48; + }; - reg { + reg chip3_bound { desc = "Exclusive bound address for chip-select 3 decoding."; field { sw = rw; hw = r; reset = 32'h0004_0000; } value[31:0]; - } chip3_bound @ 0x4c; + }; + + t_latency_access t_latency_access @ 0x00; + en_latency_additional en_latency_additional @ 0x04; + t_burst_max t_burst_max @ 0x08; + t_read_write_recovery t_read_write_recovery @ 0x0c; + t_rx_clk_delay t_rx_clk_delay @ 0x10; + t_tx_clk_delay t_tx_clk_delay @ 0x14; + address_mask_msb address_mask_msb @ 0x18; + address_space address_space @ 0x1c; + phys_in_use phys_in_use @ 0x20; + which_phy which_phy @ 0x24; + t_csh_cycles t_csh_cycles @ 0x28; + csn_to_ck_cycles csn_to_ck_cycles @ 0x2c; + chip0_base chip0_base @ 0x30; + chip0_bound chip0_bound @ 0x34; + chip1_base chip1_base @ 0x38; + chip1_bound chip1_bound @ 0x3c; + chip2_base chip2_base @ 0x40; + chip2_bound chip2_bound @ 0x44; + chip3_base chip3_base @ 0x48; + chip3_bound chip3_bound @ 0x4c; }; From c51672a1960743ca80a06513f9c9e45e4d0ecac8 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Tue, 21 Jul 2026 14:52:51 +0200 Subject: [PATCH 4/5] Extend generated HyperBus configuration --- docs/regs/hyperbus_cfg_regs.md | 198 ++++++++-- include/hyperbus_cfg_regs.h | 145 +++++-- src/hyperbus_cfg_regs.sv | 54 ++- src/hyperbus_pkg.sv | 10 +- src/regs/hyperbus_cfg_regblock.sv | 530 ++++++++++++++++++++++---- src/regs/hyperbus_cfg_regblock_pkg.sv | 112 +++++- src/regs/hyperbus_cfg_regs.rdl | 112 +++++- 7 files changed, 958 insertions(+), 203 deletions(-) diff --git a/docs/regs/hyperbus_cfg_regs.md b/docs/regs/hyperbus_cfg_regs.md index 8e995aa..326f98d 100644 --- a/docs/regs/hyperbus_cfg_regs.md +++ b/docs/regs/hyperbus_cfg_regs.md @@ -9,7 +9,9 @@ Don't override. Generated from: hyperbus_cfg_regs - Absolute Address: 0x0 - Base Offset: 0x0 -- Size: 0x50 +- Size: 0x78 + +

HyperBus controller configuration. Chip address ranges must be 4 MiB aligned, ordered by chip-select index, and non-overlapping.

|Offset| Identifier |Name| |------|---------------------|----| @@ -33,6 +35,14 @@ Don't override. Generated from: hyperbus_cfg_regs | 0x44 | chip2_bound | — | | 0x48 | chip3_base | — | | 0x4C | chip3_bound | — | +| 0x58 | chip4_base | — | +| 0x5C | chip4_bound | — | +| 0x60 | chip5_base | — | +| 0x64 | chip5_bound | — | +| 0x68 | chip6_base | — | +| 0x6C | chip6_bound | — | +| 0x70 | chip7_base | — | +| 0x74 | chip7_bound | — | ### t_latency_access register @@ -88,11 +98,20 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x10 - Size: 0x4 -

RX sampling delay-line tap setting.

+

RX sampling delay with fine taps in bits 4:0 and coarse taps in bits 7:5.

|Bits|Identifier|Access|Reset|Name| |----|----------|------|-----|----| -| 7:0| value | rw | 0x10| — | +| 4:0| fine | rw | 0x10| — | +| 7:5| coarse | rw | 0x0 | — | + +#### fine field + +

Fine delay-line tap setting, nominally about 78 ps per tap.

+ +#### coarse field + +

Coarse delay-line tap setting with an implementation-defined step size.

### t_tx_clk_delay register @@ -100,11 +119,20 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x14 - Size: 0x4 -

TX clock delay-line tap setting.

+

TX clock delay with fine taps in bits 4:0 and coarse taps in bits 7:5.

|Bits|Identifier|Access|Reset|Name| |----|----------|------|-----|----| -| 7:0| value | rw | 0x10| — | +| 4:0| fine | rw | 0x10| — | +| 7:5| coarse | rw | 0x0 | — | + +#### fine field + +

Fine delay-line tap setting, nominally about 78 ps per tap.

+ +#### coarse field + +

Coarse delay-line tap setting with an implementation-defined step size.

### address_mask_msb register @@ -184,11 +212,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x30 - Size: 0x4 -

Inclusive base address for chip-select 0 decoding.

+

Inclusive 4 MiB-aligned address for chip-select 0 decoding.

-|Bits|Identifier|Access|Reset|Name| -|----|----------|------|-----|----| -|31:0| value | rw | 0x0 | — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x0 | — | ### chip0_bound register @@ -196,11 +224,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x34 - Size: 0x4 -

Exclusive bound address for chip-select 0 decoding.

+

Exclusive 4 MiB-aligned address for chip-select 0 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x10000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x1 | — | ### chip1_base register @@ -208,11 +236,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x38 - Size: 0x4 -

Inclusive base address for chip-select 1 decoding.

+

Inclusive 4 MiB-aligned address for chip-select 1 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x10000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x1 | — | ### chip1_bound register @@ -220,11 +248,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x3C - Size: 0x4 -

Exclusive bound address for chip-select 1 decoding.

+

Exclusive 4 MiB-aligned address for chip-select 1 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x20000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x2 | — | ### chip2_base register @@ -232,11 +260,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x40 - Size: 0x4 -

Inclusive base address for chip-select 2 decoding.

+

Inclusive 4 MiB-aligned address for chip-select 2 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x20000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x2 | — | ### chip2_bound register @@ -244,11 +272,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x44 - Size: 0x4 -

Exclusive bound address for chip-select 2 decoding.

+

Exclusive 4 MiB-aligned address for chip-select 2 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x30000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x3 | — | ### chip3_base register @@ -256,11 +284,11 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x48 - Size: 0x4 -

Inclusive base address for chip-select 3 decoding.

+

Inclusive 4 MiB-aligned address for chip-select 3 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x30000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x3 | — | ### chip3_bound register @@ -268,8 +296,104 @@ Don't override. Generated from: hyperbus_cfg_regs - Base Offset: 0x4C - Size: 0x4 -

Exclusive bound address for chip-select 3 decoding.

+

Exclusive 4 MiB-aligned address for chip-select 3 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x4 | — | + +### chip4_base register + +- Absolute Address: 0x58 +- Base Offset: 0x58 +- Size: 0x4 + +

Inclusive 4 MiB-aligned address for chip-select 4 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x4 | — | + +### chip4_bound register + +- Absolute Address: 0x5C +- Base Offset: 0x5C +- Size: 0x4 + +

Exclusive 4 MiB-aligned address for chip-select 4 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x5 | — | + +### chip5_base register + +- Absolute Address: 0x60 +- Base Offset: 0x60 +- Size: 0x4 + +

Inclusive 4 MiB-aligned address for chip-select 5 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x5 | — | + +### chip5_bound register + +- Absolute Address: 0x64 +- Base Offset: 0x64 +- Size: 0x4 + +

Exclusive 4 MiB-aligned address for chip-select 5 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x6 | — | + +### chip6_base register + +- Absolute Address: 0x68 +- Base Offset: 0x68 +- Size: 0x4 + +

Inclusive 4 MiB-aligned address for chip-select 6 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x6 | — | + +### chip6_bound register + +- Absolute Address: 0x6C +- Base Offset: 0x6C +- Size: 0x4 + +

Exclusive 4 MiB-aligned address for chip-select 6 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x7 | — | + +### chip7_base register + +- Absolute Address: 0x70 +- Base Offset: 0x70 +- Size: 0x4 + +

Inclusive 4 MiB-aligned address for chip-select 7 decoding.

+ +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x7 | — | + +### chip7_bound register + +- Absolute Address: 0x74 +- Base Offset: 0x74 +- Size: 0x4 + +

Exclusive 4 MiB-aligned address for chip-select 7 decoding.

-|Bits|Identifier|Access| Reset |Name| -|----|----------|------|-------|----| -|31:0| value | rw |0x40000| — | +| Bits|Identifier|Access|Reset|Name| +|-----|----------|------|-----|----| +|31:22| value | rw | 0x8 | — | diff --git a/include/hyperbus_cfg_regs.h b/include/hyperbus_cfg_regs.h index 795ce1b..a5a09ba 100644 --- a/include/hyperbus_cfg_regs.h +++ b/include/hyperbus_cfg_regs.h @@ -35,16 +35,24 @@ extern "C" { #define HYPERBUS_CFG_REGS__T_READ_WRITE_RECOVERY__VALUE_reset 0x6 // reg - hyperbus_cfg_regs::t_rx_clk_delay -#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bm 0xff -#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_bw 8 -#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__VALUE_reset 0x10 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__FINE_bm 0x1f +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__FINE_bp 0 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__FINE_bw 5 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__FINE_reset 0x10 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__COARSE_bm 0xe0 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__COARSE_bp 5 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__COARSE_bw 3 +#define HYPERBUS_CFG_REGS__T_RX_CLK_DELAY__COARSE_reset 0x0 // reg - hyperbus_cfg_regs::t_tx_clk_delay -#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bm 0xff -#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_bw 8 -#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__VALUE_reset 0x10 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__FINE_bm 0x1f +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__FINE_bp 0 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__FINE_bw 5 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__FINE_reset 0x10 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__COARSE_bm 0xe0 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__COARSE_bp 5 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__COARSE_bw 3 +#define HYPERBUS_CFG_REGS__T_TX_CLK_DELAY__COARSE_reset 0x0 // reg - hyperbus_cfg_regs::address_mask_msb #define HYPERBUS_CFG_REGS__ADDRESS_MASK_MSB__VALUE_bm 0x1f @@ -83,52 +91,100 @@ extern "C" { #define HYPERBUS_CFG_REGS__CSN_TO_CK_CYCLES__VALUE_reset 0x0 // reg - hyperbus_cfg_regs::chip0_base -#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bw 32 +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_bw 10 #define HYPERBUS_CFG_REGS__CHIP0_BASE__VALUE_reset 0x0 // reg - hyperbus_cfg_regs::chip0_bound -#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_reset 0x10000 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP0_BOUND__VALUE_reset 0x1 // reg - hyperbus_cfg_regs::chip1_base -#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_reset 0x10000 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP1_BASE__VALUE_reset 0x1 // reg - hyperbus_cfg_regs::chip1_bound -#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_reset 0x20000 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP1_BOUND__VALUE_reset 0x2 // reg - hyperbus_cfg_regs::chip2_base -#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_reset 0x20000 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP2_BASE__VALUE_reset 0x2 // reg - hyperbus_cfg_regs::chip2_bound -#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_reset 0x30000 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP2_BOUND__VALUE_reset 0x3 // reg - hyperbus_cfg_regs::chip3_base -#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_reset 0x30000 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP3_BASE__VALUE_reset 0x3 // reg - hyperbus_cfg_regs::chip3_bound -#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bm 0xffffffff -#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bp 0 -#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bw 32 -#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_reset 0x40000 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP3_BOUND__VALUE_reset 0x4 + +// reg - hyperbus_cfg_regs::chip4_base +#define HYPERBUS_CFG_REGS__CHIP4_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP4_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP4_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP4_BASE__VALUE_reset 0x4 + +// reg - hyperbus_cfg_regs::chip4_bound +#define HYPERBUS_CFG_REGS__CHIP4_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP4_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP4_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP4_BOUND__VALUE_reset 0x5 + +// reg - hyperbus_cfg_regs::chip5_base +#define HYPERBUS_CFG_REGS__CHIP5_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP5_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP5_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP5_BASE__VALUE_reset 0x5 + +// reg - hyperbus_cfg_regs::chip5_bound +#define HYPERBUS_CFG_REGS__CHIP5_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP5_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP5_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP5_BOUND__VALUE_reset 0x6 + +// reg - hyperbus_cfg_regs::chip6_base +#define HYPERBUS_CFG_REGS__CHIP6_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP6_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP6_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP6_BASE__VALUE_reset 0x6 + +// reg - hyperbus_cfg_regs::chip6_bound +#define HYPERBUS_CFG_REGS__CHIP6_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP6_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP6_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP6_BOUND__VALUE_reset 0x7 + +// reg - hyperbus_cfg_regs::chip7_base +#define HYPERBUS_CFG_REGS__CHIP7_BASE__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP7_BASE__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP7_BASE__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP7_BASE__VALUE_reset 0x7 + +// reg - hyperbus_cfg_regs::chip7_bound +#define HYPERBUS_CFG_REGS__CHIP7_BOUND__VALUE_bm 0xffc00000 +#define HYPERBUS_CFG_REGS__CHIP7_BOUND__VALUE_bp 22 +#define HYPERBUS_CFG_REGS__CHIP7_BOUND__VALUE_bw 10 +#define HYPERBUS_CFG_REGS__CHIP7_BOUND__VALUE_reset 0x8 // addrmap - hyperbus_cfg_regs typedef struct __attribute__ ((__packed__)) { @@ -152,10 +208,19 @@ typedef struct __attribute__ ((__packed__)) { uint32_t chip2_bound; uint32_t chip3_base; uint32_t chip3_bound; + uint8_t RESERVED_50_57[0x8]; + uint32_t chip4_base; + uint32_t chip4_bound; + uint32_t chip5_base; + uint32_t chip5_bound; + uint32_t chip6_base; + uint32_t chip6_bound; + uint32_t chip7_base; + uint32_t chip7_bound; } hyperbus_cfg_regs_t; -static_assert(sizeof(hyperbus_cfg_regs_t) == 0x50, "Packing error"); +static_assert(sizeof(hyperbus_cfg_regs_t) == 0x78, "Packing error"); #ifdef __cplusplus } diff --git a/src/hyperbus_cfg_regs.sv b/src/hyperbus_cfg_regs.sv index 46310a5..84e792f 100644 --- a/src/hyperbus_cfg_regs.sv +++ b/src/hyperbus_cfg_regs.sv @@ -25,8 +25,8 @@ module hyperbus_cfg_regs #( ); `include "common_cells/registers.svh" - localparam int unsigned NumChipsMax = 4; - localparam int unsigned NumRegs = 2*NumChipsMax + 12; + localparam int unsigned NumChipsMax = 8; + localparam int unsigned NumRegs = 30; localparam int unsigned RegsBits = cf_math_pkg::idx_width(NumRegs); localparam int unsigned RegStrbWidth = RegDataWidth/8; @@ -112,20 +112,52 @@ module hyperbus_cfg_regs #( chip_rules_all[i].idx = unsigned'(i); unique case (i) 0: begin - chip_rules_all[i].start_addr = cfg_hwif_out.chip0_base.value.value; - chip_rules_all[i].end_addr = cfg_hwif_out.chip0_bound.value.value; + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip0_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip0_bound.value.value, 22'b0}; end 1: begin - chip_rules_all[i].start_addr = cfg_hwif_out.chip1_base.value.value; - chip_rules_all[i].end_addr = cfg_hwif_out.chip1_bound.value.value; + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip1_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip1_bound.value.value, 22'b0}; end 2: begin - chip_rules_all[i].start_addr = cfg_hwif_out.chip2_base.value.value; - chip_rules_all[i].end_addr = cfg_hwif_out.chip2_bound.value.value; + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip2_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip2_bound.value.value, 22'b0}; end 3: begin - chip_rules_all[i].start_addr = cfg_hwif_out.chip3_base.value.value; - chip_rules_all[i].end_addr = cfg_hwif_out.chip3_bound.value.value; + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip3_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip3_bound.value.value, 22'b0}; + end + 4: begin + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip4_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip4_bound.value.value, 22'b0}; + end + 5: begin + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip5_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip5_bound.value.value, 22'b0}; + end + 6: begin + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip6_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip6_bound.value.value, 22'b0}; + end + 7: begin + chip_rules_all[i].start_addr = { + cfg_hwif_out.chip7_base.value.value, 22'b0}; + chip_rules_all[i].end_addr = { + cfg_hwif_out.chip7_bound.value.value, 22'b0}; end default:; endcase @@ -179,7 +211,7 @@ module hyperbus_cfg_regs #( initial assert (RegDataWidth == 32) else $error("Generated HyperBus config registers require 32-bit RegDataWidth."); initial assert (NumChips <= NumChipsMax) - else $error("Generated HyperBus config registers support up to four chips."); + else $error("Generated HyperBus config registers support up to eight chips."); `endif // pragma translate_on diff --git a/src/hyperbus_pkg.sv b/src/hyperbus_pkg.sv index 664e647..1fa6219 100644 --- a/src/hyperbus_pkg.sv +++ b/src/hyperbus_pkg.sv @@ -57,10 +57,16 @@ package hyperbus_pkg; cfg.chip.en_latency_additional = hwif.en_latency_additional.value.value; cfg.chip.t_burst_max = hwif.t_burst_max.value.value; cfg.chip.t_read_write_recovery = hwif.t_read_write_recovery.value.value; - cfg.chip.t_rx_clk_delay = hwif.t_rx_clk_delay.value.value; + cfg.chip.t_rx_clk_delay = { + hwif.t_rx_clk_delay.coarse.value, + hwif.t_rx_clk_delay.fine.value + }; cfg.chip.t_csh_cycles = hwif.t_csh_cycles.value.value; cfg.chip.csn_to_ck_cycles = hwif.csn_to_ck_cycles.value.value; - cfg.t_tx_clk_delay = hwif.t_tx_clk_delay.value.value; + cfg.t_tx_clk_delay = { + hwif.t_tx_clk_delay.coarse.value, + hwif.t_tx_clk_delay.fine.value + }; cfg.phys_in_use = num_phys_one ? 1'b0 : hwif.phys_in_use.value.value; cfg.which_phy = num_phys_one ? 1'b0 : hwif.which_phy.value.value; diff --git a/src/regs/hyperbus_cfg_regblock.sv b/src/regs/hyperbus_cfg_regblock.sv index 5cbcc73..75b0286 100644 --- a/src/regs/hyperbus_cfg_regblock.sv +++ b/src/regs/hyperbus_cfg_regblock.sv @@ -106,6 +106,14 @@ module hyperbus_cfg_regblock ( logic chip2_bound; logic chip3_base; logic chip3_bound; + logic chip4_base; + logic chip4_bound; + logic chip5_base; + logic chip5_bound; + logic chip6_base; + logic chip6_bound; + logic chip7_base; + logic chip7_bound; } decoded_reg_strb_t; decoded_reg_strb_t decoded_reg_strb; logic decoded_err; @@ -140,6 +148,14 @@ module hyperbus_cfg_regblock ( decoded_reg_strb.chip2_bound = cpuif_req_masked & (cpuif_addr == 7'h44); decoded_reg_strb.chip3_base = cpuif_req_masked & (cpuif_addr == 7'h48); decoded_reg_strb.chip3_bound = cpuif_req_masked & (cpuif_addr == 7'h4c); + decoded_reg_strb.chip4_base = cpuif_req_masked & (cpuif_addr == 7'h58); + decoded_reg_strb.chip4_bound = cpuif_req_masked & (cpuif_addr == 7'h5c); + decoded_reg_strb.chip5_base = cpuif_req_masked & (cpuif_addr == 7'h60); + decoded_reg_strb.chip5_bound = cpuif_req_masked & (cpuif_addr == 7'h64); + decoded_reg_strb.chip6_base = cpuif_req_masked & (cpuif_addr == 7'h68); + decoded_reg_strb.chip6_bound = cpuif_req_masked & (cpuif_addr == 7'h6c); + decoded_reg_strb.chip7_base = cpuif_req_masked & (cpuif_addr == 7'h70); + decoded_reg_strb.chip7_bound = cpuif_req_masked & (cpuif_addr == 7'h74); decoded_err = '0; end @@ -180,15 +196,23 @@ module hyperbus_cfg_regblock ( } t_read_write_recovery; struct { struct { - logic [7:0] next; + logic [4:0] next; logic load_next; - } value; + } fine; + struct { + logic [2:0] next; + logic load_next; + } coarse; } t_rx_clk_delay; struct { struct { - logic [7:0] next; + logic [4:0] next; logic load_next; - } value; + } fine; + struct { + logic [2:0] next; + logic load_next; + } coarse; } t_tx_clk_delay; struct { struct { @@ -228,52 +252,100 @@ module hyperbus_cfg_regblock ( } csn_to_ck_cycles; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip0_base; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip0_bound; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip1_base; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip1_bound; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip2_base; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip2_bound; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip3_base; struct { struct { - logic [31:0] next; + logic [9:0] next; logic load_next; } value; } chip3_bound; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip4_base; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip4_bound; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip5_base; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip5_bound; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip6_base; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip6_bound; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip7_base; + struct { + struct { + logic [9:0] next; + logic load_next; + } value; + } chip7_bound; } field_combo_t; field_combo_t field_combo; @@ -300,13 +372,19 @@ module hyperbus_cfg_regblock ( } t_read_write_recovery; struct { struct { - logic [7:0] value; - } value; + logic [4:0] value; + } fine; + struct { + logic [2:0] value; + } coarse; } t_rx_clk_delay; struct { struct { - logic [7:0] value; - } value; + logic [4:0] value; + } fine; + struct { + logic [2:0] value; + } coarse; } t_tx_clk_delay; struct { struct { @@ -340,44 +418,84 @@ module hyperbus_cfg_regblock ( } csn_to_ck_cycles; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip0_base; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip0_bound; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip1_base; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip1_bound; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip2_base; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip2_bound; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip3_base; struct { struct { - logic [31:0] value; + logic [9:0] value; } value; } chip3_bound; + struct { + struct { + logic [9:0] value; + } value; + } chip4_base; + struct { + struct { + logic [9:0] value; + } value; + } chip4_bound; + struct { + struct { + logic [9:0] value; + } value; + } chip5_base; + struct { + struct { + logic [9:0] value; + } value; + } chip5_bound; + struct { + struct { + logic [9:0] value; + } value; + } chip6_base; + struct { + struct { + logic [9:0] value; + } value; + } chip6_bound; + struct { + struct { + logic [9:0] value; + } value; + } chip7_base; + struct { + struct { + logic [9:0] value; + } value; + } chip7_bound; } field_storage_t; field_storage_t field_storage; @@ -473,52 +591,98 @@ module hyperbus_cfg_regblock ( end end assign hwif_out.t_read_write_recovery.value.value = field_storage.t_read_write_recovery.value.value; - // Field: hyperbus_cfg_regs.t_rx_clk_delay.value + // Field: hyperbus_cfg_regs.t_rx_clk_delay.fine + always_comb begin + automatic logic [4:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_rx_clk_delay.fine.value; + load_next_c = '0; + if(decoded_reg_strb.t_rx_clk_delay && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_rx_clk_delay.fine.value & ~decoded_wr_biten[4:0]) | (decoded_wr_data[4:0] & decoded_wr_biten[4:0]); + load_next_c = '1; + end + field_combo.t_rx_clk_delay.fine.next = next_c; + field_combo.t_rx_clk_delay.fine.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_rx_clk_delay.fine.value <= 5'h10; + end else begin + if(field_combo.t_rx_clk_delay.fine.load_next) begin + field_storage.t_rx_clk_delay.fine.value <= field_combo.t_rx_clk_delay.fine.next; + end + end + end + assign hwif_out.t_rx_clk_delay.fine.value = field_storage.t_rx_clk_delay.fine.value; + // Field: hyperbus_cfg_regs.t_rx_clk_delay.coarse always_comb begin - automatic logic [7:0] next_c; + automatic logic [2:0] next_c; automatic logic load_next_c; - next_c = field_storage.t_rx_clk_delay.value.value; + next_c = field_storage.t_rx_clk_delay.coarse.value; load_next_c = '0; if(decoded_reg_strb.t_rx_clk_delay && decoded_req_is_wr) begin // SW write - next_c = (field_storage.t_rx_clk_delay.value.value & ~decoded_wr_biten[7:0]) | (decoded_wr_data[7:0] & decoded_wr_biten[7:0]); + next_c = (field_storage.t_rx_clk_delay.coarse.value & ~decoded_wr_biten[7:5]) | (decoded_wr_data[7:5] & decoded_wr_biten[7:5]); load_next_c = '1; end - field_combo.t_rx_clk_delay.value.next = next_c; - field_combo.t_rx_clk_delay.value.load_next = load_next_c; + field_combo.t_rx_clk_delay.coarse.next = next_c; + field_combo.t_rx_clk_delay.coarse.load_next = load_next_c; end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.t_rx_clk_delay.value.value <= 8'h10; + field_storage.t_rx_clk_delay.coarse.value <= 3'h0; end else begin - if(field_combo.t_rx_clk_delay.value.load_next) begin - field_storage.t_rx_clk_delay.value.value <= field_combo.t_rx_clk_delay.value.next; + if(field_combo.t_rx_clk_delay.coarse.load_next) begin + field_storage.t_rx_clk_delay.coarse.value <= field_combo.t_rx_clk_delay.coarse.next; end end end - assign hwif_out.t_rx_clk_delay.value.value = field_storage.t_rx_clk_delay.value.value; - // Field: hyperbus_cfg_regs.t_tx_clk_delay.value + assign hwif_out.t_rx_clk_delay.coarse.value = field_storage.t_rx_clk_delay.coarse.value; + // Field: hyperbus_cfg_regs.t_tx_clk_delay.fine always_comb begin - automatic logic [7:0] next_c; + automatic logic [4:0] next_c; automatic logic load_next_c; - next_c = field_storage.t_tx_clk_delay.value.value; + next_c = field_storage.t_tx_clk_delay.fine.value; load_next_c = '0; if(decoded_reg_strb.t_tx_clk_delay && decoded_req_is_wr) begin // SW write - next_c = (field_storage.t_tx_clk_delay.value.value & ~decoded_wr_biten[7:0]) | (decoded_wr_data[7:0] & decoded_wr_biten[7:0]); + next_c = (field_storage.t_tx_clk_delay.fine.value & ~decoded_wr_biten[4:0]) | (decoded_wr_data[4:0] & decoded_wr_biten[4:0]); load_next_c = '1; end - field_combo.t_tx_clk_delay.value.next = next_c; - field_combo.t_tx_clk_delay.value.load_next = load_next_c; + field_combo.t_tx_clk_delay.fine.next = next_c; + field_combo.t_tx_clk_delay.fine.load_next = load_next_c; end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.t_tx_clk_delay.value.value <= 8'h10; + field_storage.t_tx_clk_delay.fine.value <= 5'h10; end else begin - if(field_combo.t_tx_clk_delay.value.load_next) begin - field_storage.t_tx_clk_delay.value.value <= field_combo.t_tx_clk_delay.value.next; + if(field_combo.t_tx_clk_delay.fine.load_next) begin + field_storage.t_tx_clk_delay.fine.value <= field_combo.t_tx_clk_delay.fine.next; end end end - assign hwif_out.t_tx_clk_delay.value.value = field_storage.t_tx_clk_delay.value.value; + assign hwif_out.t_tx_clk_delay.fine.value = field_storage.t_tx_clk_delay.fine.value; + // Field: hyperbus_cfg_regs.t_tx_clk_delay.coarse + always_comb begin + automatic logic [2:0] next_c; + automatic logic load_next_c; + next_c = field_storage.t_tx_clk_delay.coarse.value; + load_next_c = '0; + if(decoded_reg_strb.t_tx_clk_delay && decoded_req_is_wr) begin // SW write + next_c = (field_storage.t_tx_clk_delay.coarse.value & ~decoded_wr_biten[7:5]) | (decoded_wr_data[7:5] & decoded_wr_biten[7:5]); + load_next_c = '1; + end + field_combo.t_tx_clk_delay.coarse.next = next_c; + field_combo.t_tx_clk_delay.coarse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.t_tx_clk_delay.coarse.value <= 3'h0; + end else begin + if(field_combo.t_tx_clk_delay.coarse.load_next) begin + field_storage.t_tx_clk_delay.coarse.value <= field_combo.t_tx_clk_delay.coarse.next; + end + end + end + assign hwif_out.t_tx_clk_delay.coarse.value = field_storage.t_tx_clk_delay.coarse.value; // Field: hyperbus_cfg_regs.address_mask_msb.value always_comb begin automatic logic [4:0] next_c; @@ -659,12 +823,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.csn_to_ck_cycles.value.value = field_storage.csn_to_ck_cycles.value.value; // Field: hyperbus_cfg_regs.chip0_base.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip0_base.value.value; load_next_c = '0; if(decoded_reg_strb.chip0_base && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip0_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip0_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip0_base.value.next = next_c; @@ -672,7 +836,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip0_base.value.value <= 32'h0; + field_storage.chip0_base.value.value <= 10'h0; end else begin if(field_combo.chip0_base.value.load_next) begin field_storage.chip0_base.value.value <= field_combo.chip0_base.value.next; @@ -682,12 +846,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip0_base.value.value = field_storage.chip0_base.value.value; // Field: hyperbus_cfg_regs.chip0_bound.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip0_bound.value.value; load_next_c = '0; if(decoded_reg_strb.chip0_bound && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip0_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip0_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip0_bound.value.next = next_c; @@ -695,7 +859,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip0_bound.value.value <= 32'h10000; + field_storage.chip0_bound.value.value <= 10'h1; end else begin if(field_combo.chip0_bound.value.load_next) begin field_storage.chip0_bound.value.value <= field_combo.chip0_bound.value.next; @@ -705,12 +869,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip0_bound.value.value = field_storage.chip0_bound.value.value; // Field: hyperbus_cfg_regs.chip1_base.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip1_base.value.value; load_next_c = '0; if(decoded_reg_strb.chip1_base && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip1_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip1_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip1_base.value.next = next_c; @@ -718,7 +882,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip1_base.value.value <= 32'h10000; + field_storage.chip1_base.value.value <= 10'h1; end else begin if(field_combo.chip1_base.value.load_next) begin field_storage.chip1_base.value.value <= field_combo.chip1_base.value.next; @@ -728,12 +892,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip1_base.value.value = field_storage.chip1_base.value.value; // Field: hyperbus_cfg_regs.chip1_bound.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip1_bound.value.value; load_next_c = '0; if(decoded_reg_strb.chip1_bound && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip1_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip1_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip1_bound.value.next = next_c; @@ -741,7 +905,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip1_bound.value.value <= 32'h20000; + field_storage.chip1_bound.value.value <= 10'h2; end else begin if(field_combo.chip1_bound.value.load_next) begin field_storage.chip1_bound.value.value <= field_combo.chip1_bound.value.next; @@ -751,12 +915,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip1_bound.value.value = field_storage.chip1_bound.value.value; // Field: hyperbus_cfg_regs.chip2_base.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip2_base.value.value; load_next_c = '0; if(decoded_reg_strb.chip2_base && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip2_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip2_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip2_base.value.next = next_c; @@ -764,7 +928,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip2_base.value.value <= 32'h20000; + field_storage.chip2_base.value.value <= 10'h2; end else begin if(field_combo.chip2_base.value.load_next) begin field_storage.chip2_base.value.value <= field_combo.chip2_base.value.next; @@ -774,12 +938,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip2_base.value.value = field_storage.chip2_base.value.value; // Field: hyperbus_cfg_regs.chip2_bound.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip2_bound.value.value; load_next_c = '0; if(decoded_reg_strb.chip2_bound && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip2_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip2_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip2_bound.value.next = next_c; @@ -787,7 +951,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip2_bound.value.value <= 32'h30000; + field_storage.chip2_bound.value.value <= 10'h3; end else begin if(field_combo.chip2_bound.value.load_next) begin field_storage.chip2_bound.value.value <= field_combo.chip2_bound.value.next; @@ -797,12 +961,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip2_bound.value.value = field_storage.chip2_bound.value.value; // Field: hyperbus_cfg_regs.chip3_base.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip3_base.value.value; load_next_c = '0; if(decoded_reg_strb.chip3_base && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip3_base.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip3_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip3_base.value.next = next_c; @@ -810,7 +974,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip3_base.value.value <= 32'h30000; + field_storage.chip3_base.value.value <= 10'h3; end else begin if(field_combo.chip3_base.value.load_next) begin field_storage.chip3_base.value.value <= field_combo.chip3_base.value.next; @@ -820,12 +984,12 @@ module hyperbus_cfg_regblock ( assign hwif_out.chip3_base.value.value = field_storage.chip3_base.value.value; // Field: hyperbus_cfg_regs.chip3_bound.value always_comb begin - automatic logic [31:0] next_c; + automatic logic [9:0] next_c; automatic logic load_next_c; next_c = field_storage.chip3_bound.value.value; load_next_c = '0; if(decoded_reg_strb.chip3_bound && decoded_req_is_wr) begin // SW write - next_c = (field_storage.chip3_bound.value.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + next_c = (field_storage.chip3_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); load_next_c = '1; end field_combo.chip3_bound.value.next = next_c; @@ -833,7 +997,7 @@ module hyperbus_cfg_regblock ( end always_ff @(posedge clk or negedge arst_n) begin if(~arst_n) begin - field_storage.chip3_bound.value.value <= 32'h40000; + field_storage.chip3_bound.value.value <= 10'h4; end else begin if(field_combo.chip3_bound.value.load_next) begin field_storage.chip3_bound.value.value <= field_combo.chip3_bound.value.next; @@ -841,6 +1005,190 @@ module hyperbus_cfg_regblock ( end end assign hwif_out.chip3_bound.value.value = field_storage.chip3_bound.value.value; + // Field: hyperbus_cfg_regs.chip4_base.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip4_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip4_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip4_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip4_base.value.next = next_c; + field_combo.chip4_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip4_base.value.value <= 10'h4; + end else begin + if(field_combo.chip4_base.value.load_next) begin + field_storage.chip4_base.value.value <= field_combo.chip4_base.value.next; + end + end + end + assign hwif_out.chip4_base.value.value = field_storage.chip4_base.value.value; + // Field: hyperbus_cfg_regs.chip4_bound.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip4_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip4_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip4_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip4_bound.value.next = next_c; + field_combo.chip4_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip4_bound.value.value <= 10'h5; + end else begin + if(field_combo.chip4_bound.value.load_next) begin + field_storage.chip4_bound.value.value <= field_combo.chip4_bound.value.next; + end + end + end + assign hwif_out.chip4_bound.value.value = field_storage.chip4_bound.value.value; + // Field: hyperbus_cfg_regs.chip5_base.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip5_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip5_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip5_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip5_base.value.next = next_c; + field_combo.chip5_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip5_base.value.value <= 10'h5; + end else begin + if(field_combo.chip5_base.value.load_next) begin + field_storage.chip5_base.value.value <= field_combo.chip5_base.value.next; + end + end + end + assign hwif_out.chip5_base.value.value = field_storage.chip5_base.value.value; + // Field: hyperbus_cfg_regs.chip5_bound.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip5_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip5_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip5_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip5_bound.value.next = next_c; + field_combo.chip5_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip5_bound.value.value <= 10'h6; + end else begin + if(field_combo.chip5_bound.value.load_next) begin + field_storage.chip5_bound.value.value <= field_combo.chip5_bound.value.next; + end + end + end + assign hwif_out.chip5_bound.value.value = field_storage.chip5_bound.value.value; + // Field: hyperbus_cfg_regs.chip6_base.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip6_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip6_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip6_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip6_base.value.next = next_c; + field_combo.chip6_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip6_base.value.value <= 10'h6; + end else begin + if(field_combo.chip6_base.value.load_next) begin + field_storage.chip6_base.value.value <= field_combo.chip6_base.value.next; + end + end + end + assign hwif_out.chip6_base.value.value = field_storage.chip6_base.value.value; + // Field: hyperbus_cfg_regs.chip6_bound.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip6_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip6_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip6_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip6_bound.value.next = next_c; + field_combo.chip6_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip6_bound.value.value <= 10'h7; + end else begin + if(field_combo.chip6_bound.value.load_next) begin + field_storage.chip6_bound.value.value <= field_combo.chip6_bound.value.next; + end + end + end + assign hwif_out.chip6_bound.value.value = field_storage.chip6_bound.value.value; + // Field: hyperbus_cfg_regs.chip7_base.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip7_base.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip7_base && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip7_base.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip7_base.value.next = next_c; + field_combo.chip7_base.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip7_base.value.value <= 10'h7; + end else begin + if(field_combo.chip7_base.value.load_next) begin + field_storage.chip7_base.value.value <= field_combo.chip7_base.value.next; + end + end + end + assign hwif_out.chip7_base.value.value = field_storage.chip7_base.value.value; + // Field: hyperbus_cfg_regs.chip7_bound.value + always_comb begin + automatic logic [9:0] next_c; + automatic logic load_next_c; + next_c = field_storage.chip7_bound.value.value; + load_next_c = '0; + if(decoded_reg_strb.chip7_bound && decoded_req_is_wr) begin // SW write + next_c = (field_storage.chip7_bound.value.value & ~decoded_wr_biten[31:22]) | (decoded_wr_data[31:22] & decoded_wr_biten[31:22]); + load_next_c = '1; + end + field_combo.chip7_bound.value.next = next_c; + field_combo.chip7_bound.value.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.chip7_bound.value.value <= 10'h8; + end else begin + if(field_combo.chip7_bound.value.load_next) begin + field_storage.chip7_bound.value.value <= field_combo.chip7_bound.value.next; + end + end + end + assign hwif_out.chip7_bound.value.value = field_storage.chip7_bound.value.value; //-------------------------------------------------------------------------- // Write response @@ -875,10 +1223,12 @@ module hyperbus_cfg_regblock ( readback_data_var[3:0] = field_storage.t_read_write_recovery.value.value; end if(rd_mux_addr == 7'h10) begin - readback_data_var[7:0] = field_storage.t_rx_clk_delay.value.value; + readback_data_var[4:0] = field_storage.t_rx_clk_delay.fine.value; + readback_data_var[7:5] = field_storage.t_rx_clk_delay.coarse.value; end if(rd_mux_addr == 7'h14) begin - readback_data_var[7:0] = field_storage.t_tx_clk_delay.value.value; + readback_data_var[4:0] = field_storage.t_tx_clk_delay.fine.value; + readback_data_var[7:5] = field_storage.t_tx_clk_delay.coarse.value; end if(rd_mux_addr == 7'h18) begin readback_data_var[4:0] = field_storage.address_mask_msb.value.value; @@ -899,28 +1249,52 @@ module hyperbus_cfg_regblock ( readback_data_var[3:0] = field_storage.csn_to_ck_cycles.value.value; end if(rd_mux_addr == 7'h30) begin - readback_data_var[31:0] = field_storage.chip0_base.value.value; + readback_data_var[31:22] = field_storage.chip0_base.value.value; end if(rd_mux_addr == 7'h34) begin - readback_data_var[31:0] = field_storage.chip0_bound.value.value; + readback_data_var[31:22] = field_storage.chip0_bound.value.value; end if(rd_mux_addr == 7'h38) begin - readback_data_var[31:0] = field_storage.chip1_base.value.value; + readback_data_var[31:22] = field_storage.chip1_base.value.value; end if(rd_mux_addr == 7'h3c) begin - readback_data_var[31:0] = field_storage.chip1_bound.value.value; + readback_data_var[31:22] = field_storage.chip1_bound.value.value; end if(rd_mux_addr == 7'h40) begin - readback_data_var[31:0] = field_storage.chip2_base.value.value; + readback_data_var[31:22] = field_storage.chip2_base.value.value; end if(rd_mux_addr == 7'h44) begin - readback_data_var[31:0] = field_storage.chip2_bound.value.value; + readback_data_var[31:22] = field_storage.chip2_bound.value.value; end if(rd_mux_addr == 7'h48) begin - readback_data_var[31:0] = field_storage.chip3_base.value.value; + readback_data_var[31:22] = field_storage.chip3_base.value.value; end if(rd_mux_addr == 7'h4c) begin - readback_data_var[31:0] = field_storage.chip3_bound.value.value; + readback_data_var[31:22] = field_storage.chip3_bound.value.value; + end + if(rd_mux_addr == 7'h58) begin + readback_data_var[31:22] = field_storage.chip4_base.value.value; + end + if(rd_mux_addr == 7'h5c) begin + readback_data_var[31:22] = field_storage.chip4_bound.value.value; + end + if(rd_mux_addr == 7'h60) begin + readback_data_var[31:22] = field_storage.chip5_base.value.value; + end + if(rd_mux_addr == 7'h64) begin + readback_data_var[31:22] = field_storage.chip5_bound.value.value; + end + if(rd_mux_addr == 7'h68) begin + readback_data_var[31:22] = field_storage.chip6_base.value.value; + end + if(rd_mux_addr == 7'h6c) begin + readback_data_var[31:22] = field_storage.chip6_bound.value.value; + end + if(rd_mux_addr == 7'h70) begin + readback_data_var[31:22] = field_storage.chip7_base.value.value; + end + if(rd_mux_addr == 7'h74) begin + readback_data_var[31:22] = field_storage.chip7_bound.value.value; end readback_data = readback_data_var; readback_done = decoded_req & ~decoded_req_is_wr; diff --git a/src/regs/hyperbus_cfg_regblock_pkg.sv b/src/regs/hyperbus_cfg_regblock_pkg.sv index 59572c7..85c5edb 100644 --- a/src/regs/hyperbus_cfg_regblock_pkg.sv +++ b/src/regs/hyperbus_cfg_regblock_pkg.sv @@ -5,7 +5,7 @@ package hyperbus_cfg_regblock_pkg; localparam HYPERBUS_CFG_REGBLOCK_DATA_WIDTH = 32; localparam HYPERBUS_CFG_REGBLOCK_MIN_ADDR_WIDTH = 7; - localparam HYPERBUS_CFG_REGBLOCK_SIZE = 'h50; + localparam HYPERBUS_CFG_REGBLOCK_SIZE = 'h78; typedef struct { logic [3:0] value; @@ -40,19 +40,29 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__t_read_write_recovery__out_t; typedef struct { - logic [7:0] value; - } hyperbus_cfg_regs__t_rx_clk_delay__value__out_t; + logic [4:0] value; + } hyperbus_cfg_regs__t_rx_clk_delay__fine__out_t; + + typedef struct { + logic [2:0] value; + } hyperbus_cfg_regs__t_rx_clk_delay__coarse__out_t; typedef struct { - hyperbus_cfg_regs__t_rx_clk_delay__value__out_t value; + hyperbus_cfg_regs__t_rx_clk_delay__fine__out_t fine; + hyperbus_cfg_regs__t_rx_clk_delay__coarse__out_t coarse; } hyperbus_cfg_regs__t_rx_clk_delay__out_t; typedef struct { - logic [7:0] value; - } hyperbus_cfg_regs__t_tx_clk_delay__value__out_t; + logic [4:0] value; + } hyperbus_cfg_regs__t_tx_clk_delay__fine__out_t; + + typedef struct { + logic [2:0] value; + } hyperbus_cfg_regs__t_tx_clk_delay__coarse__out_t; typedef struct { - hyperbus_cfg_regs__t_tx_clk_delay__value__out_t value; + hyperbus_cfg_regs__t_tx_clk_delay__fine__out_t fine; + hyperbus_cfg_regs__t_tx_clk_delay__coarse__out_t coarse; } hyperbus_cfg_regs__t_tx_clk_delay__out_t; typedef struct { @@ -104,7 +114,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__csn_to_ck_cycles__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip0_base__value__out_t; typedef struct { @@ -112,7 +122,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip0_base__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip0_bound__value__out_t; typedef struct { @@ -120,7 +130,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip0_bound__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip1_base__value__out_t; typedef struct { @@ -128,7 +138,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip1_base__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip1_bound__value__out_t; typedef struct { @@ -136,7 +146,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip1_bound__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip2_base__value__out_t; typedef struct { @@ -144,7 +154,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip2_base__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip2_bound__value__out_t; typedef struct { @@ -152,7 +162,7 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip2_bound__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip3_base__value__out_t; typedef struct { @@ -160,13 +170,77 @@ package hyperbus_cfg_regblock_pkg; } hyperbus_cfg_regs__chip3_base__out_t; typedef struct { - logic [31:0] value; + logic [9:0] value; } hyperbus_cfg_regs__chip3_bound__value__out_t; typedef struct { hyperbus_cfg_regs__chip3_bound__value__out_t value; } hyperbus_cfg_regs__chip3_bound__out_t; + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip4_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip4_base__value__out_t value; + } hyperbus_cfg_regs__chip4_base__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip4_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip4_bound__value__out_t value; + } hyperbus_cfg_regs__chip4_bound__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip5_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip5_base__value__out_t value; + } hyperbus_cfg_regs__chip5_base__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip5_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip5_bound__value__out_t value; + } hyperbus_cfg_regs__chip5_bound__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip6_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip6_base__value__out_t value; + } hyperbus_cfg_regs__chip6_base__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip6_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip6_bound__value__out_t value; + } hyperbus_cfg_regs__chip6_bound__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip7_base__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip7_base__value__out_t value; + } hyperbus_cfg_regs__chip7_base__out_t; + + typedef struct { + logic [9:0] value; + } hyperbus_cfg_regs__chip7_bound__value__out_t; + + typedef struct { + hyperbus_cfg_regs__chip7_bound__value__out_t value; + } hyperbus_cfg_regs__chip7_bound__out_t; + typedef struct { hyperbus_cfg_regs__t_latency_access__out_t t_latency_access; hyperbus_cfg_regs__en_latency_additional__out_t en_latency_additional; @@ -188,5 +262,13 @@ package hyperbus_cfg_regblock_pkg; hyperbus_cfg_regs__chip2_bound__out_t chip2_bound; hyperbus_cfg_regs__chip3_base__out_t chip3_base; hyperbus_cfg_regs__chip3_bound__out_t chip3_bound; + hyperbus_cfg_regs__chip4_base__out_t chip4_base; + hyperbus_cfg_regs__chip4_bound__out_t chip4_bound; + hyperbus_cfg_regs__chip5_base__out_t chip5_base; + hyperbus_cfg_regs__chip5_bound__out_t chip5_bound; + hyperbus_cfg_regs__chip6_base__out_t chip6_base; + hyperbus_cfg_regs__chip6_bound__out_t chip6_bound; + hyperbus_cfg_regs__chip7_base__out_t chip7_base; + hyperbus_cfg_regs__chip7_bound__out_t chip7_bound; } hyperbus_cfg_regs__out_t; endpackage diff --git a/src/regs/hyperbus_cfg_regs.rdl b/src/regs/hyperbus_cfg_regs.rdl index 5e49b7d..515e294 100644 --- a/src/regs/hyperbus_cfg_regs.rdl +++ b/src/regs/hyperbus_cfg_regs.rdl @@ -1,4 +1,6 @@ addrmap hyperbus_cfg_regs { + desc = "HyperBus controller configuration. Chip address ranges must be 4 MiB aligned, ordered by chip-select index, and non-overlapping."; + reg t_latency_access { desc = "Initial latency cycles before read or write data."; field { sw = rw; hw = r; reset = 4'h6; } value[3:0]; @@ -20,13 +22,35 @@ addrmap hyperbus_cfg_regs { }; reg t_rx_clk_delay { - desc = "RX sampling delay-line tap setting."; - field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; + desc = "RX sampling delay with fine taps in bits 4:0 and coarse taps in bits 7:5."; + field { + desc = "Fine delay-line tap setting, nominally about 78 ps per tap."; + sw = rw; + hw = r; + reset = 5'h10; + } fine[4:0]; + field { + desc = "Coarse delay-line tap setting with an implementation-defined step size."; + sw = rw; + hw = r; + reset = 3'h0; + } coarse[7:5]; }; reg t_tx_clk_delay { - desc = "TX clock delay-line tap setting."; - field { sw = rw; hw = r; reset = 8'h10; } value[7:0]; + desc = "TX clock delay with fine taps in bits 4:0 and coarse taps in bits 7:5."; + field { + desc = "Fine delay-line tap setting, nominally about 78 ps per tap."; + sw = rw; + hw = r; + reset = 5'h10; + } fine[4:0]; + field { + desc = "Coarse delay-line tap setting with an implementation-defined step size."; + sw = rw; + hw = r; + reset = 3'h0; + } coarse[7:5]; }; reg address_mask_msb { @@ -60,43 +84,83 @@ addrmap hyperbus_cfg_regs { }; reg chip0_base { - desc = "Inclusive base address for chip-select 0 decoding."; - field { sw = rw; hw = r; reset = 32'h0000_0000; } value[31:0]; + desc = "Inclusive 4 MiB-aligned address for chip-select 0 decoding."; + field { sw = rw; hw = r; reset = 10'd0; } value[31:22]; }; reg chip0_bound { - desc = "Exclusive bound address for chip-select 0 decoding."; - field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; + desc = "Exclusive 4 MiB-aligned address for chip-select 0 decoding."; + field { sw = rw; hw = r; reset = 10'd1; } value[31:22]; }; reg chip1_base { - desc = "Inclusive base address for chip-select 1 decoding."; - field { sw = rw; hw = r; reset = 32'h0001_0000; } value[31:0]; + desc = "Inclusive 4 MiB-aligned address for chip-select 1 decoding."; + field { sw = rw; hw = r; reset = 10'd1; } value[31:22]; }; reg chip1_bound { - desc = "Exclusive bound address for chip-select 1 decoding."; - field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; + desc = "Exclusive 4 MiB-aligned address for chip-select 1 decoding."; + field { sw = rw; hw = r; reset = 10'd2; } value[31:22]; }; reg chip2_base { - desc = "Inclusive base address for chip-select 2 decoding."; - field { sw = rw; hw = r; reset = 32'h0002_0000; } value[31:0]; + desc = "Inclusive 4 MiB-aligned address for chip-select 2 decoding."; + field { sw = rw; hw = r; reset = 10'd2; } value[31:22]; }; reg chip2_bound { - desc = "Exclusive bound address for chip-select 2 decoding."; - field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; + desc = "Exclusive 4 MiB-aligned address for chip-select 2 decoding."; + field { sw = rw; hw = r; reset = 10'd3; } value[31:22]; }; reg chip3_base { - desc = "Inclusive base address for chip-select 3 decoding."; - field { sw = rw; hw = r; reset = 32'h0003_0000; } value[31:0]; + desc = "Inclusive 4 MiB-aligned address for chip-select 3 decoding."; + field { sw = rw; hw = r; reset = 10'd3; } value[31:22]; }; reg chip3_bound { - desc = "Exclusive bound address for chip-select 3 decoding."; - field { sw = rw; hw = r; reset = 32'h0004_0000; } value[31:0]; + desc = "Exclusive 4 MiB-aligned address for chip-select 3 decoding."; + field { sw = rw; hw = r; reset = 10'd4; } value[31:22]; + }; + + reg chip4_base { + desc = "Inclusive 4 MiB-aligned address for chip-select 4 decoding."; + field { sw = rw; hw = r; reset = 10'd4; } value[31:22]; + }; + + reg chip4_bound { + desc = "Exclusive 4 MiB-aligned address for chip-select 4 decoding."; + field { sw = rw; hw = r; reset = 10'd5; } value[31:22]; + }; + + reg chip5_base { + desc = "Inclusive 4 MiB-aligned address for chip-select 5 decoding."; + field { sw = rw; hw = r; reset = 10'd5; } value[31:22]; + }; + + reg chip5_bound { + desc = "Exclusive 4 MiB-aligned address for chip-select 5 decoding."; + field { sw = rw; hw = r; reset = 10'd6; } value[31:22]; + }; + + reg chip6_base { + desc = "Inclusive 4 MiB-aligned address for chip-select 6 decoding."; + field { sw = rw; hw = r; reset = 10'd6; } value[31:22]; + }; + + reg chip6_bound { + desc = "Exclusive 4 MiB-aligned address for chip-select 6 decoding."; + field { sw = rw; hw = r; reset = 10'd7; } value[31:22]; + }; + + reg chip7_base { + desc = "Inclusive 4 MiB-aligned address for chip-select 7 decoding."; + field { sw = rw; hw = r; reset = 10'd7; } value[31:22]; + }; + + reg chip7_bound { + desc = "Exclusive 4 MiB-aligned address for chip-select 7 decoding."; + field { sw = rw; hw = r; reset = 10'd8; } value[31:22]; }; t_latency_access t_latency_access @ 0x00; @@ -119,4 +183,12 @@ addrmap hyperbus_cfg_regs { chip2_bound chip2_bound @ 0x44; chip3_base chip3_base @ 0x48; chip3_bound chip3_bound @ 0x4c; + chip4_base chip4_base @ 0x58; + chip4_bound chip4_bound @ 0x5c; + chip5_base chip5_base @ 0x60; + chip5_bound chip5_bound @ 0x64; + chip6_base chip6_base @ 0x68; + chip6_bound chip6_bound @ 0x6c; + chip7_base chip7_base @ 0x70; + chip7_bound chip7_bound @ 0x74; }; From 445b99ac86fe51565793dff59d495e2e3ebcae45 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Tue, 21 Jul 2026 14:54:45 +0200 Subject: [PATCH 5/5] Simplify and test config register wrapper --- Bender.yml | 1 + scripts/start.tcl | 42 +++++++-- src/hyperbus_cfg_regs.sv | 56 ++++++++---- src/hyperbus_pkg.sv | 40 --------- test/hyperbus_cfg_regs_tb.sv | 165 +++++++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+), 62 deletions(-) create mode 100644 test/hyperbus_cfg_regs_tb.sv diff --git a/Bender.yml b/Bender.yml index 04062ce..b3bc15e 100644 --- a/Bender.yml +++ b/Bender.yml @@ -65,4 +65,5 @@ sources: - test/dut_if.sv - test/hyperbus_tb_pkg.sv - test/axi_hyper_tb.sv + - test/hyperbus_cfg_regs_tb.sv - src/hyperbus.sv diff --git a/scripts/start.tcl b/scripts/start.tcl index 0488812..f4408ad 100644 --- a/scripts/start.tcl +++ b/scripts/start.tcl @@ -2,12 +2,42 @@ # Solderpad Hardware License, Version 0.51, see LICENSE for details. # SPDX-License-Identifier: SHL-0.51 -vsim axi_hyper_tb -t 1ps -voptargs=+acc -classdebug +set regression_failed 0 -set StdArithNoWarnings 1 -set NumericStdNoWarnings 1 -log -r /* +proc run_test {top_name wlf_name} { + global regression_failed -delete wave * + puts "==============================" + puts "= Running $top_name" + puts "==============================" -run -all + set transcript_name "[file rootname $wlf_name].log" + file delete -force $transcript_name + transcript file $transcript_name + + vsim $top_name -wlf $wlf_name -t 1ps -voptargs=+acc -classdebug + + onfinish stop + set StdArithNoWarnings 1 + set NumericStdNoWarnings 1 + log -r /* + + catch {delete wave *} + + run -all + quit -sim + + transcript file {} + set transcript_fd [open $transcript_name r] + set transcript_data [read $transcript_fd] + close $transcript_fd + if {[regexp -line {^# \*\* (Error|Fatal)( \([^)]*\))?:} $transcript_data]} { + puts "Regression errors detected in $transcript_name" + set regression_failed 1 + } +} + +run_test axi_hyper_tb sim_run_axi.wlf +run_test hyperbus_cfg_regs_tb sim_run_cfg_regs.wlf + +quit -code $regression_failed -f diff --git a/src/hyperbus_cfg_regs.sv b/src/hyperbus_cfg_regs.sv index 84e792f..6c6ebd1 100644 --- a/src/hyperbus_cfg_regs.sv +++ b/src/hyperbus_cfg_regs.sv @@ -4,6 +4,8 @@ // // Paul Scheffler +`include "common_cells/assertions.svh" + module hyperbus_cfg_regs #( parameter int unsigned NumChips = -1, parameter int unsigned NumPhys = -1, @@ -12,8 +14,8 @@ module hyperbus_cfg_regs #( parameter type reg_rsp_t = logic, parameter type rule_t = logic ) ( - input logic clk_i, - input logic rst_ni, + input logic clk_i, + input logic rst_ni, input reg_req_t reg_req_i, output reg_rsp_t reg_rsp_o, @@ -30,8 +32,11 @@ module hyperbus_cfg_regs #( localparam int unsigned RegsBits = cf_math_pkg::idx_width(NumRegs); localparam int unsigned RegStrbWidth = RegDataWidth/8; + `ASSERT_INIT(NumChipsValid, NumChips >= 1 && NumChips <= NumChipsMax) + `ASSERT_INIT(NumPhysValid, NumPhys == 1 || NumPhys == 2) + `ASSERT_INIT(RegDataWidthValid, RegDataWidth == 32) + typedef logic [RegsBits-1:0] reg_idx_t; - typedef logic [RegDataWidth-1:0] reg_data_t; typedef logic [6:0] cfg_addr_t; typedef logic [31:0] cfg_data_t; typedef logic [3:0] cfg_strb_t; @@ -94,7 +99,7 @@ module hyperbus_cfg_regs #( assign cfg_reg_req.wdata = 32'(reg_req_i.wdata); assign cfg_reg_req.wstrb = cfg_strb_t'(reg_req_i.wstrb); - always_comb begin + always_comb begin : proc_cfg_access cfg_access_active_d = cfg_access_active_q; if (!cfg_access_active_q && cfg_reg_req.valid) begin cfg_access_active_d = 1'b1; @@ -106,7 +111,7 @@ module hyperbus_cfg_regs #( `FFARN(cfg_access_active_q, cfg_access_active_d, 1'b0, clk_i, rst_ni); - always_comb begin + always_comb begin : proc_chip_rules chip_rules_all = '0; for (int unsigned i = 0; i < NumChipsMax; i++) begin chip_rules_all[i].idx = unsigned'(i); @@ -194,8 +199,36 @@ module hyperbus_cfg_regs #( .hwif_out ( cfg_hwif_out ) ); - assign frontend_cfg_o = hyperbus_pkg::hwif_to_frontend_cfg(cfg_hwif_out, NumPhys == 1); - assign phy_cfg_o = hyperbus_pkg::hwif_to_phy_cfg(cfg_hwif_out, NumPhys == 1); + always_comb begin : proc_cfg_output + frontend_cfg_o = '0; + phy_cfg_o = '0; + + frontend_cfg_o.address_mask_msb = cfg_hwif_out.address_mask_msb.value.value; + frontend_cfg_o.address_space = cfg_hwif_out.address_space.value.value; + frontend_cfg_o.phys_in_use = (NumPhys == 2) && + cfg_hwif_out.phys_in_use.value.value; + frontend_cfg_o.which_phy = (NumPhys == 2) && + cfg_hwif_out.which_phy.value.value; + + phy_cfg_o.chip.t_latency_access = cfg_hwif_out.t_latency_access.value.value; + phy_cfg_o.chip.en_latency_additional = cfg_hwif_out.en_latency_additional.value.value; + phy_cfg_o.chip.t_burst_max = cfg_hwif_out.t_burst_max.value.value; + phy_cfg_o.chip.t_read_write_recovery = cfg_hwif_out.t_read_write_recovery.value.value; + phy_cfg_o.chip.t_rx_clk_delay = { + cfg_hwif_out.t_rx_clk_delay.coarse.value, + cfg_hwif_out.t_rx_clk_delay.fine.value + }; + phy_cfg_o.chip.t_csh_cycles = cfg_hwif_out.t_csh_cycles.value.value; + phy_cfg_o.chip.csn_to_ck_cycles = cfg_hwif_out.csn_to_ck_cycles.value.value; + phy_cfg_o.t_tx_clk_delay = { + cfg_hwif_out.t_tx_clk_delay.coarse.value, + cfg_hwif_out.t_tx_clk_delay.fine.value + }; + phy_cfg_o.phys_in_use = (NumPhys == 2) && + cfg_hwif_out.phys_in_use.value.value; + phy_cfg_o.which_phy = (NumPhys == 2) && + cfg_hwif_out.which_phy.value.value; + end for (genvar i = 0; unsigned'(i) < NumChipsMax; i++) begin : gen_chip_rules if (i < NumChips) begin : gen_active @@ -206,13 +239,4 @@ module hyperbus_cfg_regs #( end end - // pragma translate_off - `ifndef VERILATOR - initial assert (RegDataWidth == 32) - else $error("Generated HyperBus config registers require 32-bit RegDataWidth."); - initial assert (NumChips <= NumChipsMax) - else $error("Generated HyperBus config registers support up to eight chips."); - `endif - // pragma translate_on - endmodule : hyperbus_cfg_regs diff --git a/src/hyperbus_pkg.sv b/src/hyperbus_pkg.sv index 1fa6219..49149ef 100644 --- a/src/hyperbus_pkg.sv +++ b/src/hyperbus_pkg.sv @@ -33,46 +33,6 @@ package hyperbus_pkg; logic which_phy; } phy_cfg_t; - function automatic frontend_cfg_t hwif_to_frontend_cfg( - input hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t hwif, - input logic num_phys_one - ); - frontend_cfg_t cfg; - - cfg.address_mask_msb = hwif.address_mask_msb.value.value; - cfg.address_space = hwif.address_space.value.value; - cfg.phys_in_use = num_phys_one ? 1'b0 : hwif.phys_in_use.value.value; - cfg.which_phy = num_phys_one ? 1'b0 : hwif.which_phy.value.value; - - return cfg; - endfunction - - function automatic phy_cfg_t hwif_to_phy_cfg( - input hyperbus_cfg_regblock_pkg::hyperbus_cfg_regs__out_t hwif, - input logic num_phys_one - ); - phy_cfg_t cfg; - - cfg.chip.t_latency_access = hwif.t_latency_access.value.value; - cfg.chip.en_latency_additional = hwif.en_latency_additional.value.value; - cfg.chip.t_burst_max = hwif.t_burst_max.value.value; - cfg.chip.t_read_write_recovery = hwif.t_read_write_recovery.value.value; - cfg.chip.t_rx_clk_delay = { - hwif.t_rx_clk_delay.coarse.value, - hwif.t_rx_clk_delay.fine.value - }; - cfg.chip.t_csh_cycles = hwif.t_csh_cycles.value.value; - cfg.chip.csn_to_ck_cycles = hwif.csn_to_ck_cycles.value.value; - cfg.t_tx_clk_delay = { - hwif.t_tx_clk_delay.coarse.value, - hwif.t_tx_clk_delay.fine.value - }; - cfg.phys_in_use = num_phys_one ? 1'b0 : hwif.phys_in_use.value.value; - cfg.which_phy = num_phys_one ? 1'b0 : hwif.which_phy.value.value; - - return cfg; - endfunction - typedef struct packed { logic write; // transaction is a write hyper_blen_t burst; diff --git a/test/hyperbus_cfg_regs_tb.sv b/test/hyperbus_cfg_regs_tb.sv new file mode 100644 index 0000000..2209dcb --- /dev/null +++ b/test/hyperbus_cfg_regs_tb.sv @@ -0,0 +1,165 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +module hyperbus_cfg_regs_tb; + + localparam int unsigned NumChips = 8; + + typedef struct packed { + logic [7:0] addr; + logic write; + logic [31:0] wdata; + logic [3:0] wstrb; + logic valid; + } reg_req_t; + + typedef struct packed { + logic [31:0] rdata; + logic error; + logic ready; + } reg_rsp_t; + + typedef struct packed { + logic [31:0] start_addr; + logic [31:0] end_addr; + logic [2:0] idx; + } rule_t; + + logic clk; + logic rst_n; + reg_req_t reg_req; + reg_rsp_t reg_rsp; + hyperbus_pkg::frontend_cfg_t frontend_cfg; + hyperbus_pkg::phy_cfg_t phy_cfg; + rule_t [NumChips-1:0] chip_rules; + logic trans_active; + + task automatic reg_write( + input logic [7:0] addr, + input logic [31:0] data + ); + @(negedge clk); + reg_req.addr = addr; + reg_req.write = 1'b1; + reg_req.wdata = data; + reg_req.wstrb = '1; + reg_req.valid = 1'b1; + + do begin + @(posedge clk); + end while (!reg_rsp.ready); + if (reg_rsp.error) begin + $error("Register write to 0x%0h failed", addr); + end + + @(negedge clk); + reg_req.valid = 1'b0; + endtask + + task automatic reg_read( + input logic [7:0] addr, + output logic [31:0] data + ); + @(negedge clk); + reg_req.addr = addr; + reg_req.write = 1'b0; + reg_req.wdata = '0; + reg_req.wstrb = '0; + reg_req.valid = 1'b1; + + do begin + @(posedge clk); + end while (!reg_rsp.ready); + data = reg_rsp.rdata; + if (reg_rsp.error) begin + $error("Register read from 0x%0h failed", addr); + end + + @(negedge clk); + reg_req.valid = 1'b0; + endtask + + always #5ns clk = ~clk; + + hyperbus_cfg_regs #( + .NumChips ( NumChips ), + .NumPhys ( 2 ), + .RegDataWidth ( 32 ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ), + .rule_t ( rule_t ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .reg_req_i ( reg_req ), + .reg_rsp_o ( reg_rsp ), + .frontend_cfg_o ( frontend_cfg ), + .phy_cfg_o ( phy_cfg ), + .chip_rules_o ( chip_rules ), + .trans_active_i ( trans_active ) + ); + + initial begin : proc_stimulus + logic [31:0] chip_addr; + logic [31:0] rx_clk_delay; + logic [31:0] tx_clk_delay; + + clk = 1'b0; + rst_n = 1'b0; + reg_req = '0; + trans_active = 1'b0; + + repeat (4) @(posedge clk); + rst_n = 1'b1; + repeat (2) @(posedge clk); + + for (int unsigned i = 0; i < NumChips; i++) begin + if ((chip_rules[i].start_addr != i * 32'h0040_0000) || + (chip_rules[i].end_addr != (i + 1) * 32'h0040_0000)) begin + $error("Unexpected reset address range for chip %0d", i); + end + end + + // Exercise both the fine [4:0] and coarse [7:5] delay settings. + reg_write(8'h10, 8'hb5); + reg_write(8'h14, 8'h6a); + reg_read(8'h10, rx_clk_delay); + reg_read(8'h14, tx_clk_delay); + if ((rx_clk_delay != 8'hb5) || (tx_clk_delay != 8'h6a) || + (phy_cfg.chip.t_rx_clk_delay != 8'hb5) || + (phy_cfg.t_tx_clk_delay != 8'h6a)) begin + $error("Delay-line configuration fields did not take effect"); + end + + // Low address bits are not stored and read back as zero. + reg_write(8'h70, 32'h8134_5678); + reg_read(8'h70, chip_addr); + if ((chip_addr != 32'h8100_0000) || + (chip_rules[7].start_addr != 32'h8100_0000)) begin + $error("Chip address alignment was not applied"); + end + + // A new configuration access must wait for an active transfer to finish. + trans_active = 1'b1; + @(negedge clk); + reg_req.addr = 8'h00; + reg_req.write = 1'b0; + reg_req.valid = 1'b1; + repeat (3) begin + @(posedge clk); + if (reg_rsp.ready) begin + $error("Configuration access completed during an active transfer"); + end + end + trans_active = 1'b0; + do begin + @(posedge clk); + end while (!reg_rsp.ready); + @(negedge clk); + reg_req.valid = 1'b0; + + $finish; + end + +endmodule