start cleanup of SPI
This commit is contained in:
parent
df6fe45d65
commit
90b74593e9
61
spi_master.v
61
spi_master.v
|
@ -1,4 +1,4 @@
|
||||||
/* (c) Peter McGoron 2022 v0.3
|
/* (c) Peter McGoron 2022 v0.4
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v.2.0. If a copy of the MPL was not distributed with this
|
* License, v.2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
@ -9,17 +9,9 @@
|
||||||
* the input).
|
* the input).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module
|
module spi_master #(
|
||||||
`ifdef SPI_MASTER_NO_READ
|
parameter ENABLE_MISO = 1, // Enable MISO and from_slave port
|
||||||
spi_master_no_read
|
parameter ENABLE_MOSI = 1, // Enable MOSI and to_slave port
|
||||||
`else
|
|
||||||
`ifdef SPI_MASTER_NO_WRITE
|
|
||||||
spi_master_no_write
|
|
||||||
`else
|
|
||||||
spi_master
|
|
||||||
`endif
|
|
||||||
`endif
|
|
||||||
#(
|
|
||||||
parameter WID = 24, // Width of bits per transaction.
|
parameter WID = 24, // Width of bits per transaction.
|
||||||
parameter WID_LEN = 5, // Length in bits required to store WID
|
parameter WID_LEN = 5, // Length in bits required to store WID
|
||||||
parameter CYCLE_HALF_WAIT = 1, // Half of the wait time of a cycle minus 1.
|
parameter CYCLE_HALF_WAIT = 1, // Half of the wait time of a cycle minus 1.
|
||||||
|
@ -27,25 +19,22 @@ spi_master
|
||||||
parameter TIMER_LEN = 3, // Length in bits required to store CYCLE_HALF_WAIT
|
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 POLARITY = 0, // 0 = sck idle low, 1 = sck idle high
|
||||||
parameter PHASE = 0 // 0 = rising-read falling-write, 1 = rising-write falling-read.
|
parameter PHASE = 0 // 0 = rising-read falling-write, 1 = rising-write falling-read.
|
||||||
)
|
) (
|
||||||
(
|
|
||||||
input clk,
|
input clk,
|
||||||
input rst_L,
|
input rst_L,
|
||||||
`ifndef SPI_MASTER_NO_READ
|
|
||||||
output reg [WID-1:0] from_slave,
|
output reg [WID-1:0] from_slave,
|
||||||
input miso,
|
input miso,
|
||||||
`endif
|
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
|
||||||
input [WID-1:0] to_slave,
|
input [WID-1:0] to_slave,
|
||||||
output reg mosi,
|
output reg mosi,
|
||||||
`endif
|
|
||||||
output reg sck_wire,
|
output reg sck_wire,
|
||||||
output reg finished,
|
output reg finished,
|
||||||
output reg ready_to_arm,
|
output reg ready_to_arm,
|
||||||
input arm
|
input arm
|
||||||
);
|
);
|
||||||
|
|
||||||
`ifndef SPI_MASTER_NO_READ
|
|
||||||
/* MISO is almost always an external wire, so buffer it.
|
/* MISO is almost always an external wire, so buffer it.
|
||||||
* This might not be necessary, since the master and slave do not respond
|
* This might not be necessary, since the master and slave do not respond
|
||||||
* immediately to changes in the wires, but this is just to be safe.
|
* immediately to changes in the wires, but this is just to be safe.
|
||||||
|
@ -56,11 +45,10 @@ spi_master
|
||||||
reg miso_hot = 0;
|
reg miso_hot = 0;
|
||||||
reg read_miso = 0;
|
reg read_miso = 0;
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) if (ENABLE_MISO) begin
|
||||||
read_miso <= miso_hot;
|
read_miso <= miso_hot;
|
||||||
miso_hot <= miso;
|
miso_hot <= miso;
|
||||||
end
|
end
|
||||||
`endif
|
|
||||||
|
|
||||||
parameter WAIT_ON_ARM = 0;
|
parameter WAIT_ON_ARM = 0;
|
||||||
parameter ON_CYCLE = 1;
|
parameter ON_CYCLE = 1;
|
||||||
|
@ -71,9 +59,7 @@ reg [1:0] state = WAIT_ON_ARM;
|
||||||
reg [WID_LEN-1:0] bit_counter = 0;
|
reg [WID_LEN-1:0] bit_counter = 0;
|
||||||
reg [TIMER_LEN-1:0] timer = 0;
|
reg [TIMER_LEN-1:0] timer = 0;
|
||||||
|
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
|
||||||
reg [WID-1:0] send_buf = 0;
|
reg [WID-1:0] send_buf = 0;
|
||||||
`endif
|
|
||||||
|
|
||||||
reg sck = 0;
|
reg sck = 0;
|
||||||
assign sck_wire = sck;
|
assign sck_wire = sck;
|
||||||
|
@ -84,25 +70,23 @@ task idle_state();
|
||||||
end else begin
|
end else begin
|
||||||
sck <= 1;
|
sck <= 1;
|
||||||
end
|
end
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
if (ENABLE_MOSI) mosi <= 0;
|
||||||
mosi <= 0;
|
|
||||||
`endif
|
|
||||||
timer <= 0;
|
timer <= 0;
|
||||||
bit_counter <= 0;
|
bit_counter <= 0;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task read_data();
|
task read_data();
|
||||||
`ifndef SPI_MASTER_NO_READ
|
if (ENABLE_MISO) begin
|
||||||
from_slave <= from_slave << 1;
|
from_slave <= from_slave << 1;
|
||||||
from_slave[0] <= read_miso;
|
from_slave[0] <= read_miso;
|
||||||
`endif
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task write_data();
|
task write_data();
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
if (ENABLE_MOSI) begin
|
||||||
mosi <= send_buf[WID-1];
|
mosi <= send_buf[WID-1];
|
||||||
send_buf <= send_buf << 1;
|
send_buf <= send_buf << 1;
|
||||||
`endif
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task setup_bits();
|
task setup_bits();
|
||||||
|
@ -113,15 +97,15 @@ task setup_bits();
|
||||||
* For mode 01 and mode 10, the first action is a WRITE.
|
* For mode 01 and mode 10, the first action is a WRITE.
|
||||||
*/
|
*/
|
||||||
if (POLARITY == PHASE) begin
|
if (POLARITY == PHASE) begin
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
if (ENABLE_MOSI) begin
|
||||||
mosi <= to_slave[WID-1];
|
mosi <= to_slave[WID-1];
|
||||||
send_buf <= to_slave << 1;
|
send_buf <= to_slave << 1;
|
||||||
`endif
|
end
|
||||||
state <= CYCLE_WAIT;
|
state <= CYCLE_WAIT;
|
||||||
end else begin
|
end else begin
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
if (ENABLE_MISO) begin
|
||||||
send_buf <= to_slave;
|
send_buf <= to_slave;
|
||||||
`endif
|
end
|
||||||
state <= ON_CYCLE;
|
state <= ON_CYCLE;
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
@ -144,12 +128,8 @@ always @ (posedge clk) begin
|
||||||
finished <= 0;
|
finished <= 0;
|
||||||
state <= WAIT_ON_ARM;
|
state <= WAIT_ON_ARM;
|
||||||
ready_to_arm <= 1;
|
ready_to_arm <= 1;
|
||||||
`ifndef SPI_MASTER_NO_READ
|
if (ENABLE_MISO) from_slave <= 0;
|
||||||
from_slave <= 0;
|
if (ENABLE_MOSI) send_buf <= 0;
|
||||||
`endif
|
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
|
||||||
send_buf <= 0;
|
|
||||||
`endif
|
|
||||||
end else case (state)
|
end else case (state)
|
||||||
WAIT_ON_ARM: begin
|
WAIT_ON_ARM: begin
|
||||||
`ifdef SIMULATION
|
`ifdef SIMULATION
|
||||||
|
@ -225,4 +205,3 @@ always @ (posedge clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
`undefineall
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
`define SPI_MASTER_NO_READ
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
`include "spi_master.v"
|
|
|
@ -1,3 +0,0 @@
|
||||||
`define SPI_MASTER_NO_WRITE
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
`include "spi_master.v"
|
|
|
@ -1,4 +0,0 @@
|
||||||
`define SPI_MASTER_SS_NAME spi_master_ss
|
|
||||||
`define SPI_MASTER_NAME spi_master
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
`include "spi_master_ss_template.v"
|
|
|
@ -1,5 +0,0 @@
|
||||||
`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"
|
|
|
@ -1,5 +0,0 @@
|
||||||
`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"
|
|
|
@ -1,36 +1,39 @@
|
||||||
/* (c) Peter McGoron 2022 v0.3
|
/* (c) Peter McGoron 2022 v0.4
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v.2.0. If a copy of the MPL was not distributed with this
|
* License, v.2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* spi master with integrated ability to wait a certain amount of cycles
|
/* spi master with integrated ability to wait a certain amount of cycles
|
||||||
* after activating SS.
|
* after activating SS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module `SPI_MASTER_SS_NAME
|
module spi_master_ss
|
||||||
#(
|
#(
|
||||||
|
parameter SS_WAIT = 1, /* Amount of cycles to wait for SS
|
||||||
|
to enable */
|
||||||
|
parameter SS_WAIT_TIMER_LEN = 2, /* Amount of bits required to
|
||||||
|
store the SS wait time */
|
||||||
|
|
||||||
|
parameter ENABLE_MISO = 1,
|
||||||
|
parameter ENABLE_MOSI = 1,
|
||||||
parameter WID = 24,
|
parameter WID = 24,
|
||||||
parameter WID_LEN = 5,
|
parameter WID_LEN = 5,
|
||||||
parameter CYCLE_HALF_WAIT = 1,
|
parameter CYCLE_HALF_WAIT = 1,
|
||||||
parameter TIMER_LEN = 3,
|
parameter TIMER_LEN = 3,
|
||||||
|
|
||||||
parameter SS_WAIT = 1,
|
|
||||||
parameter SS_WAIT_TIMER_LEN = 2,
|
|
||||||
|
|
||||||
parameter POLARITY = 0,
|
parameter POLARITY = 0,
|
||||||
parameter PHASE = 0
|
parameter PHASE = 0
|
||||||
)
|
) (
|
||||||
(
|
|
||||||
input clk,
|
input clk,
|
||||||
input rst_L,
|
input rst_L,
|
||||||
`ifndef SPI_MASTER_NO_READ
|
|
||||||
output [WID-1:0] from_slave,
|
output [WID-1:0] from_slave,
|
||||||
input miso,
|
input miso,
|
||||||
`endif
|
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
|
||||||
input [WID-1:0] to_slave,
|
input [WID-1:0] to_slave,
|
||||||
output reg mosi,
|
output reg mosi,
|
||||||
`endif
|
|
||||||
output sck_wire,
|
output sck_wire,
|
||||||
output finished,
|
output finished,
|
||||||
output ready_to_arm,
|
output ready_to_arm,
|
||||||
|
@ -42,7 +45,9 @@ reg ss = 0;
|
||||||
reg arm_master = 0;
|
reg arm_master = 0;
|
||||||
assign ss_L = !ss;
|
assign ss_L = !ss;
|
||||||
|
|
||||||
`SPI_MASTER_NAME #(
|
spi_master #(
|
||||||
|
.ENABLE_MISO(ENABLE_MISO),
|
||||||
|
.ENABLE_MOSI(ENABLE_MOSI),
|
||||||
.WID(WID),
|
.WID(WID),
|
||||||
.WID_LEN(WID_LEN),
|
.WID_LEN(WID_LEN),
|
||||||
.CYCLE_HALF_WAIT(CYCLE_HALF_WAIT),
|
.CYCLE_HALF_WAIT(CYCLE_HALF_WAIT),
|
||||||
|
@ -52,14 +57,13 @@ assign ss_L = !ss;
|
||||||
) master (
|
) master (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_L(rst_L),
|
.rst_L(rst_L),
|
||||||
`ifndef SPI_MASTER_NO_READ
|
|
||||||
.from_slave(from_slave),
|
.from_slave(from_slave),
|
||||||
.miso(miso),
|
.miso(miso),
|
||||||
`endif
|
|
||||||
`ifndef SPI_MASTER_NO_WRITE
|
|
||||||
.to_slave(to_slave),
|
.to_slave(to_slave),
|
||||||
.mosi(mosi),
|
.mosi(mosi),
|
||||||
`endif
|
|
||||||
.sck_wire(sck_wire),
|
.sck_wire(sck_wire),
|
||||||
.finished(finished),
|
.finished(finished),
|
||||||
.ready_to_arm(ready_to_arm),
|
.ready_to_arm(ready_to_arm),
|
||||||
|
@ -120,4 +124,3 @@ always @ (posedge clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
`undefineall
|
|
||||||
|
|
52
spi_slave.v
52
spi_slave.v
|
@ -1,51 +1,41 @@
|
||||||
/* (c) Peter McGoron 2022 v0.3
|
/* (c) Peter McGoron 2022 v0.4
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v.2.0. If a copy of the MPL was not distributed with this
|
* License, v.2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module
|
module spi_slave #(
|
||||||
`ifdef SPI_SLAVE_NO_READ
|
parameter ENABLE_MISO = 1, // Enable MISO and to_master port
|
||||||
spi_slave_no_read
|
parameter ENABLE_MOSI = 1, // Enable MOSI and from_master port
|
||||||
`elsif SPI_SLAVE_NO_WRITE
|
|
||||||
spi_slave_no_write
|
|
||||||
`else
|
|
||||||
spi_slave
|
|
||||||
`endif
|
|
||||||
#(
|
|
||||||
parameter WID = 24, // Width of bits per transaction.
|
parameter WID = 24, // Width of bits per transaction.
|
||||||
parameter WID_LEN = 5, // Length in bits required to store WID
|
parameter WID_LEN = 5, // Length in bits required to store WID
|
||||||
parameter POLARITY = 0,
|
parameter POLARITY = 0,
|
||||||
parameter PHASE = 0 // 0 = rising-read falling-write, 1 = rising-write falling-read.
|
parameter PHASE = 0 // 0 = rising-read falling-write, 1 = rising-write falling-read.
|
||||||
)
|
) (
|
||||||
(
|
|
||||||
input clk,
|
input clk,
|
||||||
input rst_L,
|
input rst_L,
|
||||||
input sck,
|
input sck,
|
||||||
input ss_L,
|
input ss_L,
|
||||||
`ifndef SPI_SLAVE_NO_READ
|
|
||||||
output reg [WID-1:0] from_master,
|
output reg [WID-1:0] from_master,
|
||||||
input mosi,
|
input mosi,
|
||||||
`endif
|
|
||||||
`ifndef SPI_SLAVE_NO_WRITE
|
|
||||||
input [WID-1:0] to_master,
|
input [WID-1:0] to_master,
|
||||||
output reg miso,
|
output reg miso,
|
||||||
`endif
|
|
||||||
output reg finished,
|
output reg finished,
|
||||||
input rdy,
|
input rdy,
|
||||||
output reg err
|
output reg err
|
||||||
);
|
);
|
||||||
|
|
||||||
`ifndef SPI_SLAVE_NO_READ
|
|
||||||
/* MOSI is almost always an external wire, so buffer it. */
|
/* MOSI is almost always an external wire, so buffer it. */
|
||||||
reg mosi_hot = 0;
|
reg mosi_hot = 0;
|
||||||
reg read_mosi = 0;
|
reg read_mosi = 0;
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) if (ENABLE_MOSI) begin
|
||||||
read_mosi <= mosi_hot;
|
read_mosi <= mosi_hot;
|
||||||
mosi_hot <= mosi;
|
mosi_hot <= mosi;
|
||||||
end
|
end
|
||||||
`endif
|
|
||||||
|
|
||||||
wire ss = !ss_L;
|
wire ss = !ss_L;
|
||||||
reg sck_delay = 0;
|
reg sck_delay = 0;
|
||||||
|
@ -58,21 +48,21 @@ reg [WID-1:0] send_buf = 0;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
task read_data();
|
task read_data();
|
||||||
`ifndef SPI_SLAVE_NO_READ
|
if (ENABLE_MOSI) begin
|
||||||
from_master <= from_master << 1;
|
from_master <= from_master << 1;
|
||||||
from_master[0] <= read_mosi;
|
from_master[0] <= read_mosi;
|
||||||
`endif
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task write_data();
|
task write_data();
|
||||||
`ifndef SPI_SLAVE_NO_WRITE
|
if (ENABLE_MISO) begin
|
||||||
send_buf <= send_buf << 1;
|
send_buf <= send_buf << 1;
|
||||||
miso <= send_buf[WID-1];
|
miso <= send_buf[WID-1];
|
||||||
`endif
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task setup_bits();
|
task setup_bits();
|
||||||
`ifndef SPI_SLAVE_NO_WRITE
|
if (ENABLE_MISO) begin
|
||||||
/* at Mode 00, the transmission starts with
|
/* at Mode 00, the transmission starts with
|
||||||
* a rising edge, and at mode 11, it starts with a falling
|
* a rising edge, and at mode 11, it starts with a falling
|
||||||
* edge. For both modes, these are READs.
|
* edge. For both modes, these are READs.
|
||||||
|
@ -85,7 +75,7 @@ task setup_bits();
|
||||||
end else begin
|
end else begin
|
||||||
send_buf <= to_master;
|
send_buf <= to_master;
|
||||||
end
|
end
|
||||||
`endif
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task check_counter();
|
task check_counter();
|
||||||
|
@ -102,13 +92,14 @@ always @ (posedge clk) begin
|
||||||
bit_counter <= 0;
|
bit_counter <= 0;
|
||||||
ss_delay <= 0;
|
ss_delay <= 0;
|
||||||
ready_at_start <= 0;
|
ready_at_start <= 0;
|
||||||
`ifndef SPI_SLAVE_NO_READ
|
|
||||||
from_master <= 0;
|
if (ENABLE_MOSI) from_master <= 0;
|
||||||
`endif
|
|
||||||
`ifndef SPI_SLAVE_NO_WRITE
|
if (ENABLE_MISO) begin
|
||||||
miso <= 0;
|
miso <= 0;
|
||||||
send_buf <= 0;
|
send_buf <= 0;
|
||||||
`endif
|
end
|
||||||
|
|
||||||
finished <= 0;
|
finished <= 0;
|
||||||
err <= 0;
|
err <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -163,4 +154,3 @@ always @ (posedge clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
`undefineall
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
`define SPI_SLAVE_NO_READ
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
`include "spi_slave.v"
|
|
|
@ -1,3 +0,0 @@
|
||||||
`define SPI_SLAVE_NO_WRITE
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
`include "spi_slave.v"
|
|
Loading…
Reference in New Issue