/* * lab12_adc_binary.v * demonstrate successive-approximation ADC operation for physics 364 week 12 * begun 2010-11-29 * by Bill Ashmanskas, ashmansk@hep.upenn.edu */ `default_nettype none `timescale 1ns/1ns /* * Implement successive-approximation ADC */ module adc ( input wire clk, // 68 kHz clock, for ~ 7 kHz sampling input wire cmp, // 1 if sample > DAC value, else 0 output wire [5:0] dac, // DAC used for comparing with sample output wire [5:0] adc, // ADC output value output wire conv_done, // indicate next ADC value is ready output wire sample_hold // closes FET switch for sample & hold ); // modulo-10 counter: ramp 0..5, then allow 4 extra ticks for processing wire [3:0] count; wire [3:0] count_next = (count==9) ? 0 : count+1; dffe_Nbit #(4) count_ff (.clk(clk), .ena(1), .d(count_next), .q(count)); // Update DAC bits: // on tick 0,1,2,3,4,5, bit 5,4,3,2,1,0 is set to 1; // on tick 1,2,3,4,5,6, bit 5,4,3,2,1,0 is set to comparison outcome // on tick 7, all bits are set to 0 for new cycle wire [5:0] dac_next; dffe_Nbit #(6) dac_ff (.clk(clk), .ena(1), .d(dac_next), .q(dac)); assign dac_next[5] = (count==0) ? 1 : (count==1) ? cmp : (count==7) ? 0 : dac[5]; assign dac_next[4] = (count==1) ? 1 : (count==2) ? cmp : (count==7) ? 0 : dac[4]; assign dac_next[3] = (count==2) ? 1 : (count==3) ? cmp : (count==7) ? 0 : dac[3]; assign dac_next[2] = (count==3) ? 1 : (count==4) ? cmp : (count==7) ? 0 : dac[2]; assign dac_next[1] = (count==4) ? 1 : (count==5) ? cmp : (count==7) ? 0 : dac[1]; assign dac_next[0] = (count==5) ? 1 : (count==6) ? cmp : (count==7) ? 0 : dac[0]; // ... dffe_Nbit #(6) adc_ff (.clk(clk), .ena(count==7), .d(dac), .q(adc)); // when ADC output register has updated, strobe "conversion done" signal assign conv_done = (count==8); // before new conversion begins, tell sample & hold to get new sample assign sample_hold = (count==9); endmodule /* * Test bench for ADC */ module adc_tb; reg clk=0, cmp=0; wire [5:0] adc, dac; wire conv_done, sample_hold; adc uut (.clk(clk), .cmp(cmp), .adc(adc), .dac(dac), .conv_done(conv_done), .sample_hold(sample_hold)); parameter period=1000000/68; initial begin #200; forever begin #(period/2); clk = 1; #(period/2); clk = 0; end end reg [5:0] sample = 0; always @(*) begin cmp = (sample>=dac); if (sample_hold) sample = sample+13; end always @ (negedge clk) begin $display("t=%1d done=%1d sample=%1d dac=%1d/%1b cmp=%1d adc=%1d", $time/period, conv_done, sample, dac, dac, cmp, adc); end initial begin #10000000; $finish; end endmodule /* * Implement N-bit-wide D-type flip-flop, with enable */ module dffe_Nbit #(parameter N=1) ( input wire clk, input wire ena, input wire [N-1:0] d, output wire [N-1:0] q ); reg [N-1:0] qreg=0; always @ (posedge clk) begin if (ena) qreg <= d; end assign q = qreg; endmodule