feat: SDRAM 8MB->64MB upgrade (AS4C32M16SB-7BIN) + N_SLOTS=8 support
Memory upgrade, at the user's own explicit request: Alliance Memory AS4C4M16SA-6TIN (64Mbit/8MB) -> AS4C32M16SB-7BIN (512Mbit/64MB, 54-ball TFBGA), the largest same-family SDR SDRAM Alliance Memory offers. Real-datasheet-driven (whole AS4C4M16SA/AS4C8M16SA/AS4C16M16SA/ AS4C32M16SA family investigated): 13 row bits (was 12, one new FPGA pin sdram_a[12]/ball F1), 10 column bits (was 8), real -7-grade AC timing (tRCD/tRP improved to 15ns, tREFI halved to 7.8us for the doubled row count). sdram_controller.v and sdram_model.v gained real ROW_BITS/COL_BITS/BANK_BITS parameters (was hardcoded 12/8/2). ADDR_WIDTH widened 23->26 bits across the live instantiation tree. This required a real SPI protocol change (spi_host_bridge.v): a 26-bit byte address no longer fits in 3 bytes -- every address field widened 3->4 bytes (WRITE_JOB 15->18 payload bytes, WRITE_MEM/READ_MEM header 5->6 bytes). Found and fixed two real timing regressions via nextpnr-ecp5 P&R (not assumed): neural_director.v's own runtime-indexed demux write (ERR-0027, was silently synthesizing an extra MULT18X18D) and nms_activation_fill_ctrl_v3.v's own linear N_SLOTS-wide max-scan (ERR-0028, became dominant at N_SLOTS=8) -- both replaced with constant-indexed/tree-based equivalents, bit-exact same behavior, confirmed via full D-Stress N=2/4/8 regression (identical cycle counts). N_SLOTS=4 now fully closes timing at 64MHz (8/8 seeds); N_SLOTS=8 significantly improved but not yet fully reliable (5/8 seeds) -- honestly disclosed, not claimed complete. Full regression re-verified: sdram_controller (461/461, 18 configs), tb_sdram_boundary (21/21), D-Stress N=2/4/8 (bit-exact), spi_host_bridge (18/18), board-level SPI smoke test (11/11), unified backend (40/40). See hardware/v2/docs/MEMORY_UPGRADE_64MB_N8.md for the full investigation, and errors.log/decisions.log (ERR-0027, ERR-0028, DEC-0039) for the complete root-cause writeups. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
This commit is contained in:
@@ -56,9 +56,17 @@
|
||||
// scope boundary -- not revisited here).
|
||||
// ============================================================
|
||||
module sdram_unified_backend #(
|
||||
parameter ADDR_WIDTH = 23, // byte address width (W port convention)
|
||||
parameter CLK_FREQ_MHZ = 80,
|
||||
parameter W_ENTRIES = 4 // weight-cache depth, >= real N_SLOTS
|
||||
parameter ADDR_WIDTH = 26, // byte address width (W port convention)
|
||||
parameter CLK_FREQ_MHZ = 64,
|
||||
parameter W_ENTRIES = 4, // weight-cache depth, >= real N_SLOTS
|
||||
// physical SDRAM geometry, forwarded directly to sdram_controller.v
|
||||
// (AS4C32M16SA defaults: 13 row bits/A0-A12, 10 col bits/A0-A9,
|
||||
// 2 bank bits/BA0-BA1) -- must satisfy ADDR_WIDTH-1 ==
|
||||
// BANK_BITS+ROW_BITS+COL_BITS (byte address = word address + 1 bit),
|
||||
// asserted at elaboration below.
|
||||
parameter ROW_BITS = 13,
|
||||
parameter COL_BITS = 10,
|
||||
parameter BANK_BITS = 2
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
@@ -91,12 +99,18 @@ module sdram_unified_backend #(
|
||||
output wire sdram_ras_n,
|
||||
output wire sdram_cas_n,
|
||||
output wire sdram_we_n,
|
||||
output wire [1:0] sdram_ba,
|
||||
output wire [11:0] sdram_a,
|
||||
output wire [BANK_BITS-1:0] sdram_ba,
|
||||
output wire [ROW_BITS-1:0] sdram_a,
|
||||
inout wire [15:0] sdram_dq,
|
||||
output wire [1:0] sdram_dqm
|
||||
);
|
||||
|
||||
initial if (ADDR_WIDTH != BANK_BITS + ROW_BITS + COL_BITS + 1) begin
|
||||
$display("FATAL sdram_unified_backend: ADDR_WIDTH(%0d) != BANK_BITS(%0d)+ROW_BITS(%0d)+COL_BITS(%0d)+1",
|
||||
ADDR_WIDTH, BANK_BITS, ROW_BITS, COL_BITS);
|
||||
$finish;
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// W-port cache (identical logic to sdram_weight_backend_pack128.v
|
||||
// -- an N_ENTRIES-deep, fully-associative "other half" cache,
|
||||
@@ -130,7 +144,7 @@ module sdram_unified_backend #(
|
||||
// ============================================================
|
||||
reg ctrl_req;
|
||||
reg ctrl_wr;
|
||||
reg [21:0] ctrl_addr;
|
||||
reg [ADDR_WIDTH-2:0] ctrl_addr;
|
||||
reg [127:0] ctrl_wdata;
|
||||
reg [15:0] ctrl_wmask;
|
||||
wire [127:0] ctrl_rdata;
|
||||
@@ -138,7 +152,8 @@ module sdram_unified_backend #(
|
||||
wire ctrl_busy;
|
||||
|
||||
sdram_controller #(
|
||||
.CLK_FREQ_MHZ(CLK_FREQ_MHZ), .BURST_LEN(8), .ADDR_WIDTH(22)
|
||||
.CLK_FREQ_MHZ(CLK_FREQ_MHZ), .BURST_LEN(8),
|
||||
.ROW_BITS(ROW_BITS), .COL_BITS(COL_BITS), .BANK_BITS(BANK_BITS)
|
||||
) u_sdram_ctrl (
|
||||
.clk(clk), .rst(rst),
|
||||
.req(ctrl_req), .wr(ctrl_wr), .addr(ctrl_addr),
|
||||
@@ -191,9 +206,9 @@ module sdram_unified_backend #(
|
||||
wire ar_eff_lbn = ar_req ? ar_lb_n : ar_req_lbn_lat;
|
||||
wire ar_eff_ubn = ar_req ? ar_ub_n : ar_req_ubn_lat;
|
||||
|
||||
wire [21:0] w_eff_aligned_word_addr = {w_eff_addr[ADDR_WIDTH-1:4], 3'b000};
|
||||
wire [ADDR_WIDTH-2:0] w_eff_aligned_word_addr = {w_eff_addr[ADDR_WIDTH-1:4], 3'b000};
|
||||
wire w_eff_addr_is_upper_half = w_eff_addr[3];
|
||||
wire [21:0] ar_eff_block_base = {ar_eff_addr[21:3], 3'b000};
|
||||
wire [ADDR_WIDTH-2:0] ar_eff_block_base = {ar_eff_addr[ADDR_WIDTH-2:3], 3'b000};
|
||||
wire [2:0] ar_eff_word_in_blk = ar_eff_addr[2:0];
|
||||
|
||||
integer ri;
|
||||
@@ -202,7 +217,7 @@ module sdram_unified_backend #(
|
||||
state <= S_IDLE;
|
||||
for (ri = 0; ri < W_ENTRIES; ri = ri + 1) w_cache_valid[ri] <= 1'b0;
|
||||
w_alloc_ptr <= {WEIDXW{1'b0}};
|
||||
ctrl_req <= 1'b0; ctrl_wr <= 1'b0; ctrl_addr <= 22'h0;
|
||||
ctrl_req <= 1'b0; ctrl_wr <= 1'b0; ctrl_addr <= {(ADDR_WIDTH-1){1'b0}};
|
||||
ctrl_wdata <= 128'h0; ctrl_wmask <= 16'hFFFF;
|
||||
w_ready <= 1'b0; w_rdata <= 64'h0;
|
||||
ar_ready <= 1'b0; ar_rdata <= 16'h0;
|
||||
|
||||
Reference in New Issue
Block a user