aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2022-10-23 14:03:19 -0400
committerGravatar Peter McGoron 2022-10-23 14:03:19 -0400
commit9bbe1407bae7b4aeca46dbba30814a9962cce670 (patch)
treececd07b7289e84afa02f9b7e146ca0a6103148d9
parenttest master with SS (diff)
add metastability workaround
-rw-r--r--spi_master.v19
-rw-r--r--spi_slave.v15
2 files changed, 30 insertions, 4 deletions
diff --git a/spi_master.v b/spi_master.v
index d6018c0..82e5ee8 100644
--- a/spi_master.v
+++ b/spi_master.v
@@ -4,6 +4,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
+/* CYCLE_HALF_WAIT should take into account the setup time of the slave
+ * device, and also master buffering (MISO is one cycle off to stabilize
+ * the input).
+ */
+
module
`ifdef SPI_MASTER_NO_READ
spi_master_no_read
@@ -14,7 +19,6 @@ spi_master_no_write
spi_master
`endif
`endif
-
#(
parameter WID = 24, // Width of bits per transaction.
parameter WID_LEN = 5, // Length in bits required to store WID
@@ -39,6 +43,17 @@ spi_master
input arm
);
+`ifndef SPI_MASTER_NO_READ
+/* MISO is almost always an external wire, so buffer it. */
+reg miso_hot = 0;
+reg read_miso = 0;
+
+always @ (posedge clk) begin
+ read_miso <= miso_hot;
+ miso_hot <= miso;
+end
+`endif
+
parameter WAIT_ON_ARM = 0;
parameter ON_CYCLE = 1;
parameter CYCLE_WAIT = 2;
@@ -71,7 +86,7 @@ endtask
task read_data();
`ifndef SPI_MASTER_NO_READ
from_slave <= from_slave << 1;
- from_slave[0] <= miso;
+ from_slave[0] <= read_miso;
`endif
endtask
diff --git a/spi_slave.v b/spi_slave.v
index 83ab335..c4f7a7c 100644
--- a/spi_slave.v
+++ b/spi_slave.v
@@ -24,7 +24,7 @@ spi_slave
input ss_L,
`ifndef SPI_SLAVE_NO_READ
output reg [WID-1:0] from_master,
- input reg mosi,
+ input mosi,
`endif
`ifndef SPI_SLAVE_NO_WRITE
input [WID-1:0] to_master,
@@ -35,6 +35,17 @@ spi_slave
output reg err
);
+`ifndef SPI_SLAVE_NO_READ
+/* MOSI is almost always an external wire, so buffer it. */
+reg mosi_hot = 0;
+reg read_mosi = 0;
+
+always @ (posedge clk) begin
+ read_mosi <= mosi_hot;
+ mosi_hot <= mosi;
+end
+`endif
+
wire ss = !ss_L;
reg sck_delay = 0;
reg [WID_LEN-1:0] bit_counter = 0;
@@ -48,7 +59,7 @@ reg [WID-1:0] send_buf = 0;
task read_data();
`ifndef SPI_SLAVE_NO_READ
from_master <= from_master << 1;
- from_master[0] <= mosi;
+ from_master[0] <= read_mosi;
`endif
endtask