From ccd47477004798aa8bbb4e3dd02138943a673a73 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Thu, 21 May 2026 23:15:58 +0200 Subject: [PATCH 1/3] 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/3] 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/3] 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; };