Root/Examples/ADC/logic/ADC_peripheral.v

1`timescale 1ns / 1ps
2module ADC_peripheral( clk, reset, cs, ADC_EOC, ADC_CS, ADC_CSTART,
3                        ADC_SCLK, ADC_SDIN, ADC_SDOUT,
4                        addr, rdBus, wrBus, we);
5                                    
6    input clk, reset, ADC_EOC, cs, we;
7    input [10:0] addr;
8    input [7:0] wrBus;
9    output ADC_CS, ADC_CSTART, ADC_SCLK;
10    output [7:0] rdBus;
11    inout ADC_SDIN, ADC_SDOUT;
12
13    reg ADC_CS=1;
14    
15    //RAMB registers
16    reg [7:0] rdBus;
17    wire [7:0] rdBus1;
18    reg [7:0] wrBus2;
19    reg [10:0] addr2;
20    reg we1=0, we2=0;
21    wire we;
22       
23    //Control registers
24    reg loadB=0;
25    reg initB=0;
26    reg fullB=0;
27    reg rstStart=0;
28    reg [2:0] w_st0=0;
29    reg [2:0] w_st1=0;
30    reg [2:0] w_st2=0;
31      
32    // Confiuration registers
33    reg [1:0] CMD_SW=0; // Channel offset selection
34    reg CMD_START=0; // START sampling data
35    reg CMD_TYP=0; // Command type
36    reg [3:0] CMD_ADC=0; // ADC command
37    reg [7:0] CLKDIV = 0; // Clock divisor for SPI
38    reg [9:0] SIZEB=0; // Buffer size (sampling data len.)
39        //TEMPS
40    reg [9:0] SIZEB1=0; // Temporal for buffer size
41    reg [9:0] SIZEB2=0; // Temporal for buffer size
42        wire[9:0] subSIZEB; // Temporal for subtraction SIZEB1-SIZEB2
43    reg [2:0] CMD_OFFSET=0; // Channel offset counter MOD8
44    wire[2:0] CMD_OFFSETt; // Channel offset to use
45    wire[3:0] CMD_ADCt; // Temporal for channel offset
46     
47    assign ADC_CSTART = 1'b1;
48    
49    // Dual-port RAM instatiation
50    RAMB16_S9_S9 ba0(
51            .DOA(rdBus1), // Port A 8-bit Data Output
52            .DOB(), // Port B 8-bit Data Output
53            .DOPA(), // Port A 1-bit Parity Output
54            .DOPB(), // Port B 1-bit Parity Output
55            .ADDRA(addr[10:0]), // Port A 11-bit Address Input
56            .ADDRB(addr2[10:0]), // Port B 11-bit Address Input
57            .CLKA(~clk), // Port A Clock
58            .CLKB(~clk), // Port B Clock
59            .DIA(wrBus[7:0]), // Port A 8-bit Data Input
60            .DIB(wrBus2[7:0]), // Port B 8-bit Data Input
61            .DIPA(1'b0), // Port A 1-bit parity Input
62            .DIPB(1'b0), // Port-B 1-bit parity Input
63            .ENA(1'b1), // Port A RAM Enable Input
64            .ENB(1'b1), // Port B RAM Enable Input
65            .SSRA(1'b0), // Port A Synchronous Set/Reset Input
66            .SSRB(1'b0), // Port B Synchronous Set/Reset Input
67            .WEA(we1), // Port A Write Enable Input
68            .WEB(we2) ); // Port B Write Enable Input
69
70    //SPI registers
71    reg SPI_wr = 0;
72    reg ADC_SCLK_buffer = 0;
73    reg ADC_SDIN_buffer = 0;
74    reg busy = 0, load_in = 0;
75    reg pulse = 0, clkdiv_en = 0;
76    wire fallingSCLK;
77
78    reg [3:0] in_buffer=0;
79    reg [9:0] out_buffer;
80    reg [7:0] clkcount = 0;
81    reg [5:0] pulsecount = 0;
82    
83    assign fallingSCLK = pulsecount[0];
84
85    // SPI Control
86    always @(posedge clk)
87    if(reset) begin
88        {w_st1, pulsecount, clkdiv_en, busy} <= 0;
89    end else begin
90        case (w_st1)
91             0: begin
92                    if(SPI_wr) begin
93                        clkdiv_en <= 1;
94                        load_in <= 1;
95                        w_st1 <= 1; busy <= 1;
96                    end
97                end
98             1: begin
99                     load_in <= 0;
100                     if(pulse)
101                         pulsecount <= pulsecount + 1;
102                     else if (pulsecount > 55) begin
103                          clkdiv_en <= 0; busy <= 0;
104                          w_st1 <= 0; pulsecount <= 0;
105                     end
106                end
107          endcase
108     end
109    
110    // SPI Clock Generator
111    always@(posedge clk)
112        if (clkdiv_en) begin
113           if(clkcount < CLKDIV) begin
114                   clkcount <= clkcount + 1; pulse <=0;
115           end else begin
116                clkcount <= 0; pulse <=1;
117                if((pulsecount>0) && (pulsecount < 21))
118                    ADC_SCLK_buffer <= ~ADC_SCLK_buffer;
119           end
120        end else begin
121            ADC_SCLK_buffer <= 0; pulse <=0;
122        end
123    
124    // SPI Receptor
125    always@(posedge clk)
126    begin
127        if((fallingSCLK & pulse) && (pulsecount < 21)) begin
128            out_buffer <= out_buffer << 1;
129            out_buffer[0] <= ADC_SDOUT;
130        end
131    end
132    
133    // SPI Transmitter
134    always@(posedge clk)
135    begin
136        if(load_in) in_buffer <= CMD_ADCt[3:0];
137        if(!fallingSCLK & pulse) begin
138            ADC_SDIN_buffer <= in_buffer[3];
139            in_buffer <= in_buffer << 1;
140        end
141    end
142
143    assign ADC_SCLK = ADC_SCLK_buffer;
144    assign ADC_SDIN = ADC_SDIN_buffer;
145
146    /**************************************************************************/
147
148    // REGISTER BANK: Write control
149    always @(negedge clk)
150    begin
151        if(reset)
152            {CMD_START, CMD_TYP,CMD_ADC,SIZEB,we1} <= 0;
153        else if(we & cs) begin
154            case (addr)
155                    0: begin CLKDIV[7:0] <= wrBus; end
156                    1: begin SIZEB[7:0] <= wrBus; end
157                    2: begin SIZEB[9:8] <= wrBus[1:0]; end
158                    3: begin CMD_SW[1:0] <= wrBus[7:6];
159                             CMD_START <= wrBus[5];
160                             CMD_TYP <= wrBus[4];
161                             CMD_ADC[3:0] <= wrBus[3:0]; end
162              default: begin we1 <= 1; end
163            endcase
164        end
165        else begin
166            we1 <= 0; end
167
168        if(fullB | rstStart) CMD_START <= 0;
169    end
170
171    // REGISTER BANK: Read control
172    always @(posedge clk)
173        if(reset)
174            {rdBus} <= 0;
175        else begin
176            case (addr)
177                  0: begin rdBus <= CLKDIV; end
178                  1: begin rdBus <= SIZEB[7:0]; end
179                  2: begin rdBus <= SIZEB[9:8]; end
180                  3: begin rdBus <= {CMD_SW,CMD_START,CMD_TYP,CMD_ADC};end
181            default: begin rdBus <= rdBus1; end
182            endcase
183        end
184 
185    // CONTROL
186    always @(posedge clk)
187        if(reset) begin
188            {w_st0, SPI_wr, loadB, initB} <= 0;
189            ADC_CS <=1;
190        end
191        else begin
192            case (w_st0)
193                 0: begin
194                        rstStart <= 0;
195                        if(CMD_START) begin
196                            ADC_CS <=0;
197                            SPI_wr <= 1;
198                            w_st0 <=1;
199                        end
200                    end
201                 1: begin SPI_wr <= 0; w_st0 <=2; end
202                 2: begin
203                        if(!busy & ADC_EOC) begin
204                            ADC_CS <=1;
205                            if(CMD_TYP) begin
206                                rstStart <= 1;
207                                w_st0<= 0;
208                            end
209                            else begin
210                                initB<=1;
211                                w_st0<= 3;
212                            end
213                        end
214                    end
215                 3: begin loadB <= 1; w_st0<= 4; end
216                 4: begin loadB <= 0; initB<=0; w_st0<= 0; end
217            endcase
218        end
219    
220    // Reception Buffer
221    always @(posedge clk)
222    if(reset)
223        {we2, w_st2, fullB, SIZEB1, SIZEB2} <= 0;
224    else begin
225        case (w_st2)
226             0: begin
227                    fullB <= 0;
228                    if(initB) begin
229                        w_st2 <= 1;
230                        SIZEB1<=SIZEB;
231                        SIZEB2<=SIZEB;
232                    end
233                end
234             1: begin
235                    if(loadB) begin
236                        // If buffer full set fullB flag by a clock cicle
237                        if(SIZEB2>0) begin
238                            w_st2 <= 2; end
239                        else begin
240                            fullB <= 1;
241                            w_st2 <= 0;
242                        end
243                    end
244                end
245             2: begin
246                    //Write data on BRAM (LOW)
247                    wrBus2[7:0] <= out_buffer[7:0];
248                    addr2 <= {subSIZEB,1'b0};
249                    we2 <= 1; w_st2 <= 3;
250                end
251             3: begin we2 <= 0; w_st2 <= 4; end
252             4: begin
253                    //Write data on BRAM (HI)
254                    wrBus2[7:0] <= out_buffer[9:8];
255                    addr2 <= {subSIZEB,1'b1};
256                    we2 <= 1; w_st2 <= 5;
257                end
258             5: begin
259                    we2 <= 0; w_st2 <= 1; SIZEB2 <= SIZEB2-1;
260                end
261        endcase
262      end
263    
264    assign subSIZEB = SIZEB1-SIZEB2;
265    
266    // ADC channel offset, counter MOD8
267    always @(posedge clk)
268        if(fullB | reset)
269            CMD_OFFSET <= 0;
270        else if(loadB) begin
271            CMD_OFFSET <= CMD_OFFSET + 1;
272        end
273        
274    // MUX to select the channel offset
275    assign CMD_OFFSETt = CMD_SW[1]? (CMD_SW[0]? CMD_OFFSET[2:0] :
276                                                CMD_OFFSET[1:0] )
277                                  : (CMD_SW[0]? CMD_OFFSET[0] :
278                                                3'b0 );
279                                                
280    // Add ADC command and offset
281    assign CMD_ADCt = CMD_ADC + CMD_OFFSETt;
282endmodule
283

Archive Download this file

Branches:
master



interactive