|
@@ -20,6 +20,27 @@
|
|
|
|
|
|
`define IO_MAX max(ilog2c(width)-1, 1)
|
|
|
|
|
|
+function reg [7:0] shift_in
|
|
|
+(
|
|
|
+ input [7:0] prev,
|
|
|
+ input [7:0] in,
|
|
|
+ input [1:0] xwidth, // log2(transaction width)
|
|
|
+ input [0:0] lsb
|
|
|
+ );
|
|
|
+
|
|
|
+ (* full_case *)
|
|
|
+ case (xwidth)
|
|
|
+ 2'd0:
|
|
|
+ shift_in = lsb ? { in[0], prev[7:1] } : { prev[6:0], in[0] };
|
|
|
+ 2'd1:
|
|
|
+ shift_in = lsb ? { in[1:0], prev[7:2] } : { prev[5:0], in[1:0] };
|
|
|
+ 2'd2:
|
|
|
+ shift_in = lsb ? { in[3:0], prev[7:4] } : { prev[3:0], in[3:0] };
|
|
|
+ 2'd3:
|
|
|
+ shift_in = in;
|
|
|
+ endcase // case (width)
|
|
|
+endfunction // shift_in
|
|
|
+
|
|
|
module spi_master
|
|
|
#(
|
|
|
parameter width = 1, // Max width of SPI bus (1, 2, 4, or 8)
|
|
@@ -113,11 +134,9 @@ module spi_master
|
|
|
spi_sck <= (spi_ctr[0] & spi_active) ^ cpol;
|
|
|
|
|
|
if (~spi_ctr[0])
|
|
|
- if (lsb)
|
|
|
- d_in <= (spi_io[spi_width_n-1:0] << (8-spi_width_n)) |
|
|
|
- (d_in >> spi_width_n);
|
|
|
- else
|
|
|
- d_in <= (d_in << spi_width_n) | spi_io[spi_width_n-1:0];
|
|
|
+ begin
|
|
|
+ d_in <= shift_in(d_in, spi_io, spi_width, lsb);
|
|
|
+ end
|
|
|
else
|
|
|
begin
|
|
|
spi_out_q <= idle_allio;
|
|
@@ -139,19 +158,20 @@ module spi_master
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
- if (lsb)
|
|
|
- d_out <= {spi_width_n{io_idle}} |
|
|
|
- (d_out >> spi_width_n);
|
|
|
- else
|
|
|
- d_out <= (d_out << spi_width_n) |
|
|
|
- {spi_width_n{io_idle}};
|
|
|
-
|
|
|
- // 1-byte SPI uses IO1 as output (DO)
|
|
|
- if (spi_width == 2'd0)
|
|
|
- spi_out_q[1] <= d_out[lsb ? 0 : 7];
|
|
|
- else
|
|
|
- spi_out_q[spi_width_n-1:0]
|
|
|
- <= d_out >> (lsb ? 0 : 8-spi_width_n);
|
|
|
+ d_out <= shift_in(d_out, {8{idle_io}},
|
|
|
+ spi_width, lsb);
|
|
|
+
|
|
|
+ // Note: 1-byte SPI uses IO1 as output (DO)
|
|
|
+ (* full_case *)
|
|
|
+ casez ( {spi_width, lsb} )
|
|
|
+ 3'b00_0: spi_out_q[1] <= d_out[7];
|
|
|
+ 3'b00_1: spi_out_q[1] <= d_out[0];
|
|
|
+ 3'b01_0: spi_out_q[1:0] <= d_out[7:6];
|
|
|
+ 3'b01_1: spi_out_q[1:0] <= d_out[1:0];
|
|
|
+ 3'b10_0: spi_out_q[3:0] <= d_out[7:4];
|
|
|
+ 3'b10_1: spi_out_q[3:0] <= d_out[3:0];
|
|
|
+ 3'b11_?: spi_out_q <= d_out;
|
|
|
+ endcase // casez ( {spi_width, lsb} )
|
|
|
end
|
|
|
end // if (spi_active)
|
|
|
else
|