ec82764bef
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression (272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps, and all dump-derived textures/traces) is excluded via .gitignore and stays local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
118 lines
4.8 KiB
Systemverilog
118 lines
4.8 KiB
Systemverilog
// ============================================================================
|
|
// gs_lpddr_rd_probe.sv (Ch319 Brick 3)
|
|
//
|
|
// HPS-triggered single-word AXI4 READ probe for FPGA-private LPDDR4B.
|
|
//
|
|
// Lets the HPS read framebuffer bytes back THROUGH THE HPS BRIDGE (never
|
|
// /dev/mem) for checksum + screen-dump. Drives the EMIF user port's READ
|
|
// channel (AR/R) only — the write channel (AW/W/B) is the GS tile-flush
|
|
// writer (gs_lpddr_axi_master); read and write channels are independent, so
|
|
// the two masters share the one EMIF port with no arbitration.
|
|
//
|
|
// Runs on axi_clk (= emif_clk, ~310 MHz). The control input `rd_pulse` is a
|
|
// TOGGLE in the bridge (design_clk) domain; it is 2-FF synced + edge-detected
|
|
// here. The outputs `rd_done` (toggle) + `rd_data` are produced in axi_clk;
|
|
// the bridge syncs `rd_done` and latches `rd_data` on its edge (same return-
|
|
// path CDC contract as ao486 ao486_hps_bridge ↔ lpddr4b_loader).
|
|
//
|
|
// One AXI read = one 32-byte (256-bit) beat; the requested 32-bit word is the
|
|
// lane selected by addr[4:2] (8 lanes per beat). araddr is 32-byte aligned.
|
|
// ============================================================================
|
|
|
|
module gs_lpddr_rd_probe #(
|
|
parameter ADDR_W = 30
|
|
)(
|
|
input logic axi_clk, // emif_clk
|
|
input logic axi_rst_n, // emif_reset_n (EMIF cal-ready)
|
|
|
|
// ---- control / status (rd_pulse is a design_clk-domain toggle) ----
|
|
input logic rd_pulse, // toggles when the HPS requests a read
|
|
input logic [31:0] rd_addr, // byte address (stable when rd_pulse toggles)
|
|
output logic rd_done, // toggles (axi_clk) on completion
|
|
output logic [31:0] rd_data, // 32-bit word (stable after rd_done edge)
|
|
output logic rd_busy,
|
|
|
|
// ---- AXI4 READ channel to the EMIF user port (axi_clk, 256-bit data) ----
|
|
output logic [ADDR_W-1:0] araddr,
|
|
output logic [1:0] arburst,
|
|
output logic [6:0] arid,
|
|
output logic [7:0] arlen,
|
|
output logic [2:0] arsize,
|
|
output logic arvalid,
|
|
input logic arready,
|
|
input logic [255:0] rdata,
|
|
input logic [1:0] rresp,
|
|
input logic rlast,
|
|
input logic rvalid,
|
|
output logic rready
|
|
);
|
|
// AXI read-address constants
|
|
assign arburst = 2'b01; // INCR
|
|
assign arid = 7'd1; // distinct from the writer (awid = 0)
|
|
assign arlen = 8'd0; // single beat
|
|
assign arsize = 3'b101; // 32 bytes (full 256-bit width)
|
|
|
|
// CDC: sync rd_pulse (design_clk) into axi_clk + edge-detect.
|
|
reg [2:0] pulse_sync;
|
|
wire pulse_edge = (pulse_sync[2] != pulse_sync[1]);
|
|
|
|
reg [2:0] rd_lane; // which 32-bit lane of the 256-bit beat (addr[4:2])
|
|
|
|
typedef enum logic [1:0] { S_IDLE, S_AR, S_R } st_t;
|
|
st_t st;
|
|
|
|
always_ff @(posedge axi_clk) begin
|
|
if (!axi_rst_n) begin
|
|
pulse_sync <= 3'd0;
|
|
st <= S_IDLE;
|
|
araddr <= '0;
|
|
arvalid <= 1'b0;
|
|
rready <= 1'b0;
|
|
rd_done <= 1'b0;
|
|
rd_data <= 32'd0;
|
|
rd_busy <= 1'b0;
|
|
rd_lane <= 3'd0;
|
|
end else begin
|
|
pulse_sync <= {pulse_sync[1:0], rd_pulse};
|
|
|
|
case (st)
|
|
S_IDLE: begin
|
|
if (pulse_edge) begin
|
|
rd_lane <= rd_addr[4:2];
|
|
araddr <= {rd_addr[ADDR_W-1:5], 5'd0}; // 32-byte aligned
|
|
arvalid <= 1'b1;
|
|
rd_busy <= 1'b1;
|
|
st <= S_AR;
|
|
end
|
|
end
|
|
S_AR: begin
|
|
if (arready) begin
|
|
arvalid <= 1'b0;
|
|
rready <= 1'b1;
|
|
st <= S_R;
|
|
end
|
|
end
|
|
S_R: begin
|
|
if (rvalid) begin
|
|
rready <= 1'b0;
|
|
case (rd_lane)
|
|
3'd0: rd_data <= rdata[31:0];
|
|
3'd1: rd_data <= rdata[63:32];
|
|
3'd2: rd_data <= rdata[95:64];
|
|
3'd3: rd_data <= rdata[127:96];
|
|
3'd4: rd_data <= rdata[159:128];
|
|
3'd5: rd_data <= rdata[191:160];
|
|
3'd6: rd_data <= rdata[223:192];
|
|
default: rd_data <= rdata[255:224];
|
|
endcase
|
|
rd_busy <= 1'b0;
|
|
rd_done <= ~rd_done;
|
|
st <= S_IDLE;
|
|
end
|
|
end
|
|
default: st <= S_IDLE;
|
|
endcase
|
|
end
|
|
end
|
|
endmodule
|