`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; reg ADC_CS=1; //RAMB registers reg [7:0] rdBus; wire [7:0] rdBus1; reg [7:0] wrBus2; reg [10:0] addr2; reg we1=0; reg we2=0; wire we; //Control registers reg loadB=0; reg initB=0; reg fullB=0; reg rstStart=0; reg [2:0] w_st0=0; reg w_st1=0; reg [2:0] w_st2=0; // Confiuration registers reg CMD_START=0; reg CMD_TYP=0; reg [3:0] CMD_ADC=0; reg [7:0] CLKDIV = 0; reg [9:0] SIZEB=0; //[10:8] -> size_hi | [7:0] -> size_low //TEMPS reg [9:0] SIZEB2=0; assign ADC_CSTART = 1'b1; // Dual-port RAM instatiation RAMB16_S9_S9 ba0( .DOA(rdBus1), // Port A 8-bit Data Output .DOB(), // 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[7:0]), // Port A 8-bit Data Input .DIB(wrBus2[7:0]), // 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 registers reg SPI_wr = 0; reg ADC_SCLK_buffer = 0; reg ADC_SDIN_buffer = 0; reg busy = 0, load_in = 0; reg pulse = 0, clkdiv_en = 0; wire fallingSCLK; reg [3:0] in_buffer=0; reg [9:0] out_buffer; reg [7:0] clkcount = 0; reg [5:0] pulsecount = 0; assign fallingSCLK = pulsecount[0]; // SPI Control always @(posedge clk) if(reset) begin {w_st1, pulsecount, clkdiv_en, busy} <= 0; end else begin case (w_st1) 0: begin if(SPI_wr) begin clkdiv_en <= 1; load_in <= 1; w_st1 <= 1; busy <= 1; end end 1: begin load_in <= 0; if(pulse) pulsecount <= pulsecount + 1; else if (pulsecount > 55) begin clkdiv_en <= 0; busy <= 0; w_st1 <= 0; pulsecount <= 0; end end endcase end // SPI Clock Generator always@(posedge clk) if (clkdiv_en) begin if(clkcount < CLKDIV) begin clkcount <= clkcount + 1; pulse <=0; end else begin clkcount <= 0; pulse <=1; if((pulsecount>0) && (pulsecount < 21)) ADC_SCLK_buffer <= ~ADC_SCLK_buffer; end end else begin ADC_SCLK_buffer <= 0; pulse <=0; end // SPI Receptor always@(posedge clk) begin if((fallingSCLK & pulse) && (pulsecount < 21)) begin out_buffer <= out_buffer << 1; out_buffer[0] <= ADC_SDOUT; end end // SPI Transmitter always@(posedge clk) begin if(load_in) in_buffer <= CMD_ADC[3:0]; if(!fallingSCLK & pulse) begin ADC_SDIN_buffer <= in_buffer[3]; in_buffer <= in_buffer << 1; end end assign ADC_SCLK = ADC_SCLK_buffer; assign ADC_SDIN = ADC_SDIN_buffer; /**************************************************************************/ // REGISTER BANK: Write control always @(negedge clk) if(reset) {CMD_START, CMD_TYP,CMD_ADC,SIZEB,we1} <= 0; else if(we & cs) begin case (addr) 0: begin CMD_START <= wrBus[5]; 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[9:8] <= wrBus[1:0]; end default: begin we1 <= 1; end endcase end else if(fullB || rstStart) begin CMD_START <= 0; end else begin we1 <= 0; end // REGISTER BANK: Read control always @(posedge clk) if(reset) {rdBus} <= 0; else begin case (addr) 0: begin rdBus <= {CMD_START,CMD_TYP,CMD_ADC};end 1: begin rdBus <= CLKDIV; end 2: begin rdBus <= SIZEB[7:0]; end 3: begin rdBus <= SIZEB[9:8]; end default: begin rdBus <= rdBus1; end endcase end // CONTROL always @(posedge clk) if(reset) begin {w_st0, SPI_wr} <= 0; ADC_CS <=1; end else begin case (w_st0) 0: begin rstStart <= 0; loadB <= 0; initB<=0; if(CMD_START) begin ADC_CS <=0; SPI_wr <= 1; w_st0 <=1; end end 1: begin SPI_wr <= 0; if(!busy && ADC_EOC) begin ADC_CS <=1; if(CMD_TYP) begin rstStart <= 1; w_st0<= 0; end else begin initB<=1; w_st0<= 2; end end end 2: begin loadB <= 1; w_st0<= 0; end endcase end // Reception Buffer always @(posedge clk) if(reset) {we2, w_st2, fullB, SIZEB2} <= 0; else begin case (w_st2) 0: begin fullB <= 0; if(initB) begin w_st2 <= 1; SIZEB2<=SIZEB; end end 1: begin if(loadB) begin // If buffer full set fullB flag by a clock cicle if(SIZEB2) begin w_st2 <= 2; end else begin fullB <= 1; w_st2 <= 0; end end end 2: begin //Write data on BRAM (LOW) wrBus2 <= out_buffer[7:0]; addr2 <= 4+2*(SIZEB-SIZEB2); we2 <= 1; w_st2 <= 3; end 3: begin we2 <= 0; w_st2 <= 4; end 4: begin //Write data on BRAM (HI) wrBus2 <= out_buffer[9:8]; addr2 <= 5+2*(SIZEB-SIZEB2); we2 <= 1; w_st2 <= 5; end 5: begin we2 <= 0; w_st2 <= 1; SIZEB2 <= SIZEB2-1; end endcase end endmodule