zoukankan      html  css  js  c++  java
  • 【连载】 FPGA Verilog HDL 系列实例AD转换(ADC0809)

    【连载】 FPGA Verilog HDL 系列实例

    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代码。

    ADC0809.v
      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 else
    105 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; // 0
    142 4'b0001: Y_r_1 = 7'b0000110; // 1
    143 4'b0010: Y_r_1 = 7'b1011011; // 2
    144 4'b0011: Y_r_1 = 7'b1001111; // 3
    145 4'b0100: Y_r_1 = 7'b1100110; // 4
    146 4'b0101: Y_r_1 = 7'b1101101; // 5
    147 4'b0110: Y_r_1 = 7'b1111101; // 6
    148 4'b0111: Y_r_1 = 7'b0000111; // 7
    149 4'b1000: Y_r_1 = 7'b1111111; // 8
    150 4'b1001: Y_r_1 = 7'b1101111; // 9
    151 4'b1010: Y_r_1 = 7'b1110111; // A
    152 4'b1011: Y_r_1 = 7'b1111100; // b
    153 4'b1100: Y_r_1 = 7'b0111001; // c
    154 4'b1101: Y_r_1 = 7'b1011110; // d
    155 4'b1110: Y_r_1 = 7'b1111001; // E
    156 4'b1111: Y_r_1 = 7'b1110001; // F
    157 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; // 0
    166 4'b0001: Y_r_2 = 7'b0000110; // 1
    167 4'b0010: Y_r_2 = 7'b1011011; // 2
    168 4'b0011: Y_r_2 = 7'b1001111; // 3
    169 4'b0100: Y_r_2 = 7'b1100110; // 4
    170 4'b0101: Y_r_2 = 7'b1101101; // 5
    171 4'b0110: Y_r_2 = 7'b1111101; // 6
    172 4'b0111: Y_r_2 = 7'b0000111; // 7
    173 4'b1000: Y_r_2 = 7'b1111111; // 8
    174 4'b1001: Y_r_2 = 7'b1101111; // 9
    175 4'b1010: Y_r_2 = 7'b1110111; // A
    176 4'b1011: Y_r_2 = 7'b1111100; // b
    177 4'b1100: Y_r_2 = 7'b0111001; // c
    178 4'b1101: Y_r_2 = 7'b1011110; // d
    179 4'b1110: Y_r_2 = 7'b1111001; // E
    180 4'b1111: Y_r_2 = 7'b1110001; // F
    181 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个七段数码管上就能显示数值。这就完成了将模拟数据转化为数字量的验证。

     

     

     

  • 相关阅读:
    除去String字符串里面指定的字符串
    JSON总结(java篇)
    关于tomcat文件下载配置
    在多行列表中id同名的<a>标签点击事件处理方法
    java Properties异常:Malformed uxxxx encoding.
    关于An association from the table refers to an unmapped class
    Java实现Mysql数据库自动备份
    Could not publish server configuration for Tomcat v6.0 Server at localhost.
    MySQL备份命令mysqldump参数说明与示例
    图解 | 原来这就是网络
  • 原文地址:https://www.cnblogs.com/kongtiao/p/2113210.html
Copyright © 2011-2022 走看看