Files
fpga-basics/Verilator_Tests/spi/spi_master.v
2025-07-10 22:10:05 +01:00

82 lines
1.9 KiB
Verilog

module spi_master (
input wire clk,
output reg spi_clk = 0,
input wire start, // Pulse high to begin transfer
input reg [7:0] data_out = 8'd0,
output reg spi_mosi = 0,
output wire [7:0] data_in,
input wire spi_miso,
output reg busy = 0,
output reg spi_cs = 1 // Active low
);
// SPI Mode 0: CPOL = 0, CPHA = 0 (drive on falling, sample on rising)
reg [3:0] bit_cnt = 0;
reg [7:0] shift_reg_in = 0;
reg [7:0] shift_reg_out = 0;
typedef enum logic [1:0] {
IDLE,
CHIP_SEL,
BUSY,
DONE
} state_t;
state_t state = IDLE;
always @(posedge clk) begin
case (state)
IDLE: begin
spi_cs <= 1;
spi_clk <= 0;
busy <= 0;
if (start) begin
state <= CHIP_SEL;
shift_reg_out <= data_out;
bit_cnt <= 0;
end
end
// data is one cycle after CS is brought low
CHIP_SEL: begin
spi_cs <= 0;
busy <= 1;
state <= BUSY;
end
BUSY: begin
if (clk) begin
spi_clk <= ~spi_clk;
// Falling, drive data
if (!spi_clk) begin
spi_mosi <= shift_reg_out[7];
shift_reg_out <= {shift_reg_out[6:0], 1'b0};
end else begin
// Rising, sample data
shift_reg_in <= {shift_reg_in[6:0], spi_miso};
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 7) begin
state <= DONE;
end
end
end
end
DONE: begin
spi_cs <= 1;
data_in <= {shift_reg_in[6:0], spi_miso};
state <= IDLE;
end
endcase
end
endmodule