diff --git a/spi_master.v b/spi_master.v index a69e15b..d1cf9e4 100644 --- a/spi_master.v +++ b/spi_master.v @@ -30,6 +30,7 @@ spi_master ) ( input clk, + input rst_L, `ifndef SPI_MASTER_NO_READ output reg [WID-1:0] from_slave, input miso, @@ -138,7 +139,18 @@ endtask initial ready_to_arm = 1; always @ (posedge clk) begin - case (state) + if (!rst_L) begin + idle_state(); + finished <= 0; + state <= WAIT_ON_ARM; + ready_to_arm <= 1; +`ifndef SPI_MASTER_NO_READ + from_slave <= 0; +`endif +`ifndef SPI_MASTER_NO_WRITE + send_buf <= 0; +`endif + end else case (state) WAIT_ON_ARM: begin `ifdef SIMULATION if (!ready_to_arm) diff --git a/spi_master_ss_template.v b/spi_master_ss_template.v index f231f70..6e4b970 100644 --- a/spi_master_ss_template.v +++ b/spi_master_ss_template.v @@ -17,6 +17,7 @@ module `SPI_MASTER_SS_NAME ) ( input clk, + input rst_L, `ifndef SPI_MASTER_NO_READ output [WID-1:0] from_slave, input miso, @@ -45,6 +46,7 @@ assign ss_L = !ss; .PHASE(PHASE) ) master ( .clk(clk), + .rst_L(rst_L), `ifndef SPI_MASTER_NO_READ .from_slave(from_slave), .miso(miso), @@ -72,7 +74,12 @@ task master_arm(); endtask always @ (posedge clk) begin - case (state) + if (!rst_L) begin + state <= WAIT_ON_ARM; + timer <= 0; + arm_master <= 0; + ss <= 0; + end else case (state) WAIT_ON_ARM: begin if (arm) begin timer <= 1; diff --git a/spi_slave.v b/spi_slave.v index c4f7a7c..de30a02 100644 --- a/spi_slave.v +++ b/spi_slave.v @@ -20,6 +20,7 @@ spi_slave ) ( input clk, + input rst_L, input sck, input ss_L, `ifndef SPI_SLAVE_NO_READ @@ -96,53 +97,69 @@ task check_counter(); endtask always @ (posedge clk) begin - sck_delay <= sck; - ss_delay <= ss; - - case ({ss_delay, ss}) - 2'b01: begin // rising edge of SS + if (!rst_L) begin + sck_delay <= 0; bit_counter <= 0; + ss_delay <= 0; + ready_at_start <= 0; +`ifndef SPI_SLAVE_NO_READ + from_master <= 0; +`endif +`ifndef SPI_SLAVE_NO_WRITE + miso <= 0; + send_buf <= 0; +`endif finished <= 0; err <= 0; - ready_at_start <= rdy; + end else begin + sck_delay <= sck; + ss_delay <= ss; - setup_bits(); - end - 2'b10: begin // falling edge - finished <= ready_at_start; - end - 2'b11: begin - case ({sck_delay, sck}) - 2'b01: begin // rising edge - if (PHASE == 1) begin - write_data(); - end else begin - read_data(); - end + case ({ss_delay, ss}) + 2'b01: begin // rising edge of SS + bit_counter <= 0; + finished <= 0; + err <= 0; + ready_at_start <= rdy; - if (POLARITY == 0) begin - check_counter(); - end + setup_bits(); end 2'b10: begin // falling edge - if (PHASE == 1) begin - read_data(); - end else begin - write_data(); - end - - if (POLARITY == 1) begin - check_counter(); - end + finished <= ready_at_start; + end + 2'b11: begin + case ({sck_delay, sck}) + 2'b01: begin // rising edge + if (PHASE == 1) begin + write_data(); + end else begin + read_data(); + end + + if (POLARITY == 0) begin + check_counter(); + end + end + 2'b10: begin // falling edge + if (PHASE == 1) begin + read_data(); + end else begin + write_data(); + end + + if (POLARITY == 1) begin + check_counter(); + end + end + default: ; + endcase + end + 2'b00: if (!rdy) begin + finished <= 0; + err <= 0; end - default: ; endcase end - 2'b00: if (!rdy) begin - finished <= 0; - err <= 0; - end - endcase end endmodule diff --git a/tests/simtop.v b/tests/simtop.v index 71981a8..1e6662a 100644 --- a/tests/simtop.v +++ b/tests/simtop.v @@ -12,6 +12,7 @@ module simtop parameter WID_LEN = 5 ) ( input clk, + input rst_L, `ifndef SPI_MASTER_NO_WRITE input [WID-1:0] master_to_slave, output [WID-1:0] from_master, @@ -62,6 +63,7 @@ reg slave_error; .WID_LEN(WID_LEN) ) master ( .clk(clk), + .rst_L(rst_L), `ifndef SPI_MASTER_NO_WRITE .to_slave(master_to_slave), .mosi(mosi), @@ -86,6 +88,7 @@ reg slave_error; .WID_LEN(WID_LEN) ) slave ( .clk(clk), + .rst_L(rst_L), .sck(sck), .ss_L(ss_L), `ifndef SPI_MASTER_NO_WRITE diff --git a/tests/write_read.cpp b/tests/write_read.cpp index 74a94ce..be02e57 100644 --- a/tests/write_read.cpp +++ b/tests/write_read.cpp @@ -31,6 +31,17 @@ static void progress_n(int f) { progress(); } +static void test_reset_pin(void) { + sim->rst_L = 0; + progress(); + sim->rdy = 1; + sim->activate = 1; + + progress_n(200); + assert(!sim->master_finished); + sim->rst_L = 1; +} + static void test_cross_transfer(unsigned m2s, unsigned s2m) { #ifndef SPI_MASTER_NO_WRITE sim->master_to_slave = m2s; @@ -39,6 +50,7 @@ static void test_cross_transfer(unsigned m2s, unsigned s2m) { sim->slave_to_master = s2m; #endif + sim->rst_L = 1; progress(); SET_SS(sim, 1); sim->rdy = 1; @@ -74,6 +86,19 @@ static void test_cross_transfer(unsigned m2s, unsigned s2m) { #endif } +static void test_interrupted(unsigned m2s, unsigned s2m) { + sim->rst_L = 1; + progress(); + + sim->rdy = 1; + sim->activate = 1; + progress_n(6); + sim->rst_L = 0; + progress_n(100); + sim->rst_L = 1; + test_cross_transfer(m2s, s2m); +} + int main(int argc, char **argv) { Verilated::commandArgs(argc, argv); Verilated::traceEverOn(true); @@ -84,13 +109,21 @@ int main(int argc, char **argv) { sim->activate = 0; sim->rdy = 0; + test_reset_pin(); test_cross_transfer(0b101010101010101010101010, 0b010101010101010101010101); test_cross_transfer(0b110011001100110011001100, 0b001100110011001100110011); + test_reset_pin(); for (int i = 0; i < 10000; i++) { unsigned m2s = rand() & ((1 << WID) - 1); unsigned s2m = rand() & ((1 << WID) - 1); - test_cross_transfer(m2s, s2m); + if (i % (((rand() + 1) % 32) + 1) == 0) + test_interrupted(m2s, s2m); + else + test_cross_transfer(m2s, s2m); + if (i % (((rand() + 1) % 64) + 1) == 0) + test_reset_pin(); + } sim->final();