fpga: x400: Fix SPI trigger clock crossing
Original-commit: 5da42f3542ed555623c73c7ce487b9960849f209
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user