module master_spi
#(
- parameter WIDTH = 8
+ parameter WIDTH = 8,
+ parameter CPOL = 0,
+ parameter CPHA = 0,
+ parameter LITTLE_ENDIAN = 0
)
-
(
clk,
+ sclk,
mosi,
miso,
ssel,
);
function integer log2;
- input integer value;
+ input integer n;
begin
- value = value - 1;
- for (log2 = 0; value > 0; log2 = log2 + 1) value = value >> 1;
+ n = n - 1;
+ for (log2 = 0; n > 0; log2 = log2 + 1) n = n >> 1;
end
endfunction
input clk;
+output reg sclk = CPOL;
+output mosi;
input miso;
-output reg mosi = 0;
output reg ssel = 1;
input [WIDTH-1:0] din;
output [WIDTH-1:0] dout;
input s;
reg started = 0;
-reg [log2(WIDTH)-1:0] counter;
+reg [log2(WIDTH):0] counter;
reg [WIDTH-1:0] sp_in = 0;
reg [WIDTH-1:0] sp_out = 0;
+reg [1:0] cooldown = CPHA;
assign dout = sp_out;
+assign mosi = sp_in[LITTLE_ENDIAN ? 0 : WIDTH-1];
always @(posedge clk) begin
if (r) begin
+ cooldown <= CPHA;
started <= 0;
done <= 0;
+ sclk <= CPOL;
ssel <= 1;
end else if (started) begin
if (counter == 0) begin
- ssel <= 1;
- done <= 1;
- end else begin
- ssel <= 0;
- mosi <= sp_in[WIDTH-1];
- sp_in <= sp_in << 1;
- sp_out <= (sp_out << 1) | miso;
+ if (sclk != CPOL) sclk <= ~sclk;
+ if (cooldown == 3) begin
+ done <= 1;
+ end else begin
+ cooldown <= cooldown + 1;
+ if (cooldown == 2) ssel <= 1;
+ end
+ end else if (sclk == (CPOL ^ CPHA)) begin // read cycle
+ if (LITTLE_ENDIAN) sp_out <= { miso, sp_out[WIDTH-1:1] };
+ else sp_out <= (sp_out << 1) | miso;
counter <= counter - 1;
+ sclk <= ~sclk;
+ end else begin // write cycle
+ if (LITTLE_ENDIAN) sp_in <= sp_in >> 1;
+ else sp_in <= sp_in << 1;
+ sclk <= ~sclk;
end
end else if (s) begin
sp_in <= din;
sp_out <= 0;
started <= 1;
+ ssel <= 0;
counter <= WIDTH;
end
end