using OBUFT for the spi miso

Post Reply
russm
Posts: 18
Joined: May 5th, 2013, 2:32 am

using OBUFT for the spi miso

Post by russm » May 6th, 2013, 11:08 pm

The Mojo-Base project defines SPI miso as a tristate, which isn't supported on current Xilinx parts for internal signals (the synthesises tools work around this using extra logic instead). By pushing ~ss up to the avr_interface module and combining it there with the AVR ready signal we can use a OBUFT (output buffer tristate) in one of the FPGA's IO blocks to keep the tristate behaviour on miso, drop usage of logic resources, and make the synthesis tools stop complaining.

Code: Select all

diff --git a/avr_interface.v b/avr_interface.v
index ff17a3c..8a72831 100644
--- a/avr_interface.v
+++ b/avr_interface.v
@@ -33,6 +33,8 @@ wire [7:0] spi_dout;
 
 wire tx_m;
 wire spi_miso_m;
+wire spi_miso_enable_m;
+wire spi_miso_enable;
 
 reg byte_ct_d, byte_ct_q;
 reg [9:0] sample_d, sample_q;
@@ -52,6 +54,7 @@ spi_slave spi_slave (
 	.ss(spi_ss),
 	.mosi(spi_mosi),
 	.miso(spi_miso_m),
+	.miso_enable(spi_miso_enable_m),
 	.sck(spi_sck),
 	.done(spi_done),
 	.din(8'hff),
@@ -81,9 +84,15 @@ assign sample = sample_q;
 assign sample_channel = sample_channel_q;
 
 assign spi_channel = ready ? channel : 4'bZZZZ;
-assign spi_miso = ready ? spi_miso_m : 1'bZ;
+assign spi_miso_enable = ready & spi_miso_enable_m;
 assign tx = ready ? tx_m : 1'bZ;
 
+OBUFT OBUFT_spi_miso (
+  .O(spi_miso),
+  .I(spi_miso_m),
+  .T(spi_miso_enable)
+);
+
 always @(*) begin
 	byte_ct_d = byte_ct_q;
 	sample_d = sample_q;
diff --git a/spi_slave.v b/spi_slave.v
index d62b226..cc4b356 100644
--- a/spi_slave.v
+++ b/spi_slave.v
@@ -4,6 +4,7 @@ module spi_slave(
 	input ss,
 	input mosi,
 	output miso,
+	output miso_enable,
 	input sck,
 	output done,
 	input [7:0] din,
@@ -20,7 +21,8 @@ reg [2:0] bit_ct_d, bit_ct_q;
 reg [7:0] dout_d, dout_q;
 reg miso_d, miso_q;
 
-assign miso = ss ? 1'bZ : miso_q;
+assign miso_enable = ~ss;
+assign miso = miso_q;
 assign done = done_q;
 assign dout = dout_q;
 

russm
Posts: 18
Joined: May 5th, 2013, 2:32 am

Re: using OBUFT for the spi miso

Post by russm » May 7th, 2013, 1:39 am

On second thought, dropping the explicit OBUFT and letting the tools infer the best implementation saves us even more. In this case we just push miso_enable (aka ~ss) up to avr_interface so a potentially hiZ signal never has logic done on it. This version ends up using 10 fewer slices than the one in Mojo-Base.zip, freeing up almost 1% of our capacity.

Code: Select all

diff --git a/avr_interface.v b/avr_interface.v
index ff17a3c..71a8612 100644
--- a/avr_interface.v
+++ b/avr_interface.v
@@ -33,6 +33,7 @@ wire [7:0] spi_dout;
 
 wire tx_m;
 wire spi_miso_m;
+wire spi_miso_enable_m;
 
 reg byte_ct_d, byte_ct_q;
 reg [9:0] sample_d, sample_q;
@@ -52,6 +53,7 @@ spi_slave spi_slave (
 	.ss(spi_ss),
 	.mosi(spi_mosi),
 	.miso(spi_miso_m),
+	.miso_enable(spi_miso_enable_m),
 	.sck(spi_sck),
 	.done(spi_done),
 	.din(8'hff),
@@ -81,7 +83,7 @@ assign sample = sample_q;
 assign sample_channel = sample_channel_q;
 
 assign spi_channel = ready ? channel : 4'bZZZZ;
-assign spi_miso = ready ? spi_miso_m : 1'bZ;
+assign spi_miso = (ready & spi_miso_enable_m) ? spi_miso_m : 1'bZ;
 assign tx = ready ? tx_m : 1'bZ;
 
 always @(*) begin
diff --git a/spi_slave.v b/spi_slave.v
index d62b226..cc4b356 100644
--- a/spi_slave.v
+++ b/spi_slave.v
@@ -4,6 +4,7 @@ module spi_slave(
 	input ss,
 	input mosi,
 	output miso,
+	output miso_enable,
 	input sck,
 	output done,
 	input [7:0] din,
@@ -20,7 +21,8 @@ reg [2:0] bit_ct_d, bit_ct_q;
 reg [7:0] dout_d, dout_q;
 reg miso_d, miso_q;
 
-assign miso = ss ? 1'bZ : miso_q;
+assign miso_enable = ~ss;
+assign miso = miso_q;
 assign done = done_q;
 assign dout = dout_q;
 

embmicro
Site Admin
Posts: 834
Joined: March 24th, 2013, 12:45 pm

Re: using OBUFT for the spi miso

Post by embmicro » May 7th, 2013, 11:01 am

I noticed this as well. The problem occurs because there are two places I wanted the signal to be set to highZ. If ss is high it should be highZ and if the cclk detector isn't ready it should be highZ because the AVR isn't in slave mode yet and is still driving the pins. It's important to take both of these into account.

russm
Posts: 18
Joined: May 5th, 2013, 2:32 am

Re: using OBUFT for the spi miso

Post by russm » May 7th, 2013, 6:53 pm

embmicro wrote:It's important to take both of these into account.
Yeah, I get that.

Check the patch in my second comment. There, spi_slave doesn't tristate the miso output line but instead adds a miso_enable output (aka ~ss). Then up in avr_interface the condition that decides whether to pass miso through to the spi_miso pad or set spi_miso to hiZ changes from "ready" to "(ready & spi_miso_enable_m)". behaviour on the external pad is identical, but the implementation is simpler since there's no messing around with doing logic on tristate values.

Post Reply