97 lines
2.1 KiB
Verilog
97 lines
2.1 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
module spi_regfile(
|
|
input clk, rst,
|
|
|
|
input sck, sdi, ncs,
|
|
output reg sdo,
|
|
|
|
input [7:0] spi_data_in,
|
|
output reg [7:0] spi_data_out,
|
|
|
|
input [7:0] spi_status_word,
|
|
output reg [7:0] spi_cmd_word,
|
|
output reg spi_cmd_begin,
|
|
output reg spi_cmd_active,
|
|
output reg spi_cmd_step,
|
|
output reg [19:0] spi_cmd_idx,
|
|
output [7:0] rxbuf_dbg
|
|
);
|
|
|
|
reg [6:0] txbuf;
|
|
reg [7:0] rxbuf;
|
|
reg is_cmd_word;
|
|
reg last_ncs;
|
|
reg last_sck;
|
|
reg load_data;
|
|
|
|
assign rxbuf_dbg = rxbuf;
|
|
|
|
wire sck_clean, sdi_clean, ncs_clean;
|
|
edge_cleaner sck_cleaner (.clk(clk), .in(sck), .out(sck_clean));
|
|
edge_cleaner sdi_cleaner (.clk(clk), .in(sdi), .out(sdi_clean));
|
|
edge_cleaner ncs_cleaner (.clk(clk), .in(ncs), .out(ncs_clean));
|
|
|
|
/* SPI mode 0: CPOL = 0, CPHA = 0. Initial SDO setup on falling ~CS edge */
|
|
|
|
always @(posedge clk) begin
|
|
spi_cmd_begin <= 0;
|
|
spi_cmd_step <= 0;
|
|
last_ncs <= ncs_clean;
|
|
last_sck <= sck_clean;
|
|
|
|
if (rst) begin
|
|
is_cmd_word <= 1;
|
|
spi_cmd_active <= 0;
|
|
spi_cmd_idx <= 0;
|
|
|
|
end else begin
|
|
if (last_ncs && !ncs_clean) begin
|
|
txbuf <= spi_status_word[6:0];
|
|
sdo <= spi_status_word[7];
|
|
rxbuf <= 8'h01;
|
|
end
|
|
|
|
if (!ncs_clean) begin
|
|
if (!last_sck && sck_clean) begin /* sampling edge */
|
|
if (!rxbuf[7]) begin
|
|
rxbuf <= {rxbuf[6:0], sdi_clean};
|
|
|
|
end else begin
|
|
rxbuf <= 8'h01;
|
|
load_data <= 1;
|
|
|
|
if (is_cmd_word) begin
|
|
spi_cmd_word <= {rxbuf[6:0], sdi_clean};
|
|
is_cmd_word <= 0;
|
|
spi_cmd_active <= 1;
|
|
spi_cmd_begin <= 1;
|
|
spi_cmd_idx <= 0;
|
|
|
|
end else begin
|
|
spi_data_out <= {rxbuf[6:0], sdi_clean};
|
|
spi_cmd_idx <= spi_cmd_idx+1;
|
|
spi_cmd_step <= 1;
|
|
end
|
|
end
|
|
|
|
end else if (last_sck && !sck_clean) begin /* driving edge */
|
|
if (load_data) begin
|
|
sdo <= spi_data_in[7];
|
|
txbuf <= spi_data_in[6:0];
|
|
load_data <= 0;
|
|
|
|
end else begin
|
|
sdo <= txbuf[6];
|
|
txbuf <= {txbuf[5:0], 1'b0};
|
|
end
|
|
end
|
|
|
|
end else begin
|
|
spi_cmd_active <= 0;
|
|
is_cmd_word <= 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|