aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2022-10-23 04:27:28 -0400
committerGravatar Peter McGoron 2022-10-23 04:27:28 -0400
commitfe1139e02e247c023bc594376117220fe35d180c (patch)
tree4b936c8a712603feb740af24006f51c8f78fda8d
parentbump version (diff)
add SS
-rw-r--r--README.md15
-rw-r--r--spi_master.v5
-rw-r--r--spi_master_ss.v4
-rw-r--r--spi_master_ss_no_read.v5
-rw-r--r--spi_master_ss_no_write.v5
-rw-r--r--spi_master_ss_template.v94
6 files changed, 121 insertions, 7 deletions
diff --git a/README.md b/README.md
index 6fdee35..6570060 100644
--- a/README.md
+++ b/README.md
@@ -14,14 +14,17 @@ and the CERN-OHL-W v2.0 (or any later version).
## Tests
-Go into `tests` and run `make`. To rerun tests, run `make clean` followed
-by `make`.
+Run `./mk.sh` in `tests/` to generate and run tests.
-The test for each mode generates a `.vcd` file which you may view using
-[GTKWave][1]. You can use this to gauge which SPI mode is appropriate for
-your device.
+## Modules
-[1]: https://gtkwave.sourceforge.net/
+"master_no_read" and "slave_no_write" have no Master In, Slave Out ("miso")
+wires (and no corresponding shift registers), while "master_no_write"
+and "slave_no_read" have no Master Out, Slave In ("mosi") wires. This
+is for compatability for "SPI compatible" devices that are read only.
+
+"master_ss" and others include a timer that will assert the Slave Select
+pin and wait a set number of clock cycles before starting the SPI transfer.
## SPI Modes
diff --git a/spi_master.v b/spi_master.v
index 053686f..d8b9020 100644
--- a/spi_master.v
+++ b/spi_master.v
@@ -18,7 +18,9 @@ spi_master
#(
parameter WID = 24, // Width of bits per transaction.
parameter WID_LEN = 5, // Length in bits required to store WID
- parameter CYCLE_HALF_WAIT = 1, // Half of the wait time of a cycle
+ parameter CYCLE_HALF_WAIT = 1, // One less than half of the wait time of a cycle.
+ // One cycle of a transfer is 2(CYCLE_HALF_WAIT + 1)
+ // clock cycles.
parameter TIMER_LEN = 3, // Length in bits required to store CYCLE_HALF_WAIT
parameter POLARITY = 0, // 0 = sck idle low, 1 = sck idle high
parameter PHASE = 0 // 0 = rising-read falling-write, 1 = rising-write falling-read.
@@ -134,6 +136,7 @@ always @ (posedge clk) begin
bit_counter <= bit_counter + 1;
end
end
+
state <= CYCLE_WAIT;
end
CYCLE_WAIT: begin
diff --git a/spi_master_ss.v b/spi_master_ss.v
new file mode 100644
index 0000000..6dc3429
--- /dev/null
+++ b/spi_master_ss.v
@@ -0,0 +1,4 @@
+`define SPI_MASTER_SS_NAME spi_master_ss
+`define SPI_MASTER_NAME spi_master
+/* verilator lint_off DECLFILENAME */
+`include "spi_master_ss_template.v"
diff --git a/spi_master_ss_no_read.v b/spi_master_ss_no_read.v
new file mode 100644
index 0000000..741e940
--- /dev/null
+++ b/spi_master_ss_no_read.v
@@ -0,0 +1,5 @@
+`define SPI_MASTER_SS_NAME spi_master_ss_no_read
+`define SPI_MASTER_NAME spi_master_no_read
+`define SPI_MASTER_NO_READ
+/* verilator lint_off DECLFILENAME */
+`include "spi_master_ss_template.v"
diff --git a/spi_master_ss_no_write.v b/spi_master_ss_no_write.v
new file mode 100644
index 0000000..9be3e7f
--- /dev/null
+++ b/spi_master_ss_no_write.v
@@ -0,0 +1,5 @@
+`define SPI_MASTER_SS_NAME spi_master_ss_no_write
+`define SPI_MASTER_NAME spi_master_no_write
+`define SPI_MASTER_NO_WRITE
+/* verilator lint_off DECLFILENAME */
+`include "spi_master_ss_template.v"
diff --git a/spi_master_ss_template.v b/spi_master_ss_template.v
new file mode 100644
index 0000000..eeaf01c
--- /dev/null
+++ b/spi_master_ss_template.v
@@ -0,0 +1,94 @@
+/* spi master with integrated ability to wait a certain amount of cycles
+ * after activating SS.
+ */
+
+module `SPI_MASTER_SS_NAME
+#(
+ parameter WID = 24,
+ parameter WID_LEN = 5,
+ parameter CYCLE_HALF_WAIT = 1,
+ parameter CYCLE_HALF_WAIT_TIMER_LEN = 3,
+
+ parameter SS_WAIT = 1,
+ parameter SS_WAIT_TIMER_LEN = 2,
+
+ parameter POLARITY = 0,
+ parameter PHASE = 0
+)
+(
+ input clk,
+`ifndef SPI_MASTER_NO_READ
+ output [WID-1:0] from_slave,
+ input miso,
+`endif
+`ifndef SPI_MASTER_NO_WRITE
+ input [WID-1:0] to_slave,
+ output reg mosi,
+`endif
+ output sck_wire,
+ output finished,
+ output ss_L,
+ input arm
+);
+
+reg ss = 0;
+reg arm_master = 0;
+assign ss_L = ss;
+
+`SPI_MASTER_NAME #(
+ .WID(WID),
+ .WID_LEN(WID_LEN),
+ .CYCLE_HALF_WAIT(CYCLE_HALF_WAIT),
+ .TIMER_LEN(CYCLE_HALF_WAIT_TIMER_LEN),
+ .POLARITY(POLARITY),
+ .PHASE(PHASE)
+) master (
+ .clk(clk),
+`ifndef SPI_MASTER_NO_READ
+ .from_slave(from_slave),
+ .miso(miso),
+`endif
+`ifndef SPI_MASTER_NO_WRITE
+ .to_slave(to_slave),
+ .mosi(mosi),
+`endif
+ .sck_wire(sck_wire),
+ .finished(finished),
+ .arm(arm_master)
+);
+
+localparam WAIT_ON_ARM = 0;
+localparam WAIT_ON_SS = 1;
+localparam WAIT_ON_MASTER = 2;
+localparam WAIT_ON_ARM_DEASSERT = 3;
+reg [2:0] state = WAIT_ON_ARM;
+
+always @ (posedge clk) begin
+ case (state)
+ WAIT_ON_ARM: begin
+ if (arm) begin
+ timer <= 1;
+ state <= WAIT_ON_SS;
+ ss <= 1;
+ end
+ end
+ WAIT_ON_SS: begin
+ if (timer == SS_WAIT) begin
+ arm_master <= 1;
+ state <= WAIT_ON_MASTER;
+ end
+ end
+ WAIT_ON_MASTER: begin
+ if (finished) begin
+ state <= WAIT_ON_ARM_DEASSERT;
+ end
+ end
+ WAIT_ON_ARM_DEASSERT: begin
+ if (!arm) begin
+ state <= WAIT_ON_ARM;
+ arm_master <= 0;
+ end
+ end
+end
+
+endmodule