add SS
This commit is contained in:
parent
cff9cd967f
commit
fe1139e02e
15
README.md
15
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
Loading…
Reference in New Issue