Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.bender
scripts/compile.tcl
models/s27ks0641
axi_log/
work/
transcript
modelsim.ini
vsim.wlf
models/s27ks0641
2 changes: 2 additions & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sources:
- src/hyperbus_phy2r.sv
- src/hyperbus_ddr_out.sv
- src/hyperbus_delay.sv
- src/hyperbus_rwds_sampler.sv
- src/hyperbus_trx.sv
- src/hyperbus_cfg_regs.sv
- src/hyperbus_phy.sv
Expand All @@ -47,5 +48,6 @@ sources:
- test/fixture_hyperbus.sv
- test/hyperbus_tb.sv
- test/dut_if.sv
- test/hyperbus_tb_pkg.sv
- test/axi_hyper_tb.sv
- src/hyperbus.sv
5 changes: 2 additions & 3 deletions src/hyperbus.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ module hyperbus #(
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 = 2,
parameter int unsigned TxFifoLogDepth = 2,
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 AxiLogDepth = 3,
parameter int unsigned SyncStages = 2
) (
input logic clk_phy_i,
Expand Down
4 changes: 2 additions & 2 deletions src/hyperbus_axi.sv
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ module hyperbus_axi #(
// ============================

axi_fifo #(
.Depth ( 4 ),
.Depth ( 8 ),
.FallThrough ( 1'b0 ),
.aw_chan_t ( axi_fifo_aw_chan_t ),
.w_chan_t ( axi_fifo_w_chan_t ),
Expand Down Expand Up @@ -420,7 +420,7 @@ module hyperbus_axi #(
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.T ( axi_w_chan_t ),
.DEPTH ( 8 )
.DEPTH ( 16 )
) wchan_stream_fifo (
.clk_i,
.rst_ni,
Expand Down
8 changes: 6 additions & 2 deletions src/hyperbus_cfg_regs.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ module hyperbus_cfg_regs #(
`include "common_cells/registers.svh"

// Internal Parameters
localparam int unsigned NumBaseRegs = 11;
localparam int unsigned NumBaseRegs = 13;
localparam int unsigned NumRegs = 2*NumChips + NumBaseRegs;
localparam int unsigned RegsBits = cf_math_pkg::idx_width(NumRegs);
localparam int unsigned RegStrbWidth = RegDataWidth/8; // TODO ASSERT: Must be power of two >= 16!!
localparam int unsigned RegStrbWidth = RegDataWidth/8;

// Data and index types
typedef logic [RegsBits-1:0] reg_idx_t;
Expand All @@ -59,6 +59,8 @@ module hyperbus_cfg_regs #(
if (sel_reg_mapped) begin
rfield = {
crange_q,
reg_data_t'(cfg_q.rwds_sample),
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),
Expand Down Expand Up @@ -99,6 +101,8 @@ module hyperbus_cfg_regs #(
'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);
'hc: cfg_d.rwds_sample = (~wmask & cfg_q.rwds_sample ) | (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);
Expand Down
107 changes: 74 additions & 33 deletions src/hyperbus_phy.sv
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ module hyperbus_phy import hyperbus_pkg::*; #(
logic trx_clk_ena;
logic trx_cs_ena;
logic trx_rwds_sample;
logic trx_rwds_sample_ena;
logic [15:0] trx_tx_data;
logic trx_tx_data_oe;
logic [1:0] trx_tx_rwds;
Expand All @@ -123,22 +122,23 @@ module hyperbus_phy import hyperbus_pkg::*; #(
.clk_i_90,
.rst_ni,
.test_mode_i,
.cs_i ( cs_q ),
.cs_ena_i ( trx_cs_ena ),
.rwds_sample_o ( trx_rwds_sample ),
.rwds_sample_ena_i ( trx_rwds_sample_ena ),
.tx_clk_delay_i ( cfg_i.t_tx_clk_delay ),
.tx_clk_ena_i ( trx_clk_ena ),
.tx_data_i ( trx_tx_data ),
.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_set_i ( trx_rx_clk_set ),
.rx_clk_reset_i ( trx_rx_clk_reset ),
.rx_data_o ( trx_rx_data ),
.rx_valid_o ( trx_rx_valid ),
.rx_ready_i ( trx_rx_ready ),
.cfg_edge_idx_i ( cfg_i.rwds_sample.cylce_idx ),
.cfg_edge_pol_i ( cfg_i.rwds_sample.polarity ),
.cs_i ( cs_q ),
.cs_ena_i ( trx_cs_ena ),
.rwds_sample_o ( trx_rwds_sample ),
.tx_clk_delay_i ( cfg_i.t_tx_clk_delay ),
.tx_clk_ena_i ( trx_clk_ena ),
.tx_data_i ( trx_tx_data ),
.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_set_i ( trx_rx_clk_set ),
.rx_clk_reset_i ( trx_rx_clk_reset ),
.rx_data_o ( trx_rx_data ),
.rx_valid_o ( trx_rx_valid ),
.rx_ready_i ( trx_rx_ready ),
.hyper_cs_no,
.hyper_ck_o,
.hyper_ck_no,
Expand Down Expand Up @@ -243,7 +243,6 @@ module hyperbus_phy import hyperbus_pkg::*; #(
trx_cs_ena = 1'b1;
trx_clk_ena = 1'b0;
trx_rx_clk_set = 1'b0;
trx_rwds_sample_ena = 1'b0;
// Default next state
state_d = state_q;
timer_d = timer_q - 1;
Expand All @@ -269,45 +268,87 @@ module hyperbus_phy import hyperbus_pkg::*; #(
if (trans_valid_i & ~b_pending_q & r_outstand_q == '0) begin
tf_d = trans_i;
cs_d = trans_cs_i;
// Send 3 CA words (t_CSS respected through clock delay)
timer_d = 2;
state_d = SendCA;
// Enable output driver (needs to be enabled one cycle
// earlier since tri-state enables of IO pads are quite
// slow compared to the data pins)

if(cfg_i.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;
end else begin
// max throughput when memory RWDS signal arrives early
state_d = SendCA;
// Send 3 CA words (t_CSS respected through clock delay)
timer_d = 2;
end

// Enable output driver (needs to be enabled at least
// one cycle earlier since tri-state enables of IO pads
// are quite slow compared to the data pins)
trx_tx_data_oe = 1'b1;
end
end
DelayCK: begin
trx_clk_ena = 1'b0;
if (ctl_timer_zero) begin
timer_d = 2; // Send 3 CA words
state_d = SendCA;
end
end
SendCA: begin
// Dataflow handled outside FSM
trx_clk_ena = 1'b1;
trx_tx_data_oe = 1'b1;
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;
state_d = Write;
end else begin
timer_d = TimerWidth'(cfg_i.t_latency_access) << ctl_add_latency;
timer_d = TimerWidth'(cfg_i.t_latency_access);
state_d = WaitLatAccess;
end
end
end
WaitLatAccess: begin
trx_clk_ena = 1'b1;
trx_tx_data_oe = 1'b1;
// Substract cycle for last CA and another for state delay
// ctl_add_latency may arrive at any time (adjustable RWDS sampling)
// If no additional latency required:
if (~ctl_add_latency) begin
// Substract cycle for last CA and another for state delay
if(ctl_timer_two) begin
timer_d = cfg_i.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).
if (tf_q.write) begin
state_d = Write;
trx_tx_data_oe = 1'b1;
// For zero latency writes, we must not drive the RWDS
// signal (see specs page 9). Depending on the latency
// mode we thus drive only the DQ signals or DQ + RWDS.
trx_tx_rwds_oe = ~ctl_write_zero_lat;
end else begin
state_d = Read;
trx_tx_data_oe = 1'b0;
trx_tx_rwds_oe = 1'b0;
end
end
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);
end
end
WaitAddLatAccess: begin
// Same as WaitLatAccess but without possibility
// of adding another latency count
trx_clk_ena = 1'b1;
trx_tx_data_oe = 1'b1;
if (ctl_timer_two) begin
timer_d = cfg_i.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).
if (tf_q.write) begin
state_d = Write;
trx_tx_data_oe = 1'b1;
// For zero latency writes, we must not drive the RWDS
// signal (see specs page 9). Depending on the latency
// mode we thus drive only the DQ signals or DQ + RWDS.
trx_tx_rwds_oe = ~ctl_write_zero_lat;
end else begin
state_d = Read;
Expand Down
Loading