// -*-verilog-*- // spi.v - An implementation of SPI // Author: Ben Doherty // Documentation: None. Sorry. This follows a standard SPI // protocol. the rdState and reg_rddata outputs are simply for debugging // and can be removed to reduce resource usage. module SPI(SPI_ss, SPI_clk, SPI_mosi, SPI_miso, REG_addr, REG_al, REG_wr, REG_wrdata, REG_rddata, // TESTING rdState,reg_rddata ); // SPI Inputs input SPI_ss, SPI_clk, SPI_mosi; // SPI Output output SPI_miso; wire SPI_miso; reg spi_miso; assign SPI_miso = spi_miso; // DEBUGGING OUTPUTS output [7:0] rdState; output [31:0] reg_rddata; // Register address (0..63) output [5:0] REG_addr; wire [5:0] REG_addr; reg [5:0] reg_addr; assign REG_addr = reg_addr; // Read port from register file, latched in // after address is given and then serialized // on SPI_miso input [31:0] REG_rddata; reg [31:0] reg_rddata; // Write port to register file output[31:0] REG_wrdata; wire [31:0] REG_wrdata; reg [31:0] reg_wrdata; assign REG_wrdata = reg_wrdata; // Register address and write latch lines output REG_al; wire REG_al; reg reg_al; assign REG_al = reg_al; output REG_wr; wire REG_wr; reg reg_wr; assign REG_wr = reg_wr; // Loading state reg [7:0] rdState; // Shift register reg [31:0] SHIFTREG; // Read/write flag 1=write reg rw; // This block sets the requirement that SPI_clk // must make a negative transition while SPI_ss // remains high in order to reset the state always @(SPI_ss or SPI_clk) begin if(SPI_ss == 1'b0) rdState <= rdState + 1; else if(SPI_ss == 1'b1) begin reg_rddata <= 0; rdState <= 0; end // if(rdState < 12) begin // reg_al <= 1'b0; // end // else if(rdState == 13) begin // // Latch in address // reg_al <= 1'b1; // reg_rddata <= REG_rddata; // end // else if(rdState <= 77) begin // reg_al <= 1'b0; // end end always @(rdState) begin if(rdState == 0) begin SHIFTREG = 32'h00_00_00_00; reg_al <= 1'b0; reg_wr <= 1'b0; end else if(rdState == 13) begin reg_al <= 1'b1; reg_wr <= 1'b0; end else if(rdState == 79) begin reg_al <= 1'b0; reg_wr <= 1'b1 & rw; end else if(rdState[0] == 0) begin reg_al <= 1'b0; reg_wr <= 1'b0; // Even states will occur on rising // transitions: we shift in/out values here if(rdState <= 12) begin // sequential statements here necessary // to get value from SHIFTREG into reg_addr // immediately after shift SHIFTREG[5:1] = SHIFTREG[4:0]; SHIFTREG[0] = SPI_mosi; if(rdState == 12) begin reg_addr = SHIFTREG[5:0]; SHIFTREG = 32'h00_00_00_00; end end // if (rdState <= 12) else if(rdState == 14) begin // We decide here whether we're // doing a read or a write: // 0 = read, // 1 = write rw <= SPI_mosi; if(SPI_mosi == 0) // Doing a read: load in REG_rddata reg_rddata <= REG_rddata; end else if(rdState <= 78) begin if(rw == 0) begin reg_rddata[31:1] <= reg_rddata[30:0]; spi_miso <= reg_rddata[31]; end else begin SHIFTREG[31:1] = SHIFTREG[30:0]; SHIFTREG[0] = SPI_mosi; if(rdState == 78) reg_wrdata = SHIFTREG; end end end // if (rdState[0] == 0) end // always @ (rdState) endmodule // spi