This commit is contained in:
Peter McGoron 2022-10-23 04:27:28 -04:00
parent cff9cd967f
commit fe1139e02e
6 changed files with 121 additions and 7 deletions

View File

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

View File

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

4
spi_master_ss.v Normal file
View File

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

5
spi_master_ss_no_read.v Normal file
View File

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

5
spi_master_ss_no_write.v Normal file
View File

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

94
spi_master_ss_template.v Normal file
View File

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