exp: real P&R of verified weight-reuse memory path + packed core (EXP-0063)
New hardware/v3/rtl/np_packed_weight_reuse_top.v: flat structural synthesis wrapper around the EXP-0062-verified module chain (real SDR SDRAM controller -> layer_prefetch_ctrl.v -> layer_weight_buffer.v -> weight_tile_gather.v -> neural_processor_packed.v). Real Vivado post-route: 8/240 DSP48E1 (unchanged, memory path uses zero DSPs), WNS -2.502ns @ 200MHz -> Fmax ~133.3MHz, only -1.2% vs the isolated single core (134.9MHz, EXP-0059). Real memory-path control logic adds negligible Fmax cost at this scale. Full writeup in hardware/v2/logs/experiments.log EXP-0063. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
// ============================================================
|
||||
// V3 -- synthesis top for the EXP-0062 verified weight-reuse memory
|
||||
// path + packed compute core, flat structural wiring (real modules,
|
||||
// real internal connections), for a real P&R resource/timing check.
|
||||
//
|
||||
// Control ports (pf_start/tile_req/operand_valid/...) are exposed
|
||||
// directly at the top level rather than internally sequenced -- the
|
||||
// closed-loop sequencing logic (what EXP-0062's testbench did
|
||||
// procedurally) is the still-not-built neural_director.v integration,
|
||||
// deliberately out of scope here. This module exists ONLY to let
|
||||
// Vivado see the REAL combined logic (SDRAM controller + prefetch +
|
||||
// weight buffer + tile gather + packed compute core) together for
|
||||
// utilization/timing purposes, matching EXP-0059's own single-core
|
||||
// out-of-context methodology.
|
||||
// ============================================================
|
||||
module np_packed_weight_reuse_top #(
|
||||
parameter DATA_WIDTH = 8,
|
||||
parameter P_IN = 8,
|
||||
parameter ACC_WIDTH = 32,
|
||||
parameter BURST_LEN = 8,
|
||||
parameter ROW_BITS = 13,
|
||||
parameter COL_BITS = 10,
|
||||
parameter BANK_BITS = 2,
|
||||
parameter ADDR_WIDTH = BANK_BITS + ROW_BITS + COL_BITS,
|
||||
parameter LAYER_BYTES = 128,
|
||||
parameter BUFADDRW = $clog2(LAYER_BYTES)
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
// ---- layer_prefetch_ctrl.v control ----
|
||||
input wire pf_start,
|
||||
input wire [ADDR_WIDTH-1:0] pf_layer_base,
|
||||
output wire pf_busy,
|
||||
output wire pf_done,
|
||||
|
||||
// ---- layer_weight_buffer.v control ----
|
||||
input wire consume_done,
|
||||
|
||||
// ---- weight_tile_gather.v control ----
|
||||
input wire tile_req,
|
||||
input wire [BUFADDRW-1:0] tile_base,
|
||||
output wire tile_valid,
|
||||
|
||||
// ---- neural_processor_packed.v job/operand control ----
|
||||
input wire job_valid,
|
||||
output wire job_ready,
|
||||
input wire [15:0] job_node_id_a,
|
||||
input wire [15:0] job_node_id_b,
|
||||
input wire signed [DATA_WIDTH-1:0] job_bias,
|
||||
input wire [1:0] job_activation,
|
||||
input wire operand_valid,
|
||||
output wire operand_ready,
|
||||
input wire signed [DATA_WIDTH*P_IN-1:0] input_data_a,
|
||||
input wire signed [DATA_WIDTH*P_IN-1:0] input_data_b,
|
||||
input wire tile_last,
|
||||
output wire result_valid,
|
||||
input wire result_ready,
|
||||
output wire signed [DATA_WIDTH-1:0] result_data_a,
|
||||
output wire signed [DATA_WIDTH-1:0] result_data_b,
|
||||
output wire [15:0] result_node_id_a,
|
||||
output wire [15:0] result_node_id_b,
|
||||
|
||||
// ---- real SDRAM pins ----
|
||||
output wire sdram_cke,
|
||||
output wire sdram_cs_n,
|
||||
output wire sdram_ras_n,
|
||||
output wire sdram_cas_n,
|
||||
output wire sdram_we_n,
|
||||
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
|
||||
);
|
||||
wire ctrl_req, ctrl_wr, ctrl_ready, ctrl_busy;
|
||||
wire [ADDR_WIDTH-1:0] ctrl_addr;
|
||||
wire [16*BURST_LEN-1:0] ctrl_wdata, ctrl_rdata;
|
||||
wire [2*BURST_LEN-1:0] ctrl_wmask;
|
||||
|
||||
sdram_controller #(
|
||||
.CLK_FREQ_MHZ(64), .BURST_LEN(BURST_LEN),
|
||||
.ROW_BITS(ROW_BITS), .COL_BITS(COL_BITS), .BANK_BITS(BANK_BITS)
|
||||
) u_ctrl (
|
||||
.clk(clk), .rst(rst),
|
||||
.req(ctrl_req), .wr(ctrl_wr), .addr(ctrl_addr),
|
||||
.wdata(ctrl_wdata), .wmask(ctrl_wmask),
|
||||
.rdata(ctrl_rdata), .ready(ctrl_ready), .busy(ctrl_busy),
|
||||
.sdram_cke(sdram_cke), .sdram_cs_n(sdram_cs_n), .sdram_ras_n(sdram_ras_n),
|
||||
.sdram_cas_n(sdram_cas_n), .sdram_we_n(sdram_we_n),
|
||||
.sdram_ba(sdram_ba), .sdram_a(sdram_a), .sdram_dq(sdram_dq), .sdram_dqm(sdram_dqm)
|
||||
);
|
||||
|
||||
wire pf_fill_we;
|
||||
wire [BUFADDRW-1:0] pf_fill_addr;
|
||||
wire [DATA_WIDTH-1:0] pf_fill_data;
|
||||
|
||||
layer_prefetch_ctrl #(
|
||||
.DATA_WIDTH(DATA_WIDTH), .LAYER_BYTES(LAYER_BYTES), .BURST_LEN(BURST_LEN), .ADDR_WIDTH(ADDR_WIDTH)
|
||||
) u_pf (
|
||||
.clk(clk), .rst(rst),
|
||||
.start(pf_start), .layer_base(pf_layer_base), .busy(pf_busy), .done(pf_done),
|
||||
.fill_we(pf_fill_we), .fill_addr(pf_fill_addr), .fill_data(pf_fill_data),
|
||||
.ctrl_req(ctrl_req), .ctrl_wr(ctrl_wr), .ctrl_addr(ctrl_addr),
|
||||
.ctrl_wdata(ctrl_wdata), .ctrl_wmask(ctrl_wmask),
|
||||
.ctrl_rdata(ctrl_rdata), .ctrl_ready(ctrl_ready), .ctrl_busy(ctrl_busy)
|
||||
);
|
||||
|
||||
wire [BUFADDRW-1:0] lwb_rd_addr;
|
||||
wire [DATA_WIDTH-1:0] lwb_rd_data;
|
||||
|
||||
layer_weight_buffer #(.DATA_WIDTH(DATA_WIDTH), .LAYER_DEPTH(LAYER_BYTES)) u_lwb (
|
||||
.clk(clk), .rst(rst),
|
||||
.fill_we(pf_fill_we), .fill_addr(pf_fill_addr), .fill_data(pf_fill_data), .fill_done(pf_done),
|
||||
.rd_addr(lwb_rd_addr), .rd_data(lwb_rd_data), .consume_done(consume_done),
|
||||
.active_sel(), .swapped()
|
||||
);
|
||||
|
||||
wire [DATA_WIDTH*P_IN-1:0] tile_data;
|
||||
|
||||
weight_tile_gather #(
|
||||
.DATA_WIDTH(DATA_WIDTH), .P_IN(P_IN), .BUFADDRW(BUFADDRW)
|
||||
) u_gather (
|
||||
.clk(clk), .rst(rst),
|
||||
.tile_req(tile_req), .tile_base(tile_base),
|
||||
.tile_valid(tile_valid), .tile_data(tile_data),
|
||||
.rd_addr(lwb_rd_addr), .rd_data(lwb_rd_data)
|
||||
);
|
||||
|
||||
wire [3:0] np_state;
|
||||
wire np_error;
|
||||
|
||||
neural_processor_packed #(
|
||||
.DATA_WIDTH(DATA_WIDTH), .P_IN(P_IN), .ACC_WIDTH(ACC_WIDTH)
|
||||
) u_np (
|
||||
.clk(clk), .rst(rst),
|
||||
.job_valid(job_valid), .job_ready(job_ready),
|
||||
.job_node_id_a(job_node_id_a), .job_node_id_b(job_node_id_b),
|
||||
.job_bias(job_bias), .job_activation(job_activation),
|
||||
.operand_valid(operand_valid), .operand_ready(operand_ready),
|
||||
.input_data_a(input_data_a), .input_data_b(input_data_b),
|
||||
.weight_data(tile_data), .tile_last(tile_last),
|
||||
.result_valid(result_valid), .result_ready(result_ready),
|
||||
.result_data_a(result_data_a), .result_data_b(result_data_b),
|
||||
.result_node_id_a(result_node_id_a), .result_node_id_b(result_node_id_b),
|
||||
.np_state(np_state), .np_error(np_error)
|
||||
);
|
||||
endmodule
|
||||
Reference in New Issue
Block a user