max2771 spi liens has been added.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module max2771_spi_engine #(
|
||||
parameter integer CLOCK_HZ = 50_000_000,
|
||||
parameter integer MAX_SCLK_HZ = 4_000_000
|
||||
) (
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire start,
|
||||
input wire read_not_write,
|
||||
input wire [3:0] address,
|
||||
input wire [31:0] write_data,
|
||||
output reg [31:0] read_data,
|
||||
output reg busy,
|
||||
output wire ready,
|
||||
output reg sclk,
|
||||
output reg csn,
|
||||
input wire sdata_i,
|
||||
output reg sdata_o,
|
||||
output reg sdata_oe
|
||||
);
|
||||
// Ceiling division keeps SCLK at or below the MAX2771 4 MHz limit.
|
||||
localparam integer HALF_PERIOD_CYCLES =
|
||||
(CLOCK_HZ + (2 * MAX_SCLK_HZ) - 1) / (2 * MAX_SCLK_HZ);
|
||||
localparam integer CS_INACTIVE_CYCLES =
|
||||
(CLOCK_HZ + 10_000_000 - 1) / 10_000_000;
|
||||
|
||||
reg [47:0] tx_shift;
|
||||
reg [31:0] rx_shift;
|
||||
reg [5:0] bit_index;
|
||||
integer half_count;
|
||||
integer inactive_count;
|
||||
reg transaction_is_read;
|
||||
|
||||
assign ready = !busy && (inactive_count == 0);
|
||||
|
||||
initial begin
|
||||
if (CLOCK_HZ <= 0)
|
||||
$error("CLOCK_HZ must be positive");
|
||||
if (MAX_SCLK_HZ <= 0)
|
||||
$error("MAX_SCLK_HZ must be positive");
|
||||
if (HALF_PERIOD_CYCLES < 1)
|
||||
$error("HALF_PERIOD_CYCLES must be at least one");
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!rst_n) begin
|
||||
read_data <= 32'd0;
|
||||
busy <= 1'b0;
|
||||
sclk <= 1'b0;
|
||||
csn <= 1'b1;
|
||||
sdata_o <= 1'b0;
|
||||
sdata_oe <= 1'b0;
|
||||
tx_shift <= 48'd0;
|
||||
rx_shift <= 32'd0;
|
||||
bit_index <= 6'd0;
|
||||
half_count <= 0;
|
||||
inactive_count <= 0;
|
||||
transaction_is_read <= 1'b0;
|
||||
end else if (busy) begin
|
||||
if (half_count != 0) begin
|
||||
half_count <= half_count - 1;
|
||||
end else begin
|
||||
half_count <= HALF_PERIOD_CYCLES - 1;
|
||||
if (!sclk) begin
|
||||
// MAX2771 samples input and the host samples read data on rising SCLK.
|
||||
sclk <= 1'b1;
|
||||
if (transaction_is_read && (bit_index >= 6'd16))
|
||||
rx_shift <= {rx_shift[30:0], sdata_i};
|
||||
end else begin
|
||||
// Both sides change or release SDATA on falling SCLK.
|
||||
sclk <= 1'b0;
|
||||
if (bit_index == 6'd47) begin
|
||||
read_data <= rx_shift;
|
||||
busy <= 1'b0;
|
||||
csn <= 1'b1;
|
||||
sdata_oe <= 1'b0;
|
||||
inactive_count <= CS_INACTIVE_CYCLES;
|
||||
end else begin
|
||||
bit_index <= bit_index + 1'b1;
|
||||
tx_shift <= {tx_shift[46:0], 1'b0};
|
||||
sdata_o <= tx_shift[46];
|
||||
if (transaction_is_read && (bit_index == 6'd12))
|
||||
sdata_oe <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else if (inactive_count != 0) begin
|
||||
inactive_count <= inactive_count - 1;
|
||||
end else if (start) begin
|
||||
// Frame: A[11:0], R/W, three turnaround bits, D[31:0]. A[11:4] are zero.
|
||||
tx_shift <= {8'd0, address, read_not_write, 3'd0, write_data};
|
||||
rx_shift <= 32'd0;
|
||||
bit_index <= 6'd0;
|
||||
transaction_is_read <= read_not_write;
|
||||
busy <= 1'b1;
|
||||
csn <= 1'b0;
|
||||
sclk <= 1'b0;
|
||||
sdata_o <= 1'b0;
|
||||
sdata_oe <= 1'b1;
|
||||
half_count <= HALF_PERIOD_CYCLES - 1;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user