`timescale 1ns / 1ps module ADC_peripheral( clk, reset, ADC_EOC, ADC_CS, ADC_CSTART, ADC_SCLK, ADC_SDIN, ADC_SDOUT, we2, rdBus2, wrBus2, addr2); input clk, reset, ADC_EOC; input [7:0] rdBus2; output we2, ADC_CS, ADC_CSTART, ADC_SCLK; output [7:0] wrBus2; output [8:0] addr2; inout ADC_SDIN, ADC_SDOUT; reg we2=0, nSample=0; reg [7:0] wrBus2; reg [8:0] addr2; reg [7:0] auto_count=0; reg [4:0] w_st2=0; reg [3:0] SPI_in_data=0; reg [9:0] SPI_out_data; reg SPI_rd = 0; reg SPI_wr = 0; reg [7:0] buffer_rd1; reg [3:0] ADC_cmd; assign ADC_CSTART = 1'b1; // SPI comunication module instantiation reg ADC_SCLK_buffer = 0; reg ADC_SDIN_buffer = 0; reg busy = 0; reg [3:0] in_buffer=0; reg [9:0] out_buffer; reg [7:0] clkcount = 0; reg [7:0] clkdiv = 255; reg [4:0] count = 0; assign ADC_CS = ~busy; always@(SPI_rd or out_buffer or busy or clkdiv) begin SPI_out_data = 10'bx; if(SPI_rd) begin SPI_out_data = out_buffer; end end always@(negedge clk) begin if(!busy) begin if(SPI_wr) begin in_buffer = SPI_in_data; busy = 1; end end else begin clkcount = clkcount + 1; if(clkcount >= clkdiv) begin clkcount = 0; // Send the ADC CMD on first 4 rising edge of SCLK if((count % 2) == 0) begin ADC_SDIN_buffer = in_buffer[3]; in_buffer = in_buffer << 1; end // We generate 10 cicles of SCLK if(count > 0 && count < 21) begin ADC_SCLK_buffer = ~ADC_SCLK_buffer; end count = count + 1; if(count > 21) begin count = 0; busy = 0; end end end end always@(posedge ADC_SCLK_buffer) begin out_buffer = out_buffer << 1; out_buffer[0] = ADC_SDOUT; end assign ADC_SCLK = ADC_SCLK_buffer; assign ADC_SDIN = ADC_SDIN_buffer; // State Machine for control ADC comunication always @(posedge clk) if(reset) {we2, SPI_wr, SPI_rd, w_st2, auto_count, SPI_in_data} <= 0; else begin case (w_st2) 0: begin addr2 <= 0; w_st2 <= 1; end 1: begin ADC_cmd <= rdBus2[3:0]; if (rdBus2[7:4] == 5) // Send command without read samples begin addr2<= 2; w_st2 <= 2; nSample <= 1; end else if (rdBus2[7:4] == 6) // Read: Stop when buffer full begin addr2<= 2; w_st2 <= 2; nSample <= 0; end else if (rdBus2[7:4] == 9) // Set clkdiv on SPI controller begin addr2<= 1; w_st2 <= 10; end else begin w_st2 <= 0; end end 2: begin if (rdBus2[7:0] == 0) begin auto_count<=0; w_st2 <= 0; end else begin //Send data to ADC buffer_rd1<=rdBus2; auto_count<=auto_count+1; SPI_in_data <= ADC_cmd[3:0]; SPI_wr <= 1; w_st2 <= 3; end end 3: begin SPI_wr <= 0; //Wait for complete convertion if(!ADC_EOC || ADC_CS) begin buffer_rd1<=buffer_rd1-1; SPI_rd <=1; if(nSample) w_st2<= 8; else w_st2<= 4; end end 4: begin //Write data on BRAM (LOW) wrBus2 <= SPI_out_data[7:0]; addr2 <= 2+2*auto_count; we2 <= 1; w_st2 <= 5; end 5: begin we2 <= 0; w_st2 <= 6; end 6: begin //Write data on BRAM (HI) wrBus2 <= SPI_out_data[9:8]; addr2 <= 3+2*auto_count; we2 <= 1; w_st2 <= 7; end 7: begin we2 <= 0; w_st2 <= 8; end 8: begin SPI_rd <=0; //Update Buffer Size value wrBus2 <= buffer_rd1; addr2 <= 2; we2 <= 1; w_st2 <= 9; end 9: begin we2 <= 0; w_st2 <= 0; end //Sent clock divider for speed on SPI comunication 10: begin clkdiv = rdBus2; w_st2 <= 0; end endcase end endmodule