Explorar o código

spi_master: remove non-synthesizable constructs

Seems like some things in this file were not supported by synthesis;
restructure slightly to resolve.
H. Peter Anvin %!s(int64=3) %!d(string=hai) anos
pai
achega
35ce29d153
Modificáronse 1 ficheiros con 38 adicións e 18 borrados
  1. 38 18
      spi_master.sv

+ 38 - 18
spi_master.sv

@@ -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