`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 17.09.2020 14:18:14 // Design Name: // Module Name: SlaveSpi // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module SlaveSpi #( parameter CmdRegWidth = 32, parameter DataCntWidth = 6, parameter HeaderWidth = 7, parameter CmdDataRegWith = 24, parameter Adc0DirAccessAddr = 7'h13, parameter Adc1DirAccessAddr = 7'h14 ) ( input Clk_i, input Rst_i, output reg [CmdRegWidth-1:0] Data_o, output reg Val_o, //----------------------------------- //input Spi lines from ext. Dsp input Mosi_i, input Sck_i, input Ss_i, //----------------------------------- //----------------------------------- output Mosi_o, output Sck_o, output Ss0_o, output Ss1_o, //----------------------------------- output [HeaderWidth-1:0] AnsAddr_o, input [CmdDataRegWith-1:0] AnsReg_i, input Miso_i, output Miso_o ); //================================================================================ // REG/WIRE //================================================================================ reg [CmdRegWidth-1:0] dataCaptReg; reg [DataCntWidth-1:0] dataCnt; reg [HeaderWidth-1:0] ansAddr; reg spiMode; wire directTransit = (ansAddr == Adc0DirAccessAddr)|(ansAddr == Adc1DirAccessAddr); reg txWind; reg [4:0] txCnt; //================================================================================ // ASSIGNMENTS //================================================================================ assign Mosi_o = (!spiMode&directTransit)? Mosi_i:1'b1; assign Sck_o = (directTransit)? Sck_i:1'b0; assign Ss0_o = (directTransit&&(ansAddr==Adc0DirAccessAddr))? Ss_i:1'b1; assign Ss1_o = (directTransit&&(ansAddr==Adc1DirAccessAddr))? Ss_i:1'b1; assign AnsAddr_o = ansAddr; assign Miso_o = txWind? AnsReg_i[txCnt]:1'b0; //================================================================================ // CODING //================================================================================ always @(posedge Sck_i) begin if (~Ss_i) begin dataCaptReg <= {dataCaptReg[CmdRegWidth-2:0],Mosi_i}; end else begin dataCaptReg <= dataCaptReg; end end always @(posedge Sck_i) begin if (~Rst_i) begin if (~Ss_i) begin dataCnt <= dataCnt + 5'd1; end end else begin dataCnt <= 0; end end always @(posedge Sck_i) begin if (~Rst_i) begin if (dataCnt == 5'd1) begin if (dataCaptReg[CmdRegWidth-CmdRegWidth]) begin spiMode <= 1'b1; end else begin spiMode <= 1'b0; end end end else begin spiMode <= 1'b0; end end always @(negedge Sck_i) begin if (~Rst_i) begin if (~Ss_i) begin if (dataCnt == 5'd8) begin ansAddr <= dataCaptReg[CmdRegWidth-26-:HeaderWidth]; end else if (dataCnt == 5'd0) begin ansAddr <= 7'h7F; end end else begin ansAddr <= 7'h7F; end end else begin ansAddr <= 7'h7F; end end //================================================================================ // Generating output signals //================================================================================ reg ssReg; reg ssRegR; always @(posedge Clk_i) begin ssReg <= Ss_i; ssRegR <= ssReg; end reg ssPos; always @(posedge Clk_i) begin ssPos <= ssReg&!ssRegR; end always @(posedge Clk_i) begin if (!directTransit&!spiMode) begin if (ssReg&!ssRegR) begin Val_o <= 1'b1; end else begin Val_o <= 0; end end end always @(posedge Clk_i) begin if (((ansAddr != Adc0DirAccessAddr)|(ansAddr != Adc1DirAccessAddr))&!spiMode) begin if (ssReg&!ssRegR) begin Data_o <= dataCaptReg; end end end always @(*) begin if (spiMode & !Ss_i) begin if (dataCnt >=5'd8|dataCnt == 0) begin txWind = 1'b1; end else begin txWind = 1'b0; end end else begin txWind = 1'b0; end end always @(negedge Sck_i) begin if (txWind) begin if (~Ss_i & txWind & txCnt!= 0) begin txCnt <= txCnt - 5'd1; end else begin txCnt <= 5'd24; end end else begin txCnt <= 5'd24; end end endmodule