module spi_fifo ( input wire clock, reset, input wire bus_ssel, bus_wren, input wire [15:0] bus_mosi, output wire bus_busy, output wire [1:0] spi_sel, output wire spi_sdo, output wire spi_clk ); wire int_rdempty, int_wrfull; wire [31:0] int_q; reg int_bus_busy; reg int_rdreq, int_wrreq; reg int_clken, int_sdo; reg [1:0] int_sel; reg [15:0] int_bus_mosi; reg [31:0] int_data; reg [2:0] clk_cntr; reg [4:0] bit_cntr; reg [1:0] state; dcfifo_mixed_widths #( .intended_device_family("Cyclone III"), .lpm_numwords(16), .lpm_showahead("ON"), .lpm_type("dcfifo"), .lpm_width(16), .lpm_widthu(4), .lpm_width_r(32), .lpm_widthu_r(3), .rdsync_delaypipe(4), .wrsync_delaypipe(4), .overflow_checking("ON"), .underflow_checking("ON"), .use_eab("ON")) fifo_tx ( .data(int_bus_mosi), .rdclk(clock), .rdreq((~int_rdempty) & (int_rdreq) & (&clk_cntr)), .wrclk(clock), .wrreq(int_wrreq), .q(int_q), .rdempty(int_rdempty), .wrfull(int_wrfull)); always @ (posedge clock) begin int_bus_busy <= int_wrfull; if (bus_ssel) begin if (~int_wrfull & bus_wren) begin int_bus_mosi <= bus_mosi; int_wrreq <= 1'b1; end end if (~int_wrfull & int_wrreq) begin int_wrreq <= 1'b0; end end always @ (posedge clock) begin clk_cntr <= clk_cntr + 3'd1; if (&clk_cntr) begin case (state) 0: begin int_sdo <= 1'b0; int_sel <= 2'b11; int_clken <= 1'b0; int_rdreq <= 1'b1; state <= 2'd1; end 1: begin if (~int_rdempty) begin int_rdreq <= 1'b0; int_data <= {int_q[15:0], int_q[31:16]}; bit_cntr <= 5'd0; state <= 2'd2; end end 2: begin // data int_clken <= 1'b1; int_sel <= int_data[25:24]; int_sdo <= int_data[23]; int_data[23:0] <= {int_data[22:0], 1'b0}; bit_cntr <= bit_cntr + 5'd1; if (bit_cntr == 5'd23) begin state <= 2'd3; end end 3: begin int_sdo <= 1'b0; int_clken <= 1'b0; state <= 2'd0; end endcase end end // output logic assign bus_busy = int_bus_busy; assign spi_clk = (int_clken ? clk_cntr[2] : 1'b1); assign spi_sdo = int_sdo; assign spi_sel = int_sel; endmodule