`timescale 1ns / 1ps module ADC_peripheral( clk, reset, cs, ADC_EOC, ADC_CS, ADC_CSTART, ADC_SCLK, ADC_SDIN, ADC_SDOUT, addr, rdBus, wrBus, we); input clk, reset, ADC_EOC, cs, we; input [10:0] addr; input [7:0] wrBus; output ADC_CS, ADC_CSTART, ADC_SCLK; output [7:0] rdBus; inout ADC_SDIN, ADC_SDOUT; //RAMB registers reg [7:0] rdBus; wire [7:0] rdBus1; wire [7:0] rdBus2; reg [7:0] wrBus2; reg [10:0] addr2; reg we1=0; reg we2=0; wire we; //Control registers reg nSample=0; reg [10:0] auto_count=0; reg [4:0] w_st2=0; //SPI registers reg [3:0] SPI_in_data=0; reg [9:0] SPI_out_data; reg SPI_rd = 0; reg SPI_wr = 0; // Confiuration registers reg CMD_DONE; reg CMD_TYP; reg [3:0] CMD_ADC; reg [7:0] CLKDIV = 0; reg [10:0] SIZEB; //[10:8] -> size_hi | [7:0] -> size_low //TEMPS reg [10:0] SIZEB2; reg CMD_DONE2; assign ADC_CSTART = 1'b1; // Dual-port RAM instatiation RAMB16_S9_S9 ba0( .DOA(rdBus1), // Port A 8-bit Data Output .DOB(rdBus2), // Port B 8-bit Data Output .DOPA(), // Port A 1-bit Parity Output .DOPB(), // Port B 1-bit Parity Output .ADDRA(addr[10:0]), // Port A 11-bit Address Input .ADDRB(addr2[10:0]), // Port B 11-bit Address Input .CLKA(~clk), // Port A Clock .CLKB(~clk), // Port B Clock .DIA(wrBus), // Port A 8-bit Data Input .DIB(wrBus2), // Port B 8-bit Data Input .DIPA(1'b0), // Port A 1-bit parity Input .DIPB(1'b0), // Port-B 1-bit parity Input .ENA(1'b1), // Port A RAM Enable Input .ENB(1'b1), // Port B RAM Enable Input .SSRA(1'b0), // Port A Synchronous Set/Reset Input .SSRB(1'b0), // Port B Synchronous Set/Reset Input .WEA(we1), // Port A Write Enable Input .WEB(we2) ); // Port B Write Enable Input // 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 [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; // Write control always @(negedge clk) if(reset) {CMD_TYP,CMD_ADC,SIZEB,we1} <= 0; else if(we & cs) begin case (addr) 0: begin CMD_TYP <= wrBus[4]; CMD_ADC[3:0] <= wrBus[3:0]; end 1: begin CLKDIV <= wrBus; end 2: begin SIZEB[7:0] <= wrBus; end 3: begin SIZEB[10:8] <= wrBus[2:0]; end default: begin we1 <= 1; end endcase end else if(nSample) begin SIZEB <= SIZEB - 1; end else begin we1 <= 0; end // Read control always @(posedge clk) if(reset) {rdBus} <= 0; else begin case (addr) 0: begin rdBus <= {CMD_DONE,CMD_TYP,CMD_ADC};end 1: begin rdBus <= CLKDIV; end 2: begin rdBus <= SIZEB[7:0]; end 3: begin rdBus <= SIZEB[10:8]; end default: begin rdBus <= rdBus1; end endcase end // Comunication control always @(posedge clk) if(reset) {we2, SPI_wr, SPI_rd, w_st2, auto_count, SPI_in_data, nSample} <= 0; else begin case (w_st2) 0: begin w_st2 <= 2; SIZEB2<=SIZEB; end 2: begin if (SIZEB == 0) begin w_st2 <= 0; CMD_DONE<= 1; auto_count <= 0; end else begin CMD_DONE<= 0; //Send data to ADC auto_count <= auto_count+1; SPI_in_data <= CMD_ADC[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 SPI_rd <=1; if(CMD_TYP) w_st2<= 2; else w_st2<= 4; end end 4: begin //Write data on BRAM (LOW) wrBus2 <= SPI_out_data[7:0]; addr2 <= 4+2*(SIZEB2-SIZEB); 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 <= 5+2*(SIZEB2-SIZEB); we2 <= 1; w_st2 <= 7; nSample <= 1; end 7: begin nSample <= 0; we2 <= 0; SPI_rd <=0; w_st2 <= 2; end endcase end endmodule