101 lines
2.8 KiB
Verilog
101 lines
2.8 KiB
Verilog
`timescale 1ns/1ps
|
|
|
|
module spi_controller_simple (
|
|
input clk,
|
|
input rst_n,
|
|
input [7:0] data_in,
|
|
input start,
|
|
output reg [7:0] data_out,
|
|
output reg busy,
|
|
output reg spi_clk,
|
|
output reg mosi,
|
|
input miso
|
|
);
|
|
// Simplified FSM: IDLE -> SEND -> SAMPLE -> DONE -> IDLE
|
|
localparam IDLE = 2'd0;
|
|
localparam SEND = 2'd1;
|
|
localparam SAMPLE = 2'd2;
|
|
localparam DONE = 2'd3;
|
|
|
|
reg [1:0] state;
|
|
reg [2:0] bit_count;
|
|
reg [7:0] shift_reg;
|
|
reg spi_clk_en;
|
|
|
|
// SPI clock generation: derived from main FSM state
|
|
// spi_clk toggles when in SEND state
|
|
wire spi_clk_next = spi_clk_en ? ~spi_clk : 1'b0;
|
|
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
spi_clk <= 1'b0;
|
|
end else begin
|
|
spi_clk <= spi_clk_next;
|
|
end
|
|
end
|
|
|
|
// Main FSM - single always block drives all registers
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
state <= IDLE;
|
|
bit_count <= 3'd0;
|
|
shift_reg <= 8'd0;
|
|
data_out <= 8'd0;
|
|
busy <= 1'b0;
|
|
mosi <= 1'b0;
|
|
spi_clk_en <= 1'b0;
|
|
end else begin
|
|
case (state)
|
|
IDLE: begin
|
|
busy <= 1'b0;
|
|
mosi <= 1'b0;
|
|
spi_clk_en <= 1'b0;
|
|
if (start) begin
|
|
busy <= 1'b1;
|
|
shift_reg <= data_in;
|
|
bit_count <= 3'd7;
|
|
state <= SEND;
|
|
spi_clk_en <= 1'b1;
|
|
end
|
|
end
|
|
|
|
SEND: begin
|
|
busy <= 1'b1;
|
|
mosi <= shift_reg[7];
|
|
// Check if spi_clk just transitioned (rising edge detection)
|
|
if (spi_clk == 1'b0) begin
|
|
state <= SAMPLE;
|
|
end
|
|
end
|
|
|
|
SAMPLE: begin
|
|
busy <= 1'b1;
|
|
// Shift in miso
|
|
shift_reg <= {shift_reg[6:0], miso};
|
|
if (bit_count == 3'd0) begin
|
|
data_out <= {shift_reg[6:0], miso};
|
|
state <= DONE;
|
|
spi_clk_en <= 1'b0;
|
|
end else begin
|
|
bit_count <= bit_count - 1'b1;
|
|
state <= SEND;
|
|
end
|
|
end
|
|
|
|
DONE: begin
|
|
busy <= 1'b0;
|
|
mosi <= 1'b0;
|
|
state <= IDLE;
|
|
spi_clk_en <= 1'b0;
|
|
end
|
|
|
|
default: begin
|
|
state <= IDLE;
|
|
spi_clk_en <= 1'b0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
endmodule
|