diff options
| author | 2022-07-20 19:41:54 -0400 | |
|---|---|---|
| committer | 2022-07-20 19:41:54 -0400 | |
| commit | 6f000b64ec96dcdd0176533a62536deddc2d97a6 (patch) | |
| tree | 7db2c55a4b7c4cf74ab840faf1797a71349ab69b /spi_master.v | |
start spi master and slave with testbench
Diffstat (limited to 'spi_master.v')
| -rw-r--r-- | spi_master.v | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/spi_master.v b/spi_master.v new file mode 100644 index 0000000..7bb8db1 --- /dev/null +++ b/spi_master.v @@ -0,0 +1,126 @@ +module 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 = 3, // Half of the wait time of a cycle + 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. +) +( + input clk, +`ifndef SPI_MASTER_NO_READ + output reg [WID-1:0] from_slave, + input miso, +`endif +`ifndef SPI_MASTER_NO_WRITE + input [WID-1:0] to_slave, + output mosi, +`endif + output sck_wire, + output finished, + input arm +); + +parameter WAIT_ON_ARM = 0; +parameter ON_CYCLE = 1; +parameter CYCLE_WAIT = 2; +parameter WAIT_FINISHED = 3; + +reg [1:0] state = WAIT_ON_ARM; +reg [WID_LEN-1:0] bit_counter = 0; +reg [TIMER_LEN-1:0] timer = 0; + +`ifndef SPI_MASTER_NO_WRITE +reg [WID-1:0] send_buf = 0; +`endif + +reg sck = 0; +assign sck_wire = sck; + +task idle_state(); + if (POLARITY == 0) begin + sck <= 0; + end else begin + sck <= 1; + end +`ifndef SPI_MASTER_NO_WRITE + mosi <= 0; +`endif + timer <= 0; + bit_counter <= 0; +endtask + +task read_data(); +`ifndef SPI_MASTER_NO_READ + from_slave <= from_slave << 1; + from_slave[0] <= miso; +`endif +endtask + +task write_data(); +`ifndef SPI_MASTER_NO_WRITE + mosi <= send_buf[WID-1]; + send_buf <= send_buf << 1; +`endif +endtask + +always @ (posedge clk) begin + case (state) + WAIT_ON_ARM: begin + if (!arm) begin + idle_state(); + finished <= 0; + end else begin + state <= ON_CYCLE; + send_buf <= to_slave; + end + end + ON_CYCLE: begin + if (sck) begin // rising edge + if (PHASE == 1) begin + write_data(); + end else begin + read_data(); + end + + if (POLARITY == 1) begin + bit_counter <= bit_counter + 1; + end + end else begin // falling edge + if (PHASE == 1) begin + read_data(); + end else begin + write_data(); + end + + if (POLARITY == 0) begin + bit_counter <= bit_counter + 1; + end + end + state <= CYCLE_WAIT; + end + CYCLE_WAIT: begin + if (timer == CYCLE_HALF_WAIT) begin + timer <= 0; + if (bit_counter == WID) begin + state <= WAIT_FINISHED; + end else begin + state <= ON_CYCLE; + sck <= !sck; + end + end else begin + timer <= timer + 1; + end + end + WAIT_FINISHED: begin + finished <= 1; + idle_state(); + if (!arm) begin + state <= WAIT_ON_ARM; + end + end + endcase +end + +endmodule |
