FPGA Verilog HDL系列实例—AD转换

可编程逻辑

1340人已加入

描述

Verilog HDL 之 AD转换

   AD转换就是模数转换,顾名思义,就是把模拟信号转换成数字信号。我们所用的模数转换芯片是ADC0809。

  ADC0809 8通道8位a/d转换器,ADC0809是带有8位A/D转换器、8路多路开关以及微处理机兼容的控制逻辑的CMOS组件。它是逐次逼近式A/D转换器,可以和单片机直接接口。ADC0809由一个8路模拟开关、一个地址锁存与译码器、一个A/D转换器和一个三态输出锁存器组成。多路开关可选通8个模拟通道,允许8路模拟量分时输入,共用A/D转换器进行转换。三态输出锁器用于锁存A/D转换完的数字量,当OE端为高电平时,才可以从三态输出锁存器取走转换完的数据。如图3.1所示。

     锁存器

                 图3.1 ADC0809的内部结构和引脚定义

   如何学会使用一个自己曾经没有用过的芯片,最重要的是要学会看它的芯片手册,以及它的时序图。下面我们将看看是如何根据它的时序图完成对芯片的驱动的。

      锁存器

                       图3.2 ADC0809时序图

  原理(好好理解一下,这样才能很好的根据时序图写出代码。):START为转换启动信号。当START上跳沿时,所有内部寄存器清零;下跳沿时,开始进行A/D转换;在转换期间,START应保持低电平。EOC为转换结束信号。当EOC为高电平时,表明转换结束;否则,表明正在进行A/D转换。OUTPUTENABLE为输出允许信号,用于控制三条输出锁存器向单片机输出转换得到的数据。OE=1,输出转换得到的数据;OE=0,输出数据线呈高阻状态。D7-D0为数字量输出线。CLK为时钟输入信号线。因ADC0809的内部没有时钟电路,所需时钟信号必须由外界提供,通常使用频率为500KHZ(程序中会有体现)。

Verilog HDL实现

实现步骤请参照 【连载】 FPGA Verilog HDL 系列实例--------8-3编码器。这里就不再赘述。

设计文件输入Verilog HDL代码。

 

  1 //-------------------------------------------------------------------------------------------------
  2 //  3 // File        : ADC0809.v
  4 // Generated   : 2011-07-21
  5 // Author      : wangliang
  6 //  7 //-------------------------------------------------------------------------------------------------  8 `timescale 1 ns / 1 ps
  9  10  11 module ADC0809 ( seven_seg ,ale ,OE ,D ,EOC ,clk ,abc_in ,abc_out ,start ,rst );
 12  13 input            clk ;                    //系统时钟 14 input    [2:0]    abc_in     ;                //外部控制的通道选择信号 15 input    [7:0]    D ;                         //ADC0809传进来的数据 16 input             EOC ;                    //ADC0809转换完成信号标志 17 input             rst ;                    //系统 复位 18  19 output    [15:0]    seven_seg ;                  //FPGA给数码管的数据 20 output            ale ;                      //FPGA给ADC0809的地址锁存信号 21 output            OE ;                      //FPGA给ADC0809的使能信号 22 output    [2:0]    abc_out ;                  //FPGA给ADC0809的通道选择信号 23 output            start ;                      //ADC0809 转换开始信号 24  25 parameter    st0 = 3'b000, 26             st1 = 3'b001, 27             st2 = 3'b010, 28             st3 = 3'b011, 29             st4 = 3'b100, 30             st5 = 3'b101, 31             st6 = 3'b110 ; 32             
 33 reg     [2:0]    p_state  ;
 34 reg        [2:0]    n_state ;
 35 reg                ale_r    ;
 36 reg                OE_r    ;
 37 reg                start_r    ;
 38 reg        [7:0]    reg1    ;
 39 reg        [7:0]    qq        ;
 40 wire     [2:0]    state    ;
 41  42 assign             state = p_state ;
 43  44 always @ (posedge clk or negedge rst)
 45 begin
 46      if ( rst== 1'b0 ) begin 47         p_state <= st0    ;
 48         qq <= 8'b0        ; 49             
 50     end
 51     else    begin
 52         qq <= qq + 1'b1; 53         if ( ( qq >= 8'b0100_0010) && ( clk == 1'b1 ) ) begin
 54             qq <= 8'b0; 55             p_state <=#1 n_state;
 56         end
 57         
 58     end
 59 end
 60  61 assign    ale = ale_r    ;
 62 assign    OE = OE_r     ;
 63 assign    start = start_r     ;
 64  65 assign abc_out =  abc_in ;
 66  67 always @ ( EOC ,p_state )
 68   begin
 69       case ( p_state )
 70         st0 :begin
 71             ale_r <= #1 1'b0; 72              start_r <= #1 1'b0; 73             OE_r <= #1 1'b0; 74             n_state <=#1 st1;
 75         end
 76         st1 :begin
 77             ale_r <= #1 1'b1; 78              start_r <= #1 1'b0; 79             OE_r <= #1 1'b0; 80             n_state <=#1 st2;
 81         end
 82         st2 :begin
 83             ale_r <= #1 1'b0; 84              start_r <= #1 1'b1;     85             OE_r <= #1 1'b0; 86             n_state <=#1 st3;
 87         end
 88         st3 :begin
 89             ale_r <= #1 1'b0; 90              start_r <= #1 1'b0;     91             OE_r <= #1 1'b0;  92             if ( EOC == 1'b1 ) 93                 n_state <=#1 st3;
 94             else 95                 n_state <=#1 st4;
 96                 
 97         end
 98         st4 :begin
 99              ale_r <= #1 1'b0;100              start_r <= #1 1'b0;    101             OE_r <= #1 1'b0; 102             if ( EOC == 1'b0 )103                 n_state <=#1 st4;
104             else105                 n_state <=#1 st5;
106         end
107         st5 :begin
108              ale_r <= #1 1'b0;109              start_r <= #1 1'b0;    110             OE_r <= #1 1'b1; 111             n_state <=#1 st6;
112         end
113         st6 :begin
114              ale_r <= #1 1'b0;115              start_r <= #1 1'b0;    116             OE_r <= #1 1'b1; 117             reg1 <=#1  D ;
118             n_state <=#1 st0;
119         end
120         default :begin
121              ale_r <= #1 1'b0;122              start_r <= #1 1'b0;    123             OE_r <= #1 1'b0; 124             n_state <=#1 st0;
125         end
126         endcase
127         
128 end
129     
130 /********************  数码管显示译码部分 ***********************************/131 reg        [7:0]    Y_r_1;
132 reg        [7:0]    Y_r_2;
133 134 assign seven_seg[7:0] ={1'b1,(~Y_r_1[6:0])};135 assign seven_seg[15:8] = {1'b1,(~Y_r_2[6:0])};136 137 always @(reg1[3:0] )
138     begin
139         Y_r_1 = 7'b1111111;140         case (reg1[3:0] )
141                 4'b0000: Y_r_1 = 7'b0111111; // 0142                 4'b0001: Y_r_1 = 7'b0000110; // 1143                 4'b0010: Y_r_1 = 7'b1011011; // 2144                 4'b0011: Y_r_1 = 7'b1001111; // 3145                 4'b0100: Y_r_1 = 7'b1100110; // 4146                 4'b0101: Y_r_1 = 7'b1101101; // 5147                 4'b0110: Y_r_1 = 7'b1111101; // 6148                 4'b0111: Y_r_1 = 7'b0000111; // 7149                 4'b1000: Y_r_1 = 7'b1111111; // 8150                 4'b1001: Y_r_1 = 7'b1101111; // 9151                 4'b1010: Y_r_1 = 7'b1110111; // A152                 4'b1011: Y_r_1 = 7'b1111100; // b153                 4'b1100: Y_r_1 = 7'b0111001; // c154                 4'b1101: Y_r_1 = 7'b1011110; // d155                 4'b1110: Y_r_1 = 7'b1111001; // E156                 4'b1111: Y_r_1 = 7'b1110001; // F157                 default: Y_r_1 = 7'b0000000;158             endcase
159     end
160 161     always @( reg1[7:4] )
162     begin
163         Y_r_2 = 7'b1111111;164         case ( reg1[7:4] )
165                 4'b0000: Y_r_2 = 7'b0111111; // 0166                 4'b0001: Y_r_2 = 7'b0000110; // 1167                 4'b0010: Y_r_2 = 7'b1011011; // 2168                 4'b0011: Y_r_2 = 7'b1001111; // 3169                 4'b0100: Y_r_2 = 7'b1100110; // 4170                 4'b0101: Y_r_2 = 7'b1101101; // 5171                 4'b0110: Y_r_2 = 7'b1111101; // 6172                 4'b0111: Y_r_2 = 7'b0000111; // 7173                 4'b1000: Y_r_2 = 7'b1111111; // 8174                 4'b1001: Y_r_2 = 7'b1101111; // 9175                 4'b1010: Y_r_2 = 7'b1110111; // A176                 4'b1011: Y_r_2 = 7'b1111100; // b177                 4'b1100: Y_r_2 = 7'b0111001; // c178                 4'b1101: Y_r_2 = 7'b1011110; // d179                 4'b1110: Y_r_2 = 7'b1111001; // E180                 4'b1111: Y_r_2 = 7'b1110001; // F181                 default: Y_r_2 = 7'b0000000;182             endcase
183     end
184     
185 endmodule

 

  上面一长串代码,刚接触的人一看可能会头大,但要是仔细分析一下,就会很好理解了。本实现有三部分组成:

  1.第44行~第59行:时钟分频,系统时钟为50MHZ,ADC0809的驱动频率不需要这么快,所以需要分频。一般在500KHZ左右,实例中用的是750KHz。

  2.第67行~第128行:对ADC0809时序的实现。自己好好理解下哦。一次模数转换经过6个步骤完成。第3步和第4步需要查看EOC的状态来确定是否将模拟数据转换完毕。

  3.第137行~第183行:将模拟数据转化到的数字数据输出到2个数码管上。图3.3是ADC0809的外部接口。

        锁存器

           图3.3 ADC0809的外部接口

 分配引脚:

  clk接系统时钟,rst接复位信号,abc_in[2..0]接三个按键,seven_seg[15..0]接2个七段数码管,其余的是ADC0809上的型号,这是由硬件连线决定的,只要搞清楚它们是输入还是输出就行了。

实验结果:

  将三个按键都关闭,选择0通道,这样,当旋转按钮的时候,在2个七段数码管上就能显示数值。这就完成了将模拟数据转化为数字量的验证。





审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分