--- /dev/null
+// © 2017 - 2022 Raptor Engineering, LLC
+//
+// Released under the terms of the GNU LGPL v3
+// See the LICENSE file for full details
+
+// =============================================================================================
+// Memory Map:
+// =============================================================================================
+// Device ID string (8 bytes)
+// Device version (4 bytes)
+// Base clock frequency (4 bytes)
+// PHY configuration register 1 (4 bytes): {cs_extra_idle_cycles, 2'b0, qspi_write_quad_io_en, qspi_read_quad_io_en, fast_read_mode, four_byte_address_mode, phy_io_type, dummy_cycle_count, spi_clock_divisor}
+// Flash configuration register 1 (4 bytes): {4BA QSPI read command, 3BA QSPI read command, 4BA SPI read command, 3BA SPI read command}
+// Flash configuration register 2 (4 bytes): {4BA QSPI fast read command, 3BA QSPI fast read command, 4BA SPI fast read command, 3BA SPI fast read command}
+// Flash configuration register 3 (4 bytes): {4BA QSPI program command, 3BA QSPI program command, 4BA SPI program command, 3BA SPI program command}
+// Flash configuration register 4 (4 bytes): {spi_cs_active_hold_cycles}
+// Flash configuration register 5 (4 bytes): {30'b0, allow_multicycle_writes, allow_multicycle_reads}
+// Control register 1 (4 bytes): {31'b0, user_command_mode}
+// Data register 1 (4 bytes): {24'b0, user_command_mode_read_during_write}
+
+// Stop LiteX silently ignoring net naming / missing register errors
+`default_nettype none
+
+module tercel_core(
+ // Configuration registers
+ input wire [31:0] sys_clk_freq,
+
+ // Wishbone signals
+ input wire wishbone_cyc,
+ input wire wishbone_stb,
+ input wire wishbone_we,
+ input wire [29:0] wishbone_adr,
+ input wire [31:0] wishbone_dat_w,
+ output wire [31:0] wishbone_dat_r,
+ input wire [3:0] wishbone_sel,
+ output wire wishbone_ack,
+ output wire wishbone_err,
+
+ // Wishbone configuration port signals
+ input wire cfg_wishbone_cyc,
+ input wire cfg_wishbone_stb,
+ input wire cfg_wishbone_we,
+ input wire [29:0] cfg_wishbone_adr,
+ input wire [31:0] cfg_wishbone_dat_w,
+ output wire [31:0] cfg_wishbone_dat_r,
+ input wire [3:0] cfg_wishbone_sel,
+ output wire cfg_wishbone_ack,
+ output wire cfg_wishbone_err,
+
+ // SPI bus signals
+ output wire spi_clock,
+ output wire [3:0] spi_d_out,
+ output wire [3:0] spi_d_direction, // 0 == tristate (input), 1 == driven (output)
+ input wire [3:0] spi_d_in,
+ output wire spi_ss_n,
+
+ output wire [7:0] debug_port,
+
+ input wire peripheral_reset,
+ input wire peripheral_clock
+ );
+
+ // Control and status registers
+ wire [63:0] device_id;
+ wire [31:0] device_version;
+
+ // PHY configuration register 1
+ // Defaults to standard SPI mode, 3BA, non-extended read/write (qspi_[read|write]_quad_io_en = 0), cs_extra_idle_cycles = 0, dummy cycle cont = 10, clock divisor 16
+ reg [31:0] phy_cfg1 = 32'h00000a10;
+
+ // Defaults to compatibility with Micron N25Q/512MB and similar 3BA/4BA capable devices, with multicycle and write disabled
+ // Note that the N25Q does not support normal reads in QSPI mode, so we leave the QSPI normal read commands equal
+ // to the normal SPI commands for safety -- no corruption is possible if the device is latched into read mode...
+ reg [31:0] flash_cfg1 = 32'h13031303;
+ reg [31:0] flash_cfg2 = 32'heceb0c0b;
+ reg [31:0] flash_cfg3 = 32'h34321202;
+ reg [31:0] flash_cfg4 = 32'h00000000;
+ reg [31:0] flash_cfg5 = 32'h00000000;
+
+ // Defaults to read mode
+ reg [31:0] core_ctl1 = 32'h00000000;
+ wire [31:0] core_data1;
+
+ // Device identifier
+ assign device_id = 64'h7c5250545350494d;
+ assign device_version = 32'h00010000;
+
+ reg cfg_wishbone_ack_reg = 0;
+ reg [31:0] cfg_wishbone_dat_r_reg = 0;
+
+ assign cfg_wishbone_ack = cfg_wishbone_ack_reg;
+ assign cfg_wishbone_dat_r = cfg_wishbone_dat_r_reg;
+
+ parameter WB_CFG_TRANSFER_STATE_IDLE = 0;
+ parameter WB_CFG_TRANSFER_STATE_TR01 = 1;
+
+ reg [31:0] wishbone_config_buffer_address_reg = 0;
+ reg [7:0] wishbone_config_transfer_state = 0;
+ reg [31:0] wishbone_cfg_space_tx_buffer = 0;
+ reg [31:0] wishbone_cfg_space_rx_buffer = 0;
+
+ // Wishbone configuration space connector
+ always @(posedge peripheral_clock) begin
+ if (peripheral_reset) begin
+ // Reset Wishbone interface / control state machine
+ cfg_wishbone_ack_reg <= 0;
+
+ wishbone_config_transfer_state <= WB_CFG_TRANSFER_STATE_IDLE;
+ end else begin
+ case (wishbone_config_transfer_state)
+ WB_CFG_TRANSFER_STATE_IDLE: begin
+ // Compute effective address
+ wishbone_config_buffer_address_reg[31:2] = cfg_wishbone_adr;
+ case (cfg_wishbone_sel)
+ 4'b0001: wishbone_config_buffer_address_reg[1:0] = 0;
+ 4'b0010: wishbone_config_buffer_address_reg[1:0] = 1;
+ 4'b0100: wishbone_config_buffer_address_reg[1:0] = 2;
+ 4'b1000: wishbone_config_buffer_address_reg[1:0] = 3;
+ 4'b1111: wishbone_config_buffer_address_reg[1:0] = 0;
+ default: wishbone_config_buffer_address_reg[1:0] = 0;
+ endcase
+
+ if (cfg_wishbone_cyc && cfg_wishbone_stb) begin
+ // Configuration register space access
+ // Single clock pulse signals in deasserted state...process incoming request!
+ if (!cfg_wishbone_we) begin
+ // Read requested
+ case ({wishbone_config_buffer_address_reg[7:2], 2'b00})
+ 0: wishbone_cfg_space_tx_buffer = device_id[63:32];
+ 4: wishbone_cfg_space_tx_buffer = device_id[31:0];
+ 8: wishbone_cfg_space_tx_buffer = device_version;
+ 12: wishbone_cfg_space_tx_buffer = sys_clk_freq;
+ 16: wishbone_cfg_space_tx_buffer = phy_cfg1;
+ 20: wishbone_cfg_space_tx_buffer = flash_cfg1;
+ 24: wishbone_cfg_space_tx_buffer = flash_cfg2;
+ 28: wishbone_cfg_space_tx_buffer = flash_cfg3;
+ 32: wishbone_cfg_space_tx_buffer = flash_cfg4;
+ 36: wishbone_cfg_space_tx_buffer = flash_cfg5;
+ 40: wishbone_cfg_space_tx_buffer = core_ctl1;
+ 44: wishbone_cfg_space_tx_buffer = core_data1;
+ default: wishbone_cfg_space_tx_buffer = 0;
+ endcase
+
+ // Endian swap
+ cfg_wishbone_dat_r_reg[31:24] <= wishbone_cfg_space_tx_buffer[7:0];
+ cfg_wishbone_dat_r_reg[23:16] <= wishbone_cfg_space_tx_buffer[15:8];
+ cfg_wishbone_dat_r_reg[15:8] <= wishbone_cfg_space_tx_buffer[23:16];
+ cfg_wishbone_dat_r_reg[7:0] <= wishbone_cfg_space_tx_buffer[31:24];
+
+ // Signal transfer complete
+ cfg_wishbone_ack_reg <= 1;
+
+ wishbone_config_transfer_state <= WB_CFG_TRANSFER_STATE_TR01;
+ end else begin
+ // Write requested
+ case ({wishbone_config_buffer_address_reg[7:2], 2'b00})
+ // Device ID / version registers cannot be written, don't even try...
+ 16: wishbone_cfg_space_rx_buffer = phy_cfg1;
+ 20: wishbone_cfg_space_rx_buffer = flash_cfg1;
+ 24: wishbone_cfg_space_rx_buffer = flash_cfg2;
+ 28: wishbone_cfg_space_rx_buffer = flash_cfg3;
+ 32: wishbone_cfg_space_rx_buffer = flash_cfg4;
+ 36: wishbone_cfg_space_rx_buffer = flash_cfg5;
+ 40: wishbone_cfg_space_rx_buffer = core_ctl1;
+ // Status registers cannot be written, don't even try...
+ default: wishbone_cfg_space_rx_buffer = 0;
+ endcase
+
+ if (cfg_wishbone_sel[0]) begin
+ wishbone_cfg_space_rx_buffer[7:0] = cfg_wishbone_dat_w[31:24];
+ end
+ if (cfg_wishbone_sel[1]) begin
+ wishbone_cfg_space_rx_buffer[15:8] = cfg_wishbone_dat_w[23:16];
+ end
+ if (cfg_wishbone_sel[2]) begin
+ wishbone_cfg_space_rx_buffer[23:16] = cfg_wishbone_dat_w[15:8];
+ end
+ if (cfg_wishbone_sel[3]) begin
+ wishbone_cfg_space_rx_buffer[31:24] = cfg_wishbone_dat_w[7:0];
+ end
+
+ case ({wishbone_config_buffer_address_reg[7:2], 2'b00})
+ 16: phy_cfg1 <= wishbone_cfg_space_rx_buffer;
+ 20: flash_cfg1 <= wishbone_cfg_space_rx_buffer;
+ 24: flash_cfg2 <= wishbone_cfg_space_rx_buffer;
+ 28: flash_cfg3 <= wishbone_cfg_space_rx_buffer;
+ 32: flash_cfg4 <= wishbone_cfg_space_rx_buffer;
+ 36: flash_cfg5 <= wishbone_cfg_space_rx_buffer;
+ 40: core_ctl1 <= wishbone_cfg_space_rx_buffer;
+ endcase
+
+ // Signal transfer complete
+ cfg_wishbone_ack_reg <= 1;
+
+ wishbone_config_transfer_state <= WB_CFG_TRANSFER_STATE_TR01;
+ end
+ end
+ end
+ WB_CFG_TRANSFER_STATE_TR01: begin
+ // Cycle complete
+ cfg_wishbone_ack_reg <= 0;
+ wishbone_config_transfer_state <= WB_CFG_TRANSFER_STATE_IDLE;
+ end
+ default: begin
+ // Should never reach this state
+ wishbone_config_transfer_state <= WB_CFG_TRANSFER_STATE_IDLE;
+ end
+ endcase
+ end
+ end
+
+ // SPI bus signals
+ wire spi_data_direction;
+ wire spi_quad_mode_pin_enable;
+ wire drive_host_interfaces;
+ assign drive_host_interfaces = 1;
+ assign spi_d_direction[0] = !spi_quad_mode_pin_enable || (spi_data_direction & drive_host_interfaces);
+ assign spi_d_direction[1] = spi_quad_mode_pin_enable && (spi_data_direction & drive_host_interfaces);
+ assign spi_d_direction[2] = !spi_quad_mode_pin_enable || (spi_data_direction & drive_host_interfaces);
+ assign spi_d_direction[3] = !spi_quad_mode_pin_enable || (spi_data_direction & drive_host_interfaces);
+
+ // Interface registers
+ wire [7:0] spi_clock_divisor;
+ wire [7:0] dummy_cycle_count;
+ wire [1:0] phy_io_type;
+ wire [7:0] cs_extra_idle_cycles;
+ wire four_byte_address_mode;
+ wire fast_read_mode;
+ wire qspi_read_quad_io_en;
+ wire qspi_write_quad_io_en;
+ wire [7:0] qspi_read_4ba_command_code;
+ wire [7:0] qspi_read_3ba_command_code;
+ wire [7:0] spi_read_4ba_command_code;
+ wire [7:0] spi_read_3ba_command_code;
+ wire [7:0] qspi_fast_read_4ba_command_code;
+ wire [7:0] qspi_fast_read_3ba_command_code;
+ wire [7:0] spi_fast_read_4ba_command_code;
+ wire [7:0] spi_fast_read_3ba_command_code;
+ wire [7:0] qspi_program_4ba_command_code;
+ wire [7:0] qspi_program_3ba_command_code;
+ wire [7:0] spi_program_4ba_command_code;
+ wire [7:0] spi_program_3ba_command_code;
+ wire [31:0] spi_cs_active_hold_cycles;
+ wire allow_multicycle_writes;
+ wire allow_multicycle_reads;
+ wire user_command_mode;
+ reg [7:0] user_command_mode_read_during_write = 0;
+ assign spi_clock_divisor = phy_cfg1[7:0];
+ assign dummy_cycle_count = phy_cfg1[15:8];
+ assign phy_io_type = phy_cfg1[17:16];
+ assign cs_extra_idle_cycles = phy_cfg1[31:24];
+ assign four_byte_address_mode = phy_cfg1[18];
+ assign fast_read_mode = phy_cfg1[19];
+ assign qspi_read_quad_io_en = phy_cfg1[20];
+ assign qspi_write_quad_io_en = phy_cfg1[21];
+ assign qspi_read_4ba_command_code = flash_cfg1[31:24];
+ assign qspi_read_3ba_command_code = flash_cfg1[23:16];
+ assign spi_read_4ba_command_code = flash_cfg1[15:8];
+ assign spi_read_3ba_command_code = flash_cfg1[7:0];
+ assign qspi_fast_read_4ba_command_code = flash_cfg2[31:24];
+ assign qspi_fast_read_3ba_command_code = flash_cfg2[23:16];
+ assign spi_fast_read_4ba_command_code = flash_cfg2[15:8];
+ assign spi_fast_read_3ba_command_code = flash_cfg2[7:0];
+ assign qspi_program_4ba_command_code = flash_cfg3[31:24];
+ assign qspi_program_3ba_command_code = flash_cfg3[23:16];
+ assign spi_program_4ba_command_code = flash_cfg3[15:8];
+ assign spi_program_3ba_command_code = flash_cfg3[7:0];
+ assign spi_cs_active_hold_cycles = flash_cfg4[31:0];
+ assign allow_multicycle_writes = flash_cfg5[1];
+ assign allow_multicycle_reads = flash_cfg5[0];
+ assign user_command_mode = core_ctl1[0];
+ assign core_data1 = {24'h000000, user_command_mode_read_during_write};
+
+ parameter PHY_IO_TYPE_SINGLE = 0;
+ parameter PHY_IO_TYPE_QUAD = 2;
+
+ // PHY clock generator
+ // Divisor:
+ // (spi_clock_divisor - 1) * 2
+ // 0 == undefined (actually divide by two)
+ // 1 == divide by 1
+ // 2 == divide by 2
+ // 3 == divide by 4
+ // 4 == divide by 6
+ // 5 == divide by 8
+ // 6 == divide by 10
+ // 7 == divide by 12
+ // etc.
+ wire spi_phy_clock;
+ reg spi_phy_clock_gen_reg = 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
+ 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
+ end
+
+ reg [31:0] phy_tx_data = 0;
+ wire [31:0] phy_rx_data;
+ reg phy_hold_ss_active = 0;
+ reg phy_qspi_mode_active = 0;
+ reg phy_qspi_transfer_mode = 0;
+ reg phy_qspi_transfer_direction = 0;
+ reg [7:0] phy_dummy_cycle_count = 0;
+ reg [3:0] single_cycle_read_counter = 0;
+ reg [3:0] single_cycle_write_counter = 0;
+ reg phy_cycle_start = 0;
+ wire phy_transaction_complete;
+
+ spi_master_phy_quad spi_master_phy_quad(
+ .platform_clock(spi_phy_clock),
+ .reset(peripheral_reset),
+ .tx_data(phy_tx_data),
+ .rx_data(phy_rx_data),
+ .dummy_cycle_count(phy_dummy_cycle_count),
+ .hold_ss_active(phy_hold_ss_active),
+ .qspi_mode_active(phy_qspi_mode_active),
+ .qspi_transfer_mode(phy_qspi_transfer_mode),
+ .qspi_transfer_direction(phy_qspi_transfer_direction),
+ .cycle_start(phy_cycle_start),
+ .transaction_complete(phy_transaction_complete),
+
+ .spi_clock(spi_clock),
+ .spi_d0_out(spi_d_out[0]),
+ .spi_d0_in(spi_d_in[0]),
+ .spi_d1_out(spi_d_out[1]),
+ .spi_d1_in(spi_d_in[1]),
+ .spi_d2_out(spi_d_out[2]),
+ .spi_d2_in(spi_d_in[2]),
+ .spi_d3_out(spi_d_out[3]),
+ .spi_d3_in(spi_d_in[3]),
+ .spi_ss_n(spi_ss_n),
+ .spi_data_direction(spi_data_direction),
+ .spi_quad_mode_pin_enable(spi_quad_mode_pin_enable)
+ );
+
+ reg [3:0] wishbone_sel_reg = 0;
+ reg wishbone_ack_reg = 0;
+ assign wishbone_ack = wishbone_ack_reg;
+ 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_TR03 = 16;
+ parameter SPI_MASTER_TRANSFER_STATE_TR04 = 17;
+ parameter SPI_MASTER_TRANSFER_STATE_TR05 = 18;
+ parameter SPI_MASTER_TRANSFER_STATE_TR06 = 19;
+ parameter SPI_MASTER_TRANSFER_STATE_TR07 = 20;
+ parameter SPI_MASTER_TRANSFER_STATE_TR08 = 21;
+ parameter SPI_MASTER_TRANSFER_STATE_TR09 = 22;
+ parameter SPI_MASTER_TRANSFER_STATE_TR10 = 23;
+ parameter SPI_MASTER_TRANSFER_STATE_TR11 = 24;
+ parameter SPI_MASTER_TRANSFER_STATE_TR12 = 25;
+ parameter SPI_MASTER_TRANSFER_STATE_RD01 = 32;
+ parameter SPI_MASTER_TRANSFER_STATE_RD02 = 33;
+ parameter SPI_MASTER_TRANSFER_STATE_RD03 = 34;
+ parameter SPI_MASTER_TRANSFER_STATE_WR01 = 48;
+ parameter SPI_MASTER_TRANSFER_STATE_WR02 = 49;
+ parameter SPI_MASTER_TRANSFER_STATE_WR03 = 50;
+ parameter SPI_MASTER_TRANSFER_STATE_UC01 = 64;
+ parameter SPI_MASTER_TRANSFER_STATE_UC02 = 65;
+ parameter SPI_MASTER_TRANSFER_STATE_UC03 = 66;
+ parameter SPI_MASTER_TRANSFER_STATE_UC04 = 67;
+
+ reg [7:0] byte_out = 0;
+ reg [7:0] spi_transfer_state = 0;
+ reg spi_data_cycle_type = 0;
+ reg [31:0] spi_address_reg = 0;
+ reg [1:0] phy_io_type_reg;
+ reg [31:0] spi_byte_read_count = 0;
+ reg wishbone_data_cycle_type = 0;
+ reg wishbone_access_is_32_bits = 0;
+ reg user_command_mode_active = 0;
+ reg multicycle_read_in_progress = 0;
+ reg multicycle_write_in_progress = 0;
+ reg [31:0] multicycle_transaction_address = 0;
+ reg [7:0] cs_extra_cycle_counter = 0;
+ reg [31:0] spi_cs_active_counter = 0;
+
+ assign debug_port = spi_transfer_state;
+
+ always @(posedge peripheral_clock) begin
+ if (peripheral_reset) begin
+ // Reset PHY
+ phy_hold_ss_active <= 0;
+ phy_qspi_mode_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_qspi_transfer_direction <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_cycle_start <= 0;
+
+ // Reset Wishbone interface / control state machine
+ wishbone_ack_reg <= 0;
+ wishbone_data_cycle_type <= 0;
+ wishbone_access_is_32_bits <= 0;
+ user_command_mode_read_during_write <= 0;
+ user_command_mode_active <= 0;
+ multicycle_read_in_progress <= 0;
+ multicycle_write_in_progress <= 0;
+ multicycle_transaction_address <= 0;
+ spi_cs_active_counter <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end else begin
+ case (spi_transfer_state)
+ SPI_MASTER_TRANSFER_STATE_IDLE: begin
+ // Compute effective address
+ spi_address_reg[31:2] = wishbone_adr;
+ case (wishbone_sel)
+ 4'b0001: spi_address_reg[1:0] = 0;
+ 4'b0010: spi_address_reg[1:0] = 1;
+ 4'b0100: spi_address_reg[1:0] = 2;
+ 4'b1000: spi_address_reg[1:0] = 3;
+ 4'b1111: spi_address_reg[1:0] = 0;
+ default: spi_address_reg[1:0] = 0;
+ endcase
+
+ // Process command
+ if ((spi_cs_active_hold_cycles > 0) && (spi_cs_active_counter >= spi_cs_active_hold_cycles)) begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (!user_command_mode && user_command_mode_active) begin
+ // Exit user command mode
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (multicycle_read_in_progress) begin
+ if (!allow_multicycle_reads) begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (wishbone_cyc && wishbone_stb) begin
+ if (user_command_mode) begin
+ // User command mode requested
+ // Stop multicycle transfer in preparation to enable user command mode
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (wishbone_data_cycle_type) begin
+ // Write requested
+ // Stop multicycle transfer in preparation to enable write mode
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else begin
+ // Select 8-bit/32-bit transfer size via Wishbone access mode
+ if (wishbone_sel == 4'b1111) begin
+ wishbone_access_is_32_bits <= 1;
+ end else begin
+ wishbone_access_is_32_bits <= 0;
+ end
+ wishbone_sel_reg <= wishbone_sel;
+
+ // Verify next address matches current address
+ if (four_byte_address_mode) begin
+ if (multicycle_transaction_address == spi_address_reg) begin
+ // Transfer next data chunk
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD01;
+ end else begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end
+ end else begin
+ if (multicycle_transaction_address[23:0] == spi_address_reg[23:0]) begin
+ // Transfer next data chunk
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD01;
+ end else begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end
+ end
+ end
+ end
+ end else if (multicycle_write_in_progress) begin
+ if (!allow_multicycle_writes) begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (wishbone_cyc && wishbone_stb) begin
+ if (user_command_mode) begin
+ // User command mode requested
+ // Stop multicycle transfer in preparation to enable user command mode
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else if (!wishbone_data_cycle_type) begin
+ // Read requested
+ // Stop multicycle transfer in preparation to enable read mode
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end else begin
+ // Select 8-bit/32-bit transfer size via Wishbone access mode
+ if (wishbone_sel == 4'b1111) begin
+ wishbone_access_is_32_bits <= 1;
+ end else begin
+ wishbone_access_is_32_bits <= 0;
+ end
+ wishbone_sel_reg <= wishbone_sel;
+
+ // Verify next address matches current address
+ if (four_byte_address_mode) begin
+ if (multicycle_transaction_address == spi_address_reg) begin
+ // Transfer next data chunk
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR01;
+ end else begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end
+ end else begin
+ if (multicycle_transaction_address[23:0] == spi_address_reg[23:0]) begin
+ // Transfer next data chunk
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR01;
+ end else begin
+ // Stop multicycle transfer
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC02;
+ end
+ end
+ end
+ end
+ end else begin
+ if (wishbone_cyc && wishbone_stb) begin
+ if (wishbone_sel == 4'b1111) begin
+ wishbone_access_is_32_bits <= 1;
+ end else begin
+ wishbone_access_is_32_bits <= 0;
+ end
+ wishbone_sel_reg <= wishbone_sel;
+ wishbone_data_cycle_type <= wishbone_we;
+ phy_io_type_reg <= phy_io_type;
+ if (!phy_transaction_complete) begin
+ if (user_command_mode) begin
+ // Read the data byte to write from the active lane
+ if (wishbone_sel[0]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[31:24];
+ end else if (wishbone_sel[1]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[23:16];
+ end else if (wishbone_sel[2]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[15:8];
+ end else if (wishbone_sel[3]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[7:0];
+ end else begin
+ phy_tx_data[7:0] = 8'hff; // Safe default -- will not send any useful commands / data
+ end
+
+ // Set up SPI access
+ phy_tx_data[31:8] = 0;
+ phy_qspi_mode_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_hold_ss_active <= 1;
+ phy_cycle_start <= 1;
+
+ // Set user command mode active
+ user_command_mode_active <= 1;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC01;
+ end else begin
+ if (!wishbone_we) begin
+ // Set up SPI read access
+ if (phy_io_type == PHY_IO_TYPE_QUAD) begin
+ if (four_byte_address_mode) begin
+ if (fast_read_mode) begin
+ phy_tx_data <= qspi_fast_read_4ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_read_4ba_command_code;
+ end
+ end else begin
+ if (fast_read_mode) begin
+ phy_tx_data <= qspi_fast_read_3ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_read_3ba_command_code;
+ end
+ end
+ end else begin
+ if (four_byte_address_mode) begin
+ if (fast_read_mode) begin
+ phy_tx_data <= spi_fast_read_4ba_command_code;
+ end else begin
+ phy_tx_data <= spi_read_4ba_command_code;
+ end
+ end else begin
+ if (fast_read_mode) begin
+ phy_tx_data <= spi_fast_read_3ba_command_code;
+ end else begin
+ phy_tx_data <= spi_read_3ba_command_code;
+ end
+ end
+ end
+ if (allow_multicycle_reads) begin
+ multicycle_read_in_progress <= 1;
+ end else begin
+ single_cycle_read_counter <= 0;
+ end
+ end else begin
+ // Set up SPI write access
+ if (phy_io_type == PHY_IO_TYPE_QUAD) begin
+ if (four_byte_address_mode) begin
+ phy_tx_data <= qspi_program_4ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_program_3ba_command_code;
+ end
+ end else begin
+ if (four_byte_address_mode) begin
+ phy_tx_data <= spi_program_4ba_command_code;
+ end else begin
+ phy_tx_data <= spi_program_3ba_command_code;
+ end
+ end
+ if (allow_multicycle_writes) begin
+ multicycle_write_in_progress <= 1;
+ end else begin
+ single_cycle_write_counter <= 0;
+ end
+ end
+ phy_qspi_mode_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_hold_ss_active <= 1;
+ phy_cycle_start <= 1;
+
+ if (four_byte_address_mode) begin
+ multicycle_transaction_address <= spi_address_reg;
+ end else begin
+ multicycle_transaction_address <= {8'h00, spi_address_reg[23:0]};
+ end
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR03;
+ end
+ end
+ end
+ end
+
+ if ((spi_cs_active_hold_cycles > 0) && (multicycle_read_in_progress || multicycle_write_in_progress)) begin
+ spi_cs_active_counter <= spi_cs_active_counter + 1;
+ end else begin
+ spi_cs_active_counter <= 0;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_UC01: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+
+ user_command_mode_read_during_write <= phy_rx_data[7:0];
+ if (!wishbone_data_cycle_type) begin
+ // Read cycle
+ // Replicate the output bytes to all active lanes
+ if (wishbone_sel_reg[0]) begin
+ wishbone_dat_r_reg[31:24] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[1]) begin
+ wishbone_dat_r_reg[23:16] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[2]) begin
+ wishbone_dat_r_reg[15:8] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[3]) begin
+ wishbone_dat_r_reg[7:0] <= phy_rx_data[7:0];
+ end
+ end
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR01;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_UC02: begin
+ // Release CS and prepare the SPI device for the next command
+ phy_hold_ss_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_qspi_mode_active <= 0;
+
+ // Terminate user command mode / multicycle transfers
+ user_command_mode_active <= 0;
+ multicycle_read_in_progress <= 0;
+ multicycle_write_in_progress <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC03;
+ end
+ SPI_MASTER_TRANSFER_STATE_UC03: begin
+ // Wait for CS to return to idle, since this state machine is running
+ // significantly faster than the SPI PHY state machine. This avoids
+ // potentially short cycling the PHY and not allowing CS to return
+ // to idle, thus inadvertently chaining the next command onto the
+ // previous one!
+ if (spi_ss_n) begin
+ if (cs_extra_idle_cycles > 0) begin
+ cs_extra_cycle_counter <= 1;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_UC04;
+ end else begin
+ // Return to idle
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_UC04: begin
+ if (cs_extra_cycle_counter >= cs_extra_idle_cycles) begin
+ // Return to idle
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end else begin
+ cs_extra_cycle_counter <= cs_extra_cycle_counter + 1;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR01: begin
+ // Wait for CS to return to idle, since this state machine is running
+ // significantly faster than the SPI PHY state machine. This avoids
+ // potentially short cycling the PHY and not allowing CS to return
+ // to idle, thus inadvertently chaining the next command onto the
+ // previous one!
+ // If user command mode is active, CS will be asserted by design,
+ // so ignore...
+ if (spi_ss_n || user_command_mode_active
+ || multicycle_read_in_progress
+ || multicycle_write_in_progress) begin
+ if (!wishbone_data_cycle_type
+ && wishbone_access_is_32_bits
+ && !allow_multicycle_reads
+ && (single_cycle_read_counter < 4)) begin
+ // Set up SPI read access for next byte
+ if (phy_io_type == PHY_IO_TYPE_QUAD) begin
+ if (four_byte_address_mode) begin
+ if (fast_read_mode) begin
+ phy_tx_data <= qspi_fast_read_4ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_read_4ba_command_code;
+ end
+ end else begin
+ if (fast_read_mode) begin
+ phy_tx_data <= qspi_fast_read_3ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_read_3ba_command_code;
+ end
+ end
+ end else begin
+ if (four_byte_address_mode) begin
+ if (fast_read_mode) begin
+ phy_tx_data <= spi_fast_read_4ba_command_code;
+ end else begin
+ phy_tx_data <= spi_read_4ba_command_code;
+ end
+ end else begin
+ if (fast_read_mode) begin
+ phy_tx_data <= spi_fast_read_3ba_command_code;
+ end else begin
+ phy_tx_data <= spi_read_3ba_command_code;
+ end
+ end
+ end
+
+ phy_qspi_mode_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_hold_ss_active <= 1;
+ phy_cycle_start <= 1;
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR03;
+ end else if (wishbone_data_cycle_type
+ && wishbone_access_is_32_bits
+ && !allow_multicycle_writes
+ && (single_cycle_write_counter < 4)) begin
+ // Set up SPI write access for next byte
+ if (phy_io_type == PHY_IO_TYPE_QUAD) begin
+ if (four_byte_address_mode) begin
+ phy_tx_data <= qspi_program_4ba_command_code;
+ end else begin
+ phy_tx_data <= qspi_program_3ba_command_code;
+ end
+ end else begin
+ if (four_byte_address_mode) begin
+ phy_tx_data <= spi_program_4ba_command_code;
+ end else begin
+ phy_tx_data <= spi_program_3ba_command_code;
+ end
+ end
+
+ phy_qspi_mode_active <= 0;
+ phy_qspi_transfer_mode <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_hold_ss_active <= 1;
+ phy_cycle_start <= 1;
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR03;
+ end else begin
+ // Signal transfer complete
+ wishbone_ack_reg <= 1;
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR02;
+ end
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR02: begin
+ // Cycle complete
+ wishbone_ack_reg <= 0;
+ spi_cs_active_counter <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end
+ SPI_MASTER_TRANSFER_STATE_TR03: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR04;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR04: begin
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ if (!wishbone_data_cycle_type) begin
+ // Read
+ phy_qspi_mode_active <= qspi_read_quad_io_en;
+ end else begin
+ // Write
+ phy_qspi_mode_active <= qspi_write_quad_io_en;
+ end
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ if (four_byte_address_mode) begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR05;
+ end else begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR07;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR05: begin
+ // Address (4 bytes / 1 word)
+ if (!phy_transaction_complete) begin
+ if (wishbone_access_is_32_bits && !allow_multicycle_reads) begin
+ phy_tx_data <= multicycle_transaction_address;
+ end else begin
+ phy_tx_data <= spi_address_reg;
+ end
+ phy_qspi_transfer_mode <= 1;
+ phy_qspi_transfer_direction <= 1;
+ if (!wishbone_data_cycle_type) begin
+ // Read
+ if (fast_read_mode) begin
+ phy_dummy_cycle_count <= dummy_cycle_count;
+ end else begin
+ phy_dummy_cycle_count <= 0;
+ end
+ end else begin
+ // Write
+ phy_dummy_cycle_count <= 0;
+ end
+ phy_cycle_start <= 1;
+
+ spi_byte_read_count <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR06;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR06: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+
+ if (wishbone_data_cycle_type) begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR01;
+ end else begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD01;
+ end
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_RD01: begin
+ if (!phy_transaction_complete) begin
+ // Data words
+ phy_tx_data <= 0; // Not used
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ if (wishbone_access_is_32_bits && allow_multicycle_reads) begin
+ phy_qspi_transfer_mode <= 1;
+ end else begin
+ phy_qspi_transfer_mode <= 0;
+ end
+ phy_qspi_transfer_direction <= 0;
+ phy_dummy_cycle_count <= 0;
+ phy_cycle_start <= 1;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD02;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_RD02: begin
+ if (phy_transaction_complete) begin
+ // Set Wishbone output data
+ if (wishbone_access_is_32_bits) begin
+ if (allow_multicycle_reads) begin
+ wishbone_dat_r_reg <= phy_rx_data;
+ multicycle_transaction_address <= multicycle_transaction_address + 4;
+ end else begin
+ if (single_cycle_read_counter == 0) begin
+ wishbone_dat_r_reg[31:24] <= phy_rx_data[7:0];
+ end else if (single_cycle_read_counter == 1) begin
+ wishbone_dat_r_reg[23:16] <= phy_rx_data[7:0];
+ end else if (single_cycle_read_counter == 2) begin
+ wishbone_dat_r_reg[15:8] <= phy_rx_data[7:0];
+ end else if (single_cycle_read_counter == 3) begin
+ wishbone_dat_r_reg[7:0] <= phy_rx_data[7:0];
+ end
+ single_cycle_read_counter <= single_cycle_read_counter + 1;
+ multicycle_transaction_address <= multicycle_transaction_address + 1;
+ end
+ end else begin
+ // Replicate the data bytes to all active lanes
+ if (wishbone_sel_reg[0]) begin
+ wishbone_dat_r_reg[31:24] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[1]) begin
+ wishbone_dat_r_reg[23:16] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[2]) begin
+ wishbone_dat_r_reg[15:8] <= phy_rx_data[7:0];
+ end
+ if (wishbone_sel_reg[3]) begin
+ wishbone_dat_r_reg[7:0] <= phy_rx_data[7:0];
+ end
+ multicycle_transaction_address <= multicycle_transaction_address + 1;
+ end
+
+ phy_cycle_start <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD03;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_RD03: begin
+ if (!phy_transaction_complete) begin
+ // Release CS (if required)
+ if (!multicycle_read_in_progress) begin
+ phy_hold_ss_active <= 0;
+ end
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR01;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_WR01: begin
+ if (!phy_transaction_complete) begin
+ // Data words
+ if (wishbone_access_is_32_bits) begin
+ if (allow_multicycle_writes) begin
+ phy_tx_data <= wishbone_dat_w;
+ phy_qspi_transfer_mode <= 1;
+ multicycle_transaction_address <= multicycle_transaction_address + 4;
+ end else begin
+ if (single_cycle_write_counter == 0) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[7:0];
+ end else if (single_cycle_write_counter == 1) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[15:8];
+ end else if (single_cycle_write_counter == 2) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[23:16];
+ end else if (single_cycle_write_counter == 3) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[31:24];
+ end
+ phy_qspi_transfer_mode <= 0;
+ single_cycle_write_counter <= single_cycle_write_counter + 1;
+ multicycle_transaction_address <= multicycle_transaction_address + 1;
+ end
+ end else begin
+ // Write cycle
+ // Read the data byte to write from the active lane
+ if (wishbone_sel_reg[0]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[31:24];
+ end else if (wishbone_sel_reg[1]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[23:16];
+ end else if (wishbone_sel_reg[2]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[15:8];
+ end else if (wishbone_sel_reg[3]) begin
+ phy_tx_data[7:0] <= wishbone_dat_w[7:0];
+ end else begin
+ phy_tx_data[7:0] = 8'hff; // Safe default -- will not overwrite any bits
+ end
+ phy_tx_data[31:8] = 0;
+ phy_qspi_transfer_mode <= 0;
+ multicycle_transaction_address <= multicycle_transaction_address + 1;
+ end
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ phy_qspi_transfer_direction <= 1;
+ phy_dummy_cycle_count <= 0;
+ phy_cycle_start <= 1;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR02;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_WR02: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR03;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_WR03: begin
+ if (!phy_transaction_complete) begin
+ // Release CS (if required)
+ if (!multicycle_write_in_progress) begin
+ phy_hold_ss_active <= 0;
+ end
+
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR01;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR07: begin
+ // Send the three address bytes one at a time...
+ if (!phy_transaction_complete) begin
+ if (wishbone_access_is_32_bits && !allow_multicycle_reads) begin
+ phy_tx_data <= multicycle_transaction_address[23:16];
+ end else begin
+ phy_tx_data <= spi_address_reg[23:16];
+ end
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ phy_qspi_transfer_mode <= 0;
+ phy_qspi_transfer_direction <= 1;
+ phy_dummy_cycle_count <= 0;
+ phy_cycle_start <= 1;
+
+ spi_byte_read_count <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR08;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR08: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR09;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR09: begin
+ if (!phy_transaction_complete) begin
+ if (wishbone_access_is_32_bits && !allow_multicycle_reads) begin
+ phy_tx_data <= multicycle_transaction_address[15:8];
+ end else begin
+ phy_tx_data <= spi_address_reg[15:8];
+ end
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ phy_qspi_transfer_mode <= 0;
+ phy_qspi_transfer_direction <= 1;
+ phy_dummy_cycle_count <= 0;
+ phy_cycle_start <= 1;
+
+ spi_byte_read_count <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR10;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR10: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR11;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR11: begin
+ if (!phy_transaction_complete) begin
+ if (wishbone_access_is_32_bits && !allow_multicycle_reads) begin
+ phy_tx_data <= multicycle_transaction_address[7:0];
+ end else begin
+ phy_tx_data <= spi_address_reg[7:0];
+ end
+ if (phy_io_type_reg == PHY_IO_TYPE_QUAD) begin
+ phy_qspi_mode_active <= 1;
+ end else begin
+ phy_qspi_mode_active <= 0;
+ end
+ phy_qspi_transfer_mode <= 0;
+ phy_qspi_transfer_direction <= 1;
+ if (!wishbone_data_cycle_type) begin
+ // Read
+ if (fast_read_mode) begin
+ phy_dummy_cycle_count <= dummy_cycle_count;
+ end else begin
+ phy_dummy_cycle_count <= 0;
+ end
+ end else begin
+ phy_dummy_cycle_count <= 0;
+ end
+ phy_cycle_start <= 1;
+
+ spi_byte_read_count <= 0;
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_TR12;
+ end
+ end
+ SPI_MASTER_TRANSFER_STATE_TR12: begin
+ if (phy_transaction_complete) begin
+ phy_cycle_start <= 0;
+ if (wishbone_data_cycle_type) begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_WR01;
+ end else begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_RD01;
+ end
+ end
+ end
+ default: begin
+ spi_transfer_state <= SPI_MASTER_TRANSFER_STATE_IDLE;
+ end
+ endcase
+ end
+ end
+endmodule