136 lines
3.9 KiB
Coq
136 lines
3.9 KiB
Coq
|
|
`timescale 1ns/1ps
|
||
|
|
|
||
|
|
module spi_controller (
|
||
|
|
input clk,
|
||
|
|
input rst_n,
|
||
|
|
input [7:0] data_in,
|
||
|
|
input start,
|
||
|
|
input cpol,
|
||
|
|
input cpha,
|
||
|
|
output reg [7:0] data_out,
|
||
|
|
output reg busy,
|
||
|
|
output reg spi_clk,
|
||
|
|
output reg mosi,
|
||
|
|
input miso
|
||
|
|
);
|
||
|
|
localparam IDLE = 3'd0;
|
||
|
|
localparam LOAD = 3'd1;
|
||
|
|
localparam LEAD = 3'd2;
|
||
|
|
localparam SAMPLE = 3'd3;
|
||
|
|
localparam SHIFT = 3'd4;
|
||
|
|
localparam DONE = 3'd5;
|
||
|
|
localparam ERROR = 3'd6;
|
||
|
|
|
||
|
|
reg [2:0] state;
|
||
|
|
reg [2:0] bit_count;
|
||
|
|
reg [7:0] tx_shift;
|
||
|
|
reg [7:0] rx_shift;
|
||
|
|
|
||
|
|
always @(posedge clk or negedge rst_n) begin
|
||
|
|
if (!rst_n) begin
|
||
|
|
state <= IDLE;
|
||
|
|
bit_count <= 3'd0;
|
||
|
|
tx_shift <= 8'd0;
|
||
|
|
rx_shift <= 8'd0;
|
||
|
|
data_out <= 8'd0;
|
||
|
|
busy <= 1'b0;
|
||
|
|
spi_clk <= 1'b0;
|
||
|
|
mosi <= 1'b0;
|
||
|
|
end else begin
|
||
|
|
case (state)
|
||
|
|
IDLE: begin
|
||
|
|
busy <= 1'b0;
|
||
|
|
spi_clk <= cpol;
|
||
|
|
mosi <= 1'b0;
|
||
|
|
if (start) begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
bit_count <= 3'd7;
|
||
|
|
tx_shift <= data_in;
|
||
|
|
rx_shift <= 8'd0;
|
||
|
|
state <= LOAD;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
LOAD: begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
spi_clk <= cpol;
|
||
|
|
mosi <= tx_shift[7];
|
||
|
|
if (start) begin
|
||
|
|
state <= ERROR;
|
||
|
|
end else begin
|
||
|
|
state <= LEAD;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
LEAD: begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
spi_clk <= ~cpol;
|
||
|
|
if (start) begin
|
||
|
|
state <= ERROR;
|
||
|
|
end else if (!cpha) begin
|
||
|
|
rx_shift <= {rx_shift[6:0], miso};
|
||
|
|
if (bit_count == 3'd0) begin
|
||
|
|
data_out <= {rx_shift[6:0], miso};
|
||
|
|
state <= DONE;
|
||
|
|
end else begin
|
||
|
|
state <= SHIFT;
|
||
|
|
end
|
||
|
|
end else begin
|
||
|
|
state <= SAMPLE;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
SAMPLE: begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
spi_clk <= ~cpol;
|
||
|
|
if (start) begin
|
||
|
|
state <= ERROR;
|
||
|
|
end else begin
|
||
|
|
rx_shift <= {rx_shift[6:0], miso};
|
||
|
|
if (bit_count == 3'd0) begin
|
||
|
|
data_out <= {rx_shift[6:0], miso};
|
||
|
|
state <= DONE;
|
||
|
|
end else begin
|
||
|
|
state <= SHIFT;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
SHIFT: begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
spi_clk <= cpol;
|
||
|
|
tx_shift <= {tx_shift[6:0], 1'b0};
|
||
|
|
bit_count <= bit_count - 1'b1;
|
||
|
|
mosi <= tx_shift[6];
|
||
|
|
if (start) begin
|
||
|
|
state <= ERROR;
|
||
|
|
end else begin
|
||
|
|
state <= LEAD;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
DONE: begin
|
||
|
|
busy <= 1'b0;
|
||
|
|
spi_clk <= cpol;
|
||
|
|
mosi <= 1'b0;
|
||
|
|
if (start) begin
|
||
|
|
state <= ERROR;
|
||
|
|
end else begin
|
||
|
|
state <= IDLE;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
default: begin
|
||
|
|
busy <= 1'b0;
|
||
|
|
spi_clk <= cpol;
|
||
|
|
mosi <= 1'b0;
|
||
|
|
if (!start) begin
|
||
|
|
state <= IDLE;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
endcase
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
endmodule
|