-// © 2017 - 2021 Raptor Engineering, LLC
+// © 2017 - 2022 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
module spi_master_phy_quad(
input wire platform_clock,
input wire reset,
+ output wire ready,
input wire [31:0] tx_data,
output reg [31:0] rx_data,
input wire [7:0] dummy_cycle_count,
output reg spi_quad_mode_pin_enable
);
+ reg phy_ready = 0;
+
reg [3:0] transfer_state = 0;
reg [31:0] data_shift_out = 0;
reg [7:0] sspi_transfer_cycle_stop_value = 0;
reg [3:0] qspi_transfer_cycle_stop_value = 0;
+ assign ready = phy_ready;
+
always @(posedge platform_clock) begin
if (reset) begin
+ phy_ready <= 0;
transfer_state <= 0;
state_iteration <= 0;
transaction_complete <= 1;
spi_ss_n <= 1'b0;
transfer_state <= 1;
+ phy_ready <= 0;
end else begin
if (!hold_ss_active) begin
ss_state_at_idle <= 1'b1;
end
spi_quad_mode_pin_enable <= 0;
transfer_state <= 0;
+ phy_ready <= 1;
end
end
1: begin
parameter PHY_IO_TYPE_SINGLE = 0;
parameter PHY_IO_TYPE_QUAD = 2;
- // PHY clock generator
+ // PHY clock generator and reset synchronizer
// Divisor:
// (spi_clock_divisor - 1) * 2
// 0 == undefined (actually divide by two)
// 6 == divide by 10
// 7 == divide by 12
// etc.
+ reg phy_reset = 0;
wire spi_phy_clock;
reg spi_phy_clock_gen_reg = 0;
+ reg spi_phy_clock_gen_reg_prev = 0;
reg [7:0] spi_phy_clock_counter = 0;
assign spi_phy_clock = (spi_clock_divisor == 1)?peripheral_clock:spi_phy_clock_gen_reg;
always @(posedge peripheral_clock) begin
+ // Clock generator
if (spi_phy_clock_counter >= (spi_clock_divisor - 2)) begin
spi_phy_clock_gen_reg <= ~spi_phy_clock_gen_reg;
spi_phy_clock_counter <= 0;
end else begin
spi_phy_clock_counter <= spi_phy_clock_counter + 1;
end
+
+ // Reset synchronizer
+ if ((spi_phy_clock_gen_reg_prev == 0) && (spi_phy_clock_gen_reg == 1)) begin
+ phy_reset <= 0;
+ end else begin
+ if (peripheral_reset) begin
+ phy_reset <= 1;
+ end
+ end
+
+ spi_phy_clock_gen_reg_prev <= spi_phy_clock_gen_reg;
end
+ wire phy_ready;
reg [31:0] phy_tx_data = 0;
wire [31:0] phy_rx_data;
reg phy_hold_ss_active = 0;
spi_master_phy_quad spi_master_phy_quad(
.platform_clock(spi_phy_clock),
- .reset(peripheral_reset),
+ .reset(phy_reset),
+ .ready(phy_ready),
.tx_data(phy_tx_data),
.rx_data(phy_rx_data),
.dummy_cycle_count(phy_dummy_cycle_count),
reg [31:0] wishbone_dat_r_reg = 0;
assign wishbone_dat_r = wishbone_dat_r_reg;
- parameter SPI_MASTER_TRANSFER_STATE_IDLE = 0;
- parameter SPI_MASTER_TRANSFER_STATE_TR01 = 1;
- parameter SPI_MASTER_TRANSFER_STATE_TR02 = 2;
+ parameter SPI_MASTER_TRANSFER_STATE_PHYI = 0;
+ parameter SPI_MASTER_TRANSFER_STATE_IDLE = 1;
+ parameter SPI_MASTER_TRANSFER_STATE_TR01 = 2;
+ parameter SPI_MASTER_TRANSFER_STATE_TR02 = 3;
parameter SPI_MASTER_TRANSFER_STATE_TR03 = 16;
parameter SPI_MASTER_TRANSFER_STATE_TR04 = 17;
parameter SPI_MASTER_TRANSFER_STATE_TR05 = 18;
multicycle_write_in_progress <= 0;
multicycle_transaction_address <= 0;
spi_cs_active_counter <= 0;
- spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_PHYI;
end else begin
case (spi_transfer_state)
+ SPI_MASTER_TRANSFER_STATE_PHYI: begin
+ if (phy_ready && (!phy_reset)) begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end
+ end
SPI_MASTER_TRANSFER_STATE_IDLE: begin
// Compute effective address
spi_address_reg[31:2] = wishbone_adr;