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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user