// // Chuck Benz ASIC & FPGA Design // // CGSS: Chuck's generic SPI slave core module cbaf_cgss ( input spi_clk, input rstl, input spi_select, input mosi, output reg miso, input [7:0] status1, output reg [7:0] control1 ); parameter ADDR_WIDTH = 8, DATA_WIDTH = 8 ; reg [127:0] shift_in ; // over-sized, synth will trim. reg [7:0] command ; reg [ADDR_WIDTH-1:0] addr ; reg [ADDR_WIDTH-1:0] addr_D ; reg [DATA_WIDTH-1:0] wr_data ; reg [DATA_WIDTH-1:0] rd_data_D ; reg [7:0] spi_counter ; reg [7:0] shift_out ; reg spi_selectQ ; reg mosiQ ; always @ (*) begin addr_D = addr ; if (spi_counter == (6 + ADDR_WIDTH)) addr_D[ADDR_WIDTH-1:1] = {shift_in[ADDR_WIDTH-3:0], mosiQ} ; if (spi_counter == (7 + ADDR_WIDTH)) addr_D[0] = mosiQ ; rd_data_D = 0 ; case ({addr[ADDR_WIDTH-1:1], addr_D[0]}) 0: rd_data_D = control1 ; 1: rd_data_D = status1 ; endcase end always @ (negedge spi_clk or negedge rstl) if (~rstl) miso <= 0 ; else miso <= (command[0] == 0) && (spi_selectQ == 0) && // send msbit of rd data ((rd_data_D[DATA_WIDTH-1] && (spi_counter ==(7+ADDR_WIDTH))) || // and the rest of the rd data shift_out[DATA_WIDTH-2]) ; always @ (posedge spi_clk or negedge rstl) if (~rstl) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops addr <= {(1+(ADDR_WIDTH-1)){1'b0}}; command <= 8'h0; control1 <= 8'h0; mosiQ <= 1'h0; shift_in <= 128'h0; shift_out <= 8'h0; spi_counter <= 8'h0; spi_selectQ <= 1'h0; // End of automatics end else begin // ensure use of IOB flops on SS and MOSI spi_selectQ <= spi_select ; mosiQ <= mosi ; shift_in <= {shift_in, mosiQ} ; addr <= addr_D ; if (spi_counter == 8) command <= shift_in[7:0] ; if (spi_selectQ) spi_counter <= 0 ; else if (~spi_selectQ && (spi_counter == 0)) begin spi_counter <= 1 ; end else begin // spi_selectQ is 0, spi_counter is already counting if (spi_counter == (7 + ADDR_WIDTH + DATA_WIDTH)) spi_counter <= 8 + ADDR_WIDTH ; else spi_counter <= spi_counter + 1 ; end if (command[0] && (spi_selectQ == 0) && (spi_counter == (7 + ADDR_WIDTH + DATA_WIDTH))) case (addr) 0: control1 <= {shift_in, mosiQ} ; endcase if (spi_counter == (7 + ADDR_WIDTH)) shift_out <= rd_data_D ; else shift_out <= shift_out << 1 ; end endmodule