From 9bbe1407bae7b4aeca46dbba30814a9962cce670 Mon Sep 17 00:00:00 2001 From: Peter McGoron Date: Sun, 23 Oct 2022 14:03:19 -0400 Subject: [PATCH] add metastability workaround --- spi_master.v | 19 +++++++++++++++++-- spi_slave.v | 15 +++++++++++++-- 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