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>
186 lines
6.7 KiB
Systemverilog
186 lines
6.7 KiB
Systemverilog
// retroDE_ps2 — sif_dma_ee_ack_peer_stub
|
|
//
|
|
// Protocol combiner for the first reverse-direction (IOP→EE) combined
|
|
// control+data SIF milestone. Mirror of sif_dma_ack_peer_stub with
|
|
// polarity swapped to observe the IOP's doorbell from the EE side and
|
|
// respond back IOP-ward through the mailbox.
|
|
//
|
|
// Explicitly NOT an EE. This module has no code execution, no bus
|
|
// master, no capability beyond composing two existing SIF primitives.
|
|
// Kept under `rtl/sif/` with the other protocol scaffolding so it
|
|
// does not get misread as EE maturity progress.
|
|
//
|
|
// Contract refs:
|
|
// docs/contracts/sif.md
|
|
//
|
|
// Layering:
|
|
// sif_mailbox_stub — storage primitive
|
|
// sif_dma_ee_ram_bridge_stub — reverse-direction data-plane landing
|
|
// sif_dma_ee_ack_peer_stub — THIS module. Ties them together on
|
|
// the EE side.
|
|
//
|
|
// Protocol (one-shot, reverse direction):
|
|
// 1. IOP writes SMCOM = cmd (what the IOP wants to say)
|
|
// 2. IOP writes SMFLG = CMD_PENDING_BIT (doorbell IOP→EE)
|
|
// 3. IOP DMAC ch9 transfers bounded payload through the SIF egress
|
|
// bridge, which lands qwords in EE RAM. Bridge's last_seen_o rises
|
|
// on the final beat and stays high.
|
|
// 4. this peer observes (SMFLG & CMD_PENDING_BIT) AND payload_complete
|
|
// 5. peer reads SMCOM (captures the command)
|
|
// 6. peer writes MSCOM = cmd (echo back IOP-ward)
|
|
// 7. peer writes MSFLG = CMD_ACK_BIT (ack back IOP-ward)
|
|
// 8. terminal DONE (one-shot for this milestone)
|
|
//
|
|
// The peer does NOT clear SMFLG or MSFLG — lifecycle is the TB's
|
|
// responsibility, consistent with sif_mailbox_peer_stub's guardrail.
|
|
//
|
|
// Ordering guarantee: the load-bearing behaviour is that the peer will
|
|
// not advance to the ack write sequence unless BOTH the doorbell AND
|
|
// payload_complete are observed simultaneously. The milestone is about
|
|
// verifying that the ack is gated on data arriving, not just control.
|
|
//
|
|
// Ports connect to:
|
|
// obs_* → sif_mailbox_stub ee_rd_* (peer reads SMFLG, then SMCOM)
|
|
// resp_* → sif_mailbox_stub ee_wr_* (peer writes MSCOM, then MSFLG)
|
|
// payload_complete ← sif_dma_ee_ram_bridge_stub.last_seen_o
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
module sif_dma_ee_ack_peer_stub
|
|
#(
|
|
parameter logic [7:0] MSCOM_OFF = 8'h00,
|
|
parameter logic [7:0] SMCOM_OFF = 8'h10,
|
|
parameter logic [7:0] MSFLG_OFF = 8'h20,
|
|
parameter logic [7:0] SMFLG_OFF = 8'h30,
|
|
parameter logic [31:0] CMD_PENDING_BIT = 32'h0000_0001,
|
|
parameter logic [31:0] CMD_ACK_BIT = 32'h0000_0002
|
|
) (
|
|
input logic clk,
|
|
input logic rst_n,
|
|
|
|
// Mailbox observation (EE-side read port)
|
|
output logic obs_rd_en,
|
|
output logic [7:0] obs_rd_addr,
|
|
input logic [31:0] obs_rd_data,
|
|
input logic obs_rd_valid,
|
|
|
|
// Mailbox response (EE-side write port)
|
|
output logic resp_wr_en,
|
|
output logic [7:0] resp_wr_addr,
|
|
output logic [31:0] resp_wr_data,
|
|
|
|
// Payload completion indication from sif_dma_ee_ram_bridge_stub (level)
|
|
input logic payload_complete,
|
|
|
|
// Status
|
|
output logic done_o,
|
|
output logic [31:0] ack_count_o
|
|
);
|
|
|
|
typedef enum logic [2:0] {
|
|
S_POLL_REQ = 3'd0, // pulse rd_en for SMFLG
|
|
S_POLL_WAIT = 3'd1, // wait for rd_valid, gate on BOTH conditions
|
|
S_SMCOM_REQ = 3'd2, // pulse rd_en for SMCOM
|
|
S_SMCOM_WAIT = 3'd3, // wait for rd_valid, latch cmd
|
|
S_WRITE_MSCOM = 3'd4, // drive wr_en, addr=MSCOM, data=cmd
|
|
S_WRITE_MSFLG = 3'd5, // drive wr_en, addr=MSFLG, data=ACK
|
|
S_DONE = 3'd6 // terminal (one-shot for this milestone)
|
|
} state_e;
|
|
|
|
state_e state;
|
|
logic [31:0] latched_cmd;
|
|
|
|
// ------------------------------------------------------------------
|
|
// State machine — advance to SMCOM_REQ only when SMFLG pending is set
|
|
// AND payload_complete is observed simultaneously. This is the
|
|
// load-bearing guarantee of the whole combiner.
|
|
// ------------------------------------------------------------------
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (!rst_n) begin
|
|
state <= S_POLL_REQ;
|
|
latched_cmd <= 32'd0;
|
|
end else begin
|
|
unique case (state)
|
|
S_POLL_REQ: state <= S_POLL_WAIT;
|
|
|
|
S_POLL_WAIT: begin
|
|
if (obs_rd_valid) begin
|
|
if (((obs_rd_data & CMD_PENDING_BIT) != 32'd0) &&
|
|
payload_complete)
|
|
state <= S_SMCOM_REQ;
|
|
else
|
|
state <= S_POLL_REQ; // keep polling
|
|
end
|
|
end
|
|
|
|
S_SMCOM_REQ: state <= S_SMCOM_WAIT;
|
|
|
|
S_SMCOM_WAIT: begin
|
|
if (obs_rd_valid) begin
|
|
latched_cmd <= obs_rd_data;
|
|
state <= S_WRITE_MSCOM;
|
|
end
|
|
end
|
|
|
|
S_WRITE_MSCOM: state <= S_WRITE_MSFLG;
|
|
|
|
S_WRITE_MSFLG: state <= S_DONE;
|
|
|
|
S_DONE: state <= S_DONE;
|
|
|
|
default: state <= S_POLL_REQ;
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// ------------------------------------------------------------------
|
|
// Output drive (combinational, one-hot on state)
|
|
// ------------------------------------------------------------------
|
|
|
|
always_comb begin
|
|
obs_rd_en = 1'b0;
|
|
obs_rd_addr = 8'd0;
|
|
resp_wr_en = 1'b0;
|
|
resp_wr_addr = 8'd0;
|
|
resp_wr_data = 32'd0;
|
|
|
|
unique case (state)
|
|
S_POLL_REQ: begin
|
|
obs_rd_en = 1'b1;
|
|
obs_rd_addr = SMFLG_OFF;
|
|
end
|
|
S_SMCOM_REQ: begin
|
|
obs_rd_en = 1'b1;
|
|
obs_rd_addr = SMCOM_OFF;
|
|
end
|
|
S_WRITE_MSCOM: begin
|
|
resp_wr_en = 1'b1;
|
|
resp_wr_addr = MSCOM_OFF;
|
|
resp_wr_data = latched_cmd;
|
|
end
|
|
S_WRITE_MSFLG: begin
|
|
resp_wr_en = 1'b1;
|
|
resp_wr_addr = MSFLG_OFF;
|
|
resp_wr_data = CMD_ACK_BIT;
|
|
end
|
|
default: ;
|
|
endcase
|
|
end
|
|
|
|
// ------------------------------------------------------------------
|
|
// Ack bookkeeping
|
|
// ------------------------------------------------------------------
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (!rst_n) begin
|
|
ack_count_o <= 32'd0;
|
|
done_o <= 1'b0;
|
|
end else if (state == S_WRITE_MSFLG) begin
|
|
ack_count_o <= ack_count_o + 32'd1;
|
|
done_o <= 1'b1;
|
|
end
|
|
end
|
|
|
|
endmodule : sif_dma_ee_ack_peer_stub
|