fpga: x400: Fix SPI trigger clock crossing

Original-commit: 5da42f3542ed555623c73c7ce487b9960849f209
This commit is contained in:
Mark Eid
2023-07-31 17:35:44 -05:00
committed by Wade Fife
parent 88dd427a98
commit b4c2aa0a40
+37 -8
View File
@@ -369,19 +369,48 @@ module x4xx_gpio_spi #(
assign readback_stb_extended = readback_stb; assign readback_stb_extended = readback_stb;
`else // X410 `else // X410
// Register set_stb for use in 2x domain.
// We only trigger one cycle of set_stb_2x per state change. This way the latency
// is deterministic from the first change and aligned to the correct address,
// without the need to pipeline the signal.
// ┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
//clk : └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └───
// xxxxxx/ \/ \/ \xxxxxxxxxxxxxxxxxxxxxx
//state : xxxxxx\ ctrl /\ div /\ data /xxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxx/ \/ \/ \xxxxxxxxxx
//state_dlyd : xxxxxxxxxxxxxxxxxx\ ctrl /\ div /\ data /xxxxxxxxxx
// ┐ ┌───────────────────────────────────┐
//set_stb : └─────────────────┘ └─────────
// xxxxxxxxxxxxxxxxxx/ \/ \/ \xxxxxxxxxx
//set_addr : xxxxxxxxxxxxxxxxxx\ 0x1 /\ 0x0 /\ 0x2 /xxxxxxxxxx
// ──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐
//clk_2x : └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └
// xxxxxxxxxxxxxxxxxxxxxxxx/ \/ \/ \xxxx
//state_dlyd_2x: xxxxxxxxxxxxxxxxxxxxxxxx\ ctrl /\ div /\ data /xxxx
// ┌─────┐ ┌─────┐ ┌─────┐
//set_stb_2x : ────────────────────────┘ └─────┘ └─────┘ └─────────
// ┌─────┐
//trigger_spi : ──────────────────────────────────────────────────────┘ └───
//
reg set_stb_2x = 1'b0; reg set_stb_2x = 1'b0;
reg ctrlport_clk_phase = 1'b1; reg [2:0] state_dlyd, state_dlyd_2x = IDLE;
always @ (posedge ctrlport_clk) begin
if (ctrlport_rst) begin
state_dlyd <= IDLE;
end else begin
state_dlyd <= state;
end
end
always @ (posedge ctrlport_clk_2x) begin always @ (posedge ctrlport_clk_2x) begin
if (ctrlport_rst) begin if (ctrlport_rst) begin
ctrlport_clk_phase <= 1'b1; state_dlyd_2x <= IDLE;
set_stb_2x <= 1'b0; set_stb_2x <= 1'b0;
end else begin end else begin
// Assert strobe only during a single 2x cycle of the state_dlyd_2x <= state_dlyd;
// 1x pulse, when 1x clock is low. set_stb_2x <= set_stb && (state_dlyd_2x != state_dlyd);
set_stb_2x <= ctrlport_clk_phase & set_stb;
ctrlport_clk_phase <= ~ctrlport_clk_phase;
end end
end end