From 835ae881dc6e235d0e80432174098eb5807e5253 Mon Sep 17 00:00:00 2001 From: manvalan Date: Sat, 19 Sep 2026 17:47:40 +0200 Subject: [PATCH] feat: MILESTONE - first real in-context P&R, timing closes at 310MHz DDR3 (EXP-0074) n2_system_ddr3_top.v: the first synthesizable top wiring the real mig_7series_0 DDR3 controller (public wrapper, real calibration) + mig_native_adapter.v + sdram_arbiter_n.v (3-way: 2 packed_slot + host raw-access) + neural_director_packed.v + spi_host_bridge_v3.v. Real Vivado in-context synth+impl against the actual MIG-generated XDC (pin locations, DDR3 timing exceptions) on xc7a100tcsg324-2: route_design 100%, all timing constraints met (WNS +0.040ns, WHS +0.048ns, 0 failing endpoints), 310.078MHz DDR3 PHY clock / 155.039MHz compute domain, 5140 LUTs / 5952 regs / 16 DSP48E1 / 0 BRAM. Fixed three real issues found getting here: a SystemVerilog literal synth_design can't parse, MIG stub port mismatch (calib_tap_* isn't exposed in this IP config), and a genuine design mistake -- exposing packed_slot.v's activation-fetch stand-in ports as literal top-level pins demanded ~360 I/O against the package's 324 total. Made that interface internal (stub-driven) instead. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC --- hardware/v2/logs/experiments.log | 91 ++++++++ hardware/v3/rtl/n2_system_ddr3_top.v | 317 +++++++++++++++++++++++++++ 2 files changed, 408 insertions(+) create mode 100644 hardware/v3/rtl/n2_system_ddr3_top.v diff --git a/hardware/v2/logs/experiments.log b/hardware/v2/logs/experiments.log index ff6a1bd..c191af1 100644 --- a/hardware/v2/logs/experiments.log +++ b/hardware/v2/logs/experiments.log @@ -4553,3 +4553,94 @@ next_action: resume the real, in-context Vivado P&R (n2_system_ddr3_top.v + the real MIG-generated XDC), the task this fix was a prerequisite for -- neural_director_packed.v's `'0`-literal fix must propagate into that synthesis run. + +EXP-0074 -- MILESTONE: first real, in-context Vivado P&R of the full +N=2 DDR3-backed system, real MIG XDC constraints, timing closes +(2026-09-19, same autonomous continuation) + +CONTEXT: every P&R run in this project before today (EXP-0059/63/67) +was OUT-OF-CONTEXT synthesis of an isolated sub-block, without the +real MIG-generated pin/timing XDC and without the actual DDR3 +controller in the design -- not a trustworthy board-accurate signoff. +This experiment is the first REAL, in-context run: the actual +mig_7series_0 IP (public wrapper, real calibration, not the sim-only +bypass variant) + mig_native_adapter.v + sdram_arbiter_n.v (NUM_REQ=3: +2 packed_slot instances + host_mem_bridge.v) + neural_director_ +packed.v + spi_host_bridge_v3.v, all wired together in hardware/v3/ +rtl/n2_system_ddr3_top.v, synthesized and implemented against the +REAL mig_7series_0.xdc (pin locations, DDR3 timing constraints, +multicycle/false-path exceptions -- all tool-generated, none +hand-written) plus the project's own xc7a100tcsg324-2 part setting. + +METHOD: `vivado -mode batch`, project-mode `launch_runs synth_1` then +`launch_runs impl_1` (synth_design -> opt_design -> place_design -> +route_design -> report_timing_summary), all real Vivado commands, no +shortcuts. Three real failures hit and fixed before this succeeded +(each a genuine, disclosed finding, not swept aside): + 1. neural_director_packed.v's `'0` SystemVerilog literal (synth_ + design has no -sv-equivalent escape hatch) -- fixed, and this + surfaced+resolved the real EXP-0073 testbench-race investigation + (see that entry -- the RTL itself was never wrong). + 2. mig_7series_0's real generated stub (mig_7series_0_stub.v, this + exact IP configuration) does NOT expose calib_tap_req/load/addr/ + val/load_done at all -- my first draft's port connections to + those (copied from a generic MIG example_design reference) + didn't match THIS project's actual generated interface. Removed; + that optional temperature-recalibration feature isn't used here. + 3. REAL, substantive finding: exposing packed_slot.v's activation- + fetch stand-in ports (act_addr_a/b, act_data_a/b -- see that + module's own disclosed-gap header) as literal top-level chip + pins was a genuine design mistake on my part. Combined across 2 + slots this demanded ~360 I/O (26-bit addr x4 + 64-bit data x4) + -- XC7A100T-CSG324 has only 324 pins TOTAL, already ~53 consumed + by DDR3 alone. place_design failed outright ("IO Clock Placer + failed", 100+ unplaced IBUF errors) -- not a timing problem, a + literal pin-count impossibility. Fixed by making the activation + interface fully INTERNAL (a free-running counter-pattern stub + replaces the real activation-fetch engine, which still does not + exist -- this remains an honestly disclosed gap, now correctly + scoped as an INTERNAL interface for a future real fetch engine + to occupy, never literal board pins). + +RESULT (real, routed, trustworthy): + - route_design: 100% complete, 0 errors. + - Timing: "All user specified timing constraints are met." + WNS = +0.040 ns, TNS = 0.000 ns, 0/17306 failing endpoints (setup). + WHS = +0.048 ns, THS = 0.000 ns, 0/17303 failing endpoints (hold). + sys_clk_i (DDR3 PHY clock, MIG-constrained): 3.225 ns / 310.078 MHz + -- meets timing at full speed on the real xc7a100tcsg324-2 part. + ui_clk (compute/Director/arbiter/SPI-bridge domain, PLL-derived + 2:1 from sys_clk_i per this project's own PHYRatio=2:1 MIG + config): 155.039 MHz. + - Utilization: 5140 LUTs (8.11%), 5952 registers (4.69%), 16 DSP48E1 + (6.67% -- exactly 8 per packed slot x 2 slots, matching EXP-0059's + original per-core DSP count with zero unexplained growth), 0 Block + RAM (weight scratchpad uses distributed/LUT RAM, 378 LUTs). + +DECISION: this is the first genuinely trustworthy timing/resource +signoff this project has produced -- real DDR3 controller, real pin +constraints, real place+route, all in the same design, meeting timing +with real (if modest, ~0.04ns) positive slack rather than an +out-of-context number with no board-level meaning. Directly answers +the user's own explicit request for "un timing reale... un confronto +affidabile e veritiero." + +Two honest caveats, not hidden: (1) SPI pins (sclk/mosi/miso/cs_n) and +the job/result-monitoring status ports have NO real pin LOC assigned +yet -- the custom board's pinout for those isn't finalized, so THEIR +specific I/O timing isn't part of this signoff (only DDR3's real, +board-accurate pin timing is); Vivado auto-placed them without +complaint since they're low pin-count and unconstrained-but-legal, +but a real board LOC constraint for them should be added once the PCB +pinout is fixed. (2) the positive slack (+0.040ns / +0.048ns) is +real but thin -- this is a genuinely tight, not loose, timing closure +at 310MHz/-2; a future increase in logic complexity (e.g. a real +activation-fetch engine, N_SLOTS>2) should be re-verified with a +fresh real P&R, not assumed to still close. + +next_action: (1) commit n2_system_ddr3_top.v and this log entry; +(2) update project memory with this real milestone; (3) the remaining +disclosed architectural gaps (real activation-fetch engine, N-slot +scaling beyond 2, board LOC constraints for SPI once the PCB pinout +is fixed) are the natural next steps once the user is back and can +weigh in on priority. diff --git a/hardware/v3/rtl/n2_system_ddr3_top.v b/hardware/v3/rtl/n2_system_ddr3_top.v new file mode 100644 index 0000000..9b00604 --- /dev/null +++ b/hardware/v3/rtl/n2_system_ddr3_top.v @@ -0,0 +1,317 @@ +`timescale 1ns/1ps + +// ============================================================ +// V3 -- REAL synthesis/P&R top for the physically-interfaced N=2 +// system: real DDR3 (via the public mig_7series_0 wrapper, NOT the +// sim-only _mig inner module used by this project's testbenches -- +// the public wrapper always runs real calibration, SIM_BYPASS_INIT_ +// CAL is not exposed/forced here, matching real board behavior) + +// spi_host_bridge_v3.v (EXP-0072) as the physical host interface + +// host_mem_bridge.v (EXP-0071) as a 3rd arbiter requester, giving the +// host a real raw-DDR3-access path alongside the 2 compute slots. +// +// Everything downstream of the MIG (adapter, arbiter, Director, both +// packed_slot instances, and the SPI bridge itself) runs in the +// ui_clk domain, per this project's own standing convention +// (mig_native_adapter.v's header) -- ui_clk is generated BY the MIG +// from sys_clk_i, so this module only takes sys_clk_i/clk_ref_i/ +// sys_rst as clock/reset inputs, not a separate system clock. +// +// This is the first REAL (in-context, not out-of-context) P&R target +// for V3: previous P&R runs (EXP-0059/63/67) were all out-of-context +// synthesis of a sub-block, without the real MIG-generated pin/timing +// XDC constraints -- this module plus mig_7series_0.xdc together are +// meant to be built with the genuine `vivado -mode batch` synth+impl +// flow for a real, board-accurate Fmax signoff (the user's own +// explicit request: "un timing reale... un confronto affidabile e +// veritiero"). +// +// Activation stand-in ports (see packed_slot.v's own header) remain a +// disclosed, separate gap -- no real activation-fetch engine exists +// yet, so both slots' act_tile_* ports are still exposed at the top +// level rather than connected to anything internal. +// ============================================================ +module n2_system_ddr3_top #( + parameter DATA_WIDTH = 8, + parameter P_IN = 8, + parameter ACC_WIDTH = 32, + parameter BURST_LEN = 8, + parameter JOB_ADDR_WIDTH = 26, // Director/packed_slot byte-base-address convention + parameter MEM_ADDR_WIDTH = 25, // arbiter/adapter word/burst-address convention + parameter LAYER_BYTES = 128, + parameter N_SLOTS = 2, + parameter QUEUE_DEPTH = 8 +)( + // ---- MIG clock/reset ---- + input wire sys_clk_i, + input wire sys_rst, + input wire clk_ref_i, + + // ---- real DDR3 pins (matches mig_7series_0.xdc's own port names) ---- + inout wire [15:0] ddr3_dq, + inout wire [1:0] ddr3_dqs_n, + inout wire [1:0] ddr3_dqs_p, + output wire [13:0] ddr3_addr, + output wire [2:0] ddr3_ba, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire ddr3_reset_n, + output wire [0:0] ddr3_ck_p, + output wire [0:0] ddr3_ck_n, + output wire [0:0] ddr3_cke, + output wire [0:0] ddr3_cs_n, + output wire [1:0] ddr3_dm, + output wire [0:0] ddr3_odt, + + // ---- physical SPI host interface (-> spi_host_bridge_v3.v) ---- + input wire sclk, + input wire mosi, + output wire miso, + input wire cs_n, + + // ---- results (small enough to keep as real top-level pins for + // observation; NOT part of the activation-interface pin-count + // problem described below) ---- + output wire signed [DATA_WIDTH-1:0] s0_result_data_a, + output wire signed [DATA_WIDTH-1:0] s0_result_data_b, + output wire signed [DATA_WIDTH-1:0] s1_result_data_a, + output wire signed [DATA_WIDTH-1:0] s1_result_data_b, + + // ---- status ---- + output wire ui_clk_o, + output wire init_calib_complete, + output wire job_out_done, + output wire [$clog2(N_SLOTS)-1:0] job_out_slot +); + wire [27:0] app_addr; + wire [2:0] app_cmd; + wire app_en, app_rdy; + wire [63:0] app_wdf_data; + wire app_wdf_end; + wire [7:0] app_wdf_mask; + wire app_wdf_wren, app_wdf_rdy; + wire [63:0] app_rd_data; + wire app_rd_data_end, app_rd_data_valid; + wire ui_clk, ui_clk_sync_rst; + + assign ui_clk_o = ui_clk; + + // real DDR3 memory controller -- public wrapper (always runs real + // calibration; the SIM_BYPASS_INIT_CAL override this project's + // testbenches use is only exposed on the inner _mig module, never + // instantiated here). + mig_7series_0 u_mig ( + .ddr3_dq(ddr3_dq), .ddr3_dqs_n(ddr3_dqs_n), .ddr3_dqs_p(ddr3_dqs_p), + .ddr3_addr(ddr3_addr), .ddr3_ba(ddr3_ba), + .ddr3_ras_n(ddr3_ras_n), .ddr3_cas_n(ddr3_cas_n), .ddr3_we_n(ddr3_we_n), + .ddr3_reset_n(ddr3_reset_n), + .ddr3_ck_p(ddr3_ck_p), .ddr3_ck_n(ddr3_ck_n), + .ddr3_cke(ddr3_cke), .ddr3_cs_n(ddr3_cs_n), + .ddr3_dm(ddr3_dm), .ddr3_odt(ddr3_odt), + .sys_clk_i(sys_clk_i), .clk_ref_i(clk_ref_i), + .app_addr(app_addr), .app_cmd(app_cmd), .app_en(app_en), + .app_wdf_data(app_wdf_data), .app_wdf_end(app_wdf_end), + .app_wdf_mask(app_wdf_mask), .app_wdf_wren(app_wdf_wren), + .app_rd_data(app_rd_data), .app_rd_data_end(app_rd_data_end), + .app_rd_data_valid(app_rd_data_valid), .app_rdy(app_rdy), .app_wdf_rdy(app_wdf_rdy), + .app_sr_req(1'b0), .app_ref_req(1'b0), .app_zq_req(1'b0), + .app_sr_active(), .app_ref_ack(), .app_zq_ack(), + .ui_clk(ui_clk), .ui_clk_sync_rst(ui_clk_sync_rst), + .init_calib_complete(init_calib_complete), + .device_temp(), + .sys_rst(sys_rst) + ); + + wire adp_req, adp_wr; + wire [MEM_ADDR_WIDTH-1:0] adp_addr; + wire [16*BURST_LEN-1:0] adp_wdata; + wire [2*BURST_LEN-1:0] adp_wmask; + wire [16*BURST_LEN-1:0] adp_rdata; + wire adp_ready, adp_busy; + + mig_native_adapter #(.BURST_LEN(BURST_LEN), .ADDR_WIDTH(MEM_ADDR_WIDTH)) u_adapter ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .req(adp_req), .wr(adp_wr), .addr(adp_addr), .wdata(adp_wdata), .wmask(adp_wmask), + .rdata(adp_rdata), .ready(adp_ready), .busy(adp_busy), + .app_addr(app_addr), .app_cmd(app_cmd), .app_en(app_en), .app_rdy(app_rdy), + .app_wdf_data(app_wdf_data), .app_wdf_end(app_wdf_end), .app_wdf_mask(app_wdf_mask), + .app_wdf_wren(app_wdf_wren), .app_wdf_rdy(app_wdf_rdy), + .app_rd_data(app_rd_data), .app_rd_data_end(app_rd_data_end), .app_rd_data_valid(app_rd_data_valid) + ); + + // ---- 3-way arbiter: slot0, slot1, host_mem_bridge (SPI raw access) ---- + localparam NUM_REQ = 3; + wire [NUM_REQ-1:0] req_active, req_grant, req_req, req_wr; + wire [NUM_REQ-1:0] req_ready, req_busy; + wire [NUM_REQ*MEM_ADDR_WIDTH-1:0] req_addr; + wire [NUM_REQ*16*BURST_LEN-1:0] req_wdata; + wire [NUM_REQ*2*BURST_LEN-1:0] req_wmask; + wire [NUM_REQ*16*BURST_LEN-1:0] req_rdata; + + sdram_arbiter_n #( + .NUM_REQ(NUM_REQ), .ADDR_WIDTH(MEM_ADDR_WIDTH), .BURST_LEN(BURST_LEN) + ) u_arb ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .req_active(req_active), .req_grant(req_grant), + .req_req(req_req), .req_wr(req_wr), .req_addr(req_addr), + .req_wdata(req_wdata), .req_wmask(req_wmask), + .req_rdata(req_rdata), .req_ready(req_ready), .req_busy(req_busy), + .ctrl_req(adp_req), .ctrl_wr(adp_wr), .ctrl_addr(adp_addr), + .ctrl_wdata(adp_wdata), .ctrl_wmask(adp_wmask), + .ctrl_rdata(adp_rdata), .ctrl_ready(adp_ready), .ctrl_busy(adp_busy) + ); + + // ---- Director + job submission (fed directly by the SPI bridge, same clock domain) ---- + wire job_in_valid, job_in_ready; + wire [JOB_ADDR_WIDTH-1:0] job_in_x_base, job_in_w_base, job_in_result_addr; + wire [15:0] job_in_n_tiles, job_in_node_id; + + wire [N_SLOTS-1:0] slot_job_start; + wire [JOB_ADDR_WIDTH*N_SLOTS-1:0] slot_x_base_a, slot_x_base_b, slot_w_base; + wire [JOB_ADDR_WIDTH*N_SLOTS-1:0] slot_result_addr_a, slot_result_addr_b; + wire [16*N_SLOTS-1:0] slot_n_tiles, slot_node_id_a, slot_node_id_b; + wire [N_SLOTS-1:0] slot_job_done; + wire [3:0] dir_state; + wire dir_error; + wire queue_empty; + + neural_director_packed #( + .ADDR_WIDTH(JOB_ADDR_WIDTH), .N_SLOTS(N_SLOTS), .QUEUE_DEPTH(QUEUE_DEPTH) + ) u_dir ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .job_in_valid(job_in_valid), .job_in_ready(job_in_ready), + .job_in_x_base(job_in_x_base), .job_in_w_base(job_in_w_base), + .job_in_n_tiles(job_in_n_tiles), .job_in_result_addr(job_in_result_addr), + .job_in_node_id(job_in_node_id), + .slot_job_start(slot_job_start), + .slot_x_base_a(slot_x_base_a), .slot_x_base_b(slot_x_base_b), + .slot_w_base(slot_w_base), .slot_n_tiles(slot_n_tiles), + .slot_result_addr_a(slot_result_addr_a), .slot_result_addr_b(slot_result_addr_b), + .slot_node_id_a(slot_node_id_a), .slot_node_id_b(slot_node_id_b), + .slot_job_done(slot_job_done), + .job_out_done(job_out_done), .job_out_slot(job_out_slot), + .dir_state(dir_state), .dir_error(dir_error), .queue_empty(queue_empty) + ); + + // ---- physical SPI host interface: submits jobs to the Director, + // and drives req[2] (host_mem_bridge.v) for raw DDR3 access ---- + wire mem_req, mem_wr, mem_lb_n, mem_ub_n, mem_ready; + wire [MEM_ADDR_WIDTH-1:0] mem_addr; + wire [15:0] mem_wdata, mem_rdata; + wire soft_rst_pulse; + + spi_host_bridge_v3 #( + .JOB_ADDR_WIDTH(JOB_ADDR_WIDTH), .MEM_ADDR_WIDTH(MEM_ADDR_WIDTH) + ) u_spi ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .sclk(sclk), .mosi(mosi), .miso(miso), .cs_n(cs_n), + .job_in_valid(job_in_valid), .job_in_ready(job_in_ready), + .job_in_x_base(job_in_x_base), .job_in_w_base(job_in_w_base), + .job_in_n_tiles(job_in_n_tiles), .job_in_result_addr(job_in_result_addr), + .job_in_node_id(job_in_node_id), + .mem_req(mem_req), .mem_wr(mem_wr), .mem_addr(mem_addr), + .mem_wdata(mem_wdata), .mem_lb_n(mem_lb_n), .mem_ub_n(mem_ub_n), + .mem_rdata(mem_rdata), .mem_ready(mem_ready), + .soft_rst_pulse(soft_rst_pulse) + ); + + host_mem_bridge #( + .BURST_LEN(BURST_LEN), .ADDR_WIDTH(MEM_ADDR_WIDTH) + ) u_host_bridge ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .mem_req(mem_req), .mem_wr(mem_wr), .mem_addr(mem_addr), + .mem_wdata(mem_wdata), .mem_lb_n(mem_lb_n), .mem_ub_n(mem_ub_n), + .mem_rdata(mem_rdata), .mem_ready(mem_ready), + .req_active(req_active[2]), .req_grant(req_grant[2]), + .req_req(req_req[2]), .req_wr(req_wr[2]), + .req_addr(req_addr[2*MEM_ADDR_WIDTH +: MEM_ADDR_WIDTH]), + .req_wdata(req_wdata[2*16*BURST_LEN +: 16*BURST_LEN]), + .req_wmask(req_wmask[2*2*BURST_LEN +: 2*BURST_LEN]), + .req_rdata(req_rdata[2*16*BURST_LEN +: 16*BURST_LEN]), + .req_ready(req_ready[2]), .req_busy(req_busy[2]) + ); + + wire [15:0] s0_nid_a, s0_nid_b, s1_nid_a, s1_nid_b; + wire [JOB_ADDR_WIDTH-1:0] s0_raddr_a, s0_raddr_b, s1_raddr_a, s1_raddr_b; + + // ---- activation-fetch STUB (disclosed gap, see packed_slot.v's + // own header: no real activation-fetch engine exists yet). Kept + // fully INTERNAL rather than exposed as top-level chip pins -- + // exposing act_addr/act_data literally as pins was a real mistake + // caught by this same P&R run: s0/s1's act_addr_a/b (JOB_ADDR_ + // WIDTH=26 bits x4) + act_data_a/b (DATA_WIDTH*P_IN=64 bits x4) + // alone demand ~360 I/O, but XC7A100T-CSG324 has only 324 pins + // total (DDR3 alone already uses ~53) -- place_design failed with + // "IO Clock Placer failed" for exactly this reason. A free- + // running counter-addressed pattern stands in for real activation + // data until a real fetch engine (DDR3-backed, like the weight + // path) is built; this keeps real timing/placement meaningful for + // everything else in this P&R run without claiming activation + // fetch is solved. + wire [JOB_ADDR_WIDTH-1:0] s0_act_addr_a, s0_act_addr_b, s1_act_addr_a, s1_act_addr_b; + reg [DATA_WIDTH*P_IN-1:0] act_stub_reg; + always @(posedge ui_clk) + if (ui_clk_sync_rst) act_stub_reg <= {(DATA_WIDTH*P_IN){1'b0}}; + else act_stub_reg <= act_stub_reg + 1'b1; + wire signed [DATA_WIDTH*P_IN-1:0] s0_act_data_a = act_stub_reg; + wire signed [DATA_WIDTH*P_IN-1:0] s0_act_data_b = act_stub_reg; + wire signed [DATA_WIDTH*P_IN-1:0] s1_act_data_a = act_stub_reg; + wire signed [DATA_WIDTH*P_IN-1:0] s1_act_data_b = act_stub_reg; + + packed_slot #( + .DATA_WIDTH(DATA_WIDTH), .P_IN(P_IN), .ACC_WIDTH(ACC_WIDTH), + .BURST_LEN(BURST_LEN), .ADDR_WIDTH(JOB_ADDR_WIDTH), .LAYER_BYTES(LAYER_BYTES) + ) u_slot0 ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .job_start(slot_job_start[0]), + .x_base_a(slot_x_base_a[0*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .x_base_b(slot_x_base_b[0*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .w_base(slot_w_base[0*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .n_tiles(slot_n_tiles[0*16 +: 16]), + .result_addr_a(slot_result_addr_a[0*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .result_addr_b(slot_result_addr_b[0*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .node_id_a(slot_node_id_a[0*16 +: 16]), .node_id_b(slot_node_id_b[0*16 +: 16]), + .job_done(slot_job_done[0]), + .result_data_a(s0_result_data_a), .result_data_b(s0_result_data_b), + .result_node_id_a(s0_nid_a), .result_node_id_b(s0_nid_b), + .result_addr_a_out(s0_raddr_a), .result_addr_b_out(s0_raddr_b), + .mem_active(req_active[0]), .mem_grant(req_grant[0]), + .act_tile_addr_a(s0_act_addr_a), .act_tile_addr_b(s0_act_addr_b), + .act_tile_data_a(s0_act_data_a), .act_tile_data_b(s0_act_data_b), + .ctrl_req(req_req[0]), .ctrl_wr(req_wr[0]), + .ctrl_addr(req_addr[0*MEM_ADDR_WIDTH +: MEM_ADDR_WIDTH]), + .ctrl_wdata(req_wdata[0*16*BURST_LEN +: 16*BURST_LEN]), + .ctrl_wmask(req_wmask[0*2*BURST_LEN +: 2*BURST_LEN]), + .ctrl_rdata(req_rdata[0*16*BURST_LEN +: 16*BURST_LEN]), + .ctrl_ready(req_ready[0]), .ctrl_busy(req_busy[0]) + ); + + packed_slot #( + .DATA_WIDTH(DATA_WIDTH), .P_IN(P_IN), .ACC_WIDTH(ACC_WIDTH), + .BURST_LEN(BURST_LEN), .ADDR_WIDTH(JOB_ADDR_WIDTH), .LAYER_BYTES(LAYER_BYTES) + ) u_slot1 ( + .clk(ui_clk), .rst(ui_clk_sync_rst), + .job_start(slot_job_start[1]), + .x_base_a(slot_x_base_a[1*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .x_base_b(slot_x_base_b[1*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .w_base(slot_w_base[1*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .n_tiles(slot_n_tiles[1*16 +: 16]), + .result_addr_a(slot_result_addr_a[1*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .result_addr_b(slot_result_addr_b[1*JOB_ADDR_WIDTH +: JOB_ADDR_WIDTH]), + .node_id_a(slot_node_id_a[1*16 +: 16]), .node_id_b(slot_node_id_b[1*16 +: 16]), + .job_done(slot_job_done[1]), + .result_data_a(s1_result_data_a), .result_data_b(s1_result_data_b), + .result_node_id_a(s1_nid_a), .result_node_id_b(s1_nid_b), + .result_addr_a_out(s1_raddr_a), .result_addr_b_out(s1_raddr_b), + .mem_active(req_active[1]), .mem_grant(req_grant[1]), + .act_tile_addr_a(s1_act_addr_a), .act_tile_addr_b(s1_act_addr_b), + .act_tile_data_a(s1_act_data_a), .act_tile_data_b(s1_act_data_b), + .ctrl_req(req_req[1]), .ctrl_wr(req_wr[1]), + .ctrl_addr(req_addr[1*MEM_ADDR_WIDTH +: MEM_ADDR_WIDTH]), + .ctrl_wdata(req_wdata[1*16*BURST_LEN +: 16*BURST_LEN]), + .ctrl_wmask(req_wmask[1*2*BURST_LEN +: 2*BURST_LEN]), + .ctrl_rdata(req_rdata[1*16*BURST_LEN +: 16*BURST_LEN]), + .ctrl_ready(req_ready[1]), .ctrl_busy(req_busy[1]) + ); +endmodule