本实验是用ADC0809CCN进行数据采样,并用7段数码管进行显示。

  ADC0809由一个8路模拟开关、一个地址锁存与译码器、一个A/D转换器和一个三态输出锁存器组成。多路开关可选通8个模拟通道,允许8路模拟量分时输入,共用A/D转换器进行转换。三态输出锁器用于锁存A/D转换完的数字量,当OE端为高电平时,才可以从三态输出锁存器取走转换完的数据。如下图所示。

时序图(本实验用上升沿去采数据):

原理图:

工作方式:

ALE为地址锁存允许输入线,高电平有效。当ALE线为高电平时,地址锁存与译码器将A,B,C三条地址线的地址信号进行锁存,经译码后被选中的通道的模拟量进入转换器进行转换。A,B和C为地址输入线,用于选通IN0-IN7上的一路模拟量输入,这里选通IN0。START为转换启动信号。当START上跳沿时,所有内部寄存器清零;下跳沿时,开始进行A/D转换;在转换期间,START应保持低电平。EOC为转换结束信号,在转换期间EOC为低。当EOC在为高电平时,表明转换结束;否则,表明正在进行A/D转换。OE为输出允许信号,用于控制三条输出锁存器向FPGA输出转换得到的数据。OE=1,输出转换得到的数据;OE=0,输出数据线呈高阻状态。D7-D0为数字量输出线,可以得到状态图。

状态图:

代码实现:

adc0809_control.v

 module adc0809_control(
//input
sys_clk,
rst_n,
eoc,//adc转换结束信号标志
data,//adc转换出的数据, //ouput
clk_adc,//给adc的时钟500HZ
ale,//adc地址锁存
start,//启动adc
address,//adc地址选通
oe,//控制adc数据传出
seg_data//传给数码显示
);
input sys_clk;//27MHZ
input rst_n;
input eoc;
input [:] data; output clk_adc;
output ale;
output start;
output [:] address;
output oe;
output [:] seg_data;
/*********************************************/
parameter IDLE = 'd0,
ALE = 'd1,
START_P = 'd2,
START_N = 'd3,
CHECK_EOC_P = 'd4,
CHECK_EOC_N = 'd5,
OE = 'd6,
SEND_DATA = 'd7;
/*********************************************/
//产生500kHZ的频率
reg clk_adc;
reg [:] cnt;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n) begin
cnt <= 'd0;
clk_adc <= 'b0;
end
else if(cnt == 'd26)
begin
cnt <= 'd0;
clk_adc <= ~clk_adc;
end
else
cnt <= cnt + 'b1;
/*********************************************/
reg start;
reg ale;
reg oe;
reg [:] data_temp;
reg [:] state;
//always @(clk_adc or rst_n or eoc)//用组合逻辑方式不行,采集不到数据
always @(posedge clk_adc or negedge rst_n)
if(!rst_n) begin
start <= 'b0;
ale <= 'b0;
oe <= 'b0;
data_temp <= 'd0;
state <= IDLE;
end
else
case(state)
IDLE: begin
ale <= 'b0;
start <= 'b0;
oe <= 'b0;
state <= ALE;
end ALE: begin
ale <= 'b1;
start <= 'b0;
state <= START_P;
end START_P: begin
ale <= 'b0;//1
start <= 'b1;
state <= START_N;
end START_N: begin
ale <= 'b0;
start <= 'b0;
state <= CHECK_EOC_P;
end CHECK_EOC_P: begin
if(eoc == 'b1)
state = CHECK_EOC_P;
else
state = CHECK_EOC_N;//检测到了低电平,说明开始转换
end CHECK_EOC_N: begin
if(eoc == 'b0)
state <= CHECK_EOC_N;//等待转换的结束
else
state <= OE;
end OE: begin
oe <= 'b1;
state <= SEND_DATA;
end SEND_DATA: begin
data_temp <= data;
state <= IDLE;
end default: begin
ale <= 'b0;
start <= 'b0;
oe <= 'b0;
state <= IDLE;
end
endcase
/*********************************************/
assign address = 'b000;//选通IN0
assign seg_data = data_temp;
/*********************************************/
endmodule

display_control.v

 module  display_control(
//input
sys_clk,
rst_n,
seg_data, //output
slec_wei,
slec_duan
);
input rst_n;
input [:] seg_data;
input sys_clk; output [:] slec_wei;
output [:] slec_duan;
/*****************************************/
parameter SEG_NUM0 = 'h3f,//c0,
SEG_NUM1 = 'h06,//f9,
SEG_NUM2 = 'h5b,//a4,
SEG_NUM3 = 'h4f,//b0,
SEG_NUM4 = 'h66,//99,
SEG_NUM5 = 'h6d,//92,
SEG_NUM6 = 'h7d,//82,
SEG_NUM7 = 'h07,//F8,
SEG_NUM8 = 'h7f,//80,
SEG_NUM9 = 'h6f,//90,
SEG_NUMa = 'h77,
SEG_NUMb = 'h7c,
SEG_NUMc = 'h39,
SEG_NUMd = 'h5e,
SEG_NUMe = 'h79,
SEG_NUMf = 'h71;
/*****************************************/
reg[:] cnt;
always @ (posedge sys_clk or negedge rst_n)
if(!rst_n) cnt <= 'd0;
else cnt <= cnt+'b1;
/*****************************************/
wire[:] num; //用两位数码管显示
assign num = cnt[] ? seg_data[:] : seg_data[:];
assign slec_wei[] = cnt[];
assign slec_wei[] = ~cnt[]; //由于板上数码管是四位,另两位不点亮
assign slec_wei[] = 'b1;
assign slec_wei[] = 'b1; reg [:] slec_duan;
always @ (posedge sys_clk)
case(num) //进行编码
'h0: slec_duan <= SEG_NUM0;
'h1: slec_duan <= SEG_NUM1;
'h2: slec_duan <= SEG_NUM2;
'h3: slec_duan <= SEG_NUM3;
'h4: slec_duan <= SEG_NUM4;
'h5: slec_duan <= SEG_NUM5;
'h6: slec_duan <= SEG_NUM6;
'h7: slec_duan <= SEG_NUM7;
'h8: slec_duan <= SEG_NUM8;
'h9: slec_duan <= SEG_NUM9;
'ha: slec_duan <= SEG_NUMa;
'hb: slec_duan <= SEG_NUMb;
'hc: slec_duan <= SEG_NUMc;
'hd: slec_duan <= SEG_NUMd;
'he: slec_duan <= SEG_NUMe;
'hf: slec_duan <= SEG_NUMf;
default:slec_duan <= SEG_NUM0;
endcase
/*****************************************/
endmodule

adc0809_top.v

 module adc0809_top(//input
sys_clk,
rst_n,
eoc,
data, //output
clk_adc,
ale,
start,
address,
oe,
slec_wei,
slec_duan
);
input sys_clk;//27MHZ
input rst_n;
input [:] data;
input eoc; output clk_adc;
output ale;
output start;
output [:] address;
output oe;
output [:] slec_wei;
output [:] slec_duan; wire [:] seg_data; adc0809_control u1(
//input
.sys_clk(sys_clk),
.rst_n(rst_n),
.eoc(eoc),//adc转换结束信号标志
.data(data),//adc转换出的数据, //ouput
.clk_adc(clk_adc),//给adc的时钟500HZ
.ale(ale),//adc地址锁存
.start(start),//启动adc
.address(address),//adc地址选通
.oe(oe),//控制adc数据传出
.seg_data(seg_data)//传给数码显示
); display_control u2(
//input
.sys_clk(sys_clk),
.rst_n(rst_n),
.seg_data(seg_data), //output
.slec_wei(slec_wei),
.slec_duan(slec_duan)
);
endmodule

仿真代码:

 `timescale  ns/  ps
module adc0809_top_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg [:] data;
reg eoc;
reg rst_n;
reg sys_clk;
// wires
wire [:] address;
wire ale;
wire clk_adc;
wire oe;
wire [:] slec_duan;
wire [:] slec_wei;
wire start; // assign statements (if any)
adc0809_top i1 (
// port map - connection between master ports and signals/registers
.address(address),
.ale(ale),
.clk_adc(clk_adc),
.data(data),
.eoc(eoc),
.oe(oe),
.rst_n(rst_n),
.slec_duan(slec_duan),
.slec_wei(slec_wei),
.start(start),
.sys_clk(sys_clk)
);
initial
begin
sys_clk =;
rst_n = ;
#;
rst_n = ;
end
always # sys_clk = ~sys_clk; initial begin
data = 'h0;
eoc = ;
end always @(negedge start)
begin
#;
eoc = ;
data <= data + 'b1;
#;
eoc = ;
end
endmodule

仿真波形:

调试过程的心情:

  看完人家的例子,时序图也看明白了,然后开始写自己的代码,在编译时也遇到很奇怪的问题,如下图,代码中找了许久都没找到,这让很头疼,后来我就把关于case这段语句剪切掉,只留接口定义部分,进行编译,编译OK,我在把刚才剪切掉的代码复制原位置(完全是一摸一样),编译既然通过了,很郁闷,这个问题一直没有弄明白,实在想不通,就跳过这个问题,既然编译通过了,那赶紧下载到板子上去验证吧,下完之后,显示两个0,变阻器无论怎么调都没用,哎,无语了,只能回过头在检查代码,看是否哪里有错误。实在检查不出来,只有仿真看时序对不对哦,仿真后还真没看出来有啥问题(很可能当时仿真代码没有写好,其实也没仔细的看波形),然后反复的看别人的代码,对照自己的代码是否哪里写的不对。最终把这个语句always @(clk_adc or rst_n or eoc)改为时序逻辑always @(posedge clk_adc or negedge rst_n)就可以了 ,终于看到了数码显示数据了,调电位器,数据也在变动,很高兴啊。。。。

总结:

1、例子最好找一个比较规范的例子,可以到网上收集相同的例子,进行参考对比。

2、遇到问题时,不要气馁,沉住气。问题总会解决的。

基于Verilog HDL的ADC0809CCN数据采样的更多相关文章

  1. 基于Verilog HDL 各种实验

    菜鸟做的的小实验链接汇总:           1.基于Verilog HDL 的数字时钟设计 2.乘法器 3.触发器(基本的SR触发器.同步触发器.D触发器) 4.基于Verilog HDL的ADC ...

  2. 基于Verilog HDL 的数字电压表设计

    本次实验是在“基于Verilog HDL的ADC0809CCN数据采样”实验上进一步改进,利用ADC0809采集到的8位数据,进行BCD编码,以供查表方式相加进行显示,本次实验用三位数码管. ADC0 ...

  3. 基于Verilog HDL整数乘法器设计与仿真验证

    基于Verilog HDL整数乘法器设计与仿真验证 1.预备知识 整数分为短整数,中整数,长整数,本文只涉及到短整数.短整数:占用一个字节空间,8位,其中最高位为符号位(最高位为1表示为负数,最高位为 ...

  4. 基于Verilog HDL 的数字时钟设计

    基于Verilog HDL的数字时钟设计 一.实验内容:     利用FPGA实现数字时钟设计,附带秒表功能及时间设置功能.时间设置由开关S1和S2控制,分别是增和减.开关S3是模式选择:0是正常时钟 ...

  5. 基于Verilog HDL的二进制转BCD码实现

    在项目设计中,经常需要显示一些数值,比如温湿度,时间等等.在数字电路中数据都是用二进制的形式存储,要想显示就需要进行转换,对于一个两位的数值,对10取除可以得到其十位的数值,对10取余可以得到个位的数 ...

  6. 基于Verilog HDL的超前进位全加器设计

    通常我们所使用的加法器一般是串行进位,将从输入的ci逐位进位地传递到最高位的进位输出co,由于电路是有延迟的,这样的长途旅行是需要时间的,所以为了加快加法器的运算,引入了超前进位全加器. 全加器的两个 ...

  7. paper:基于verilog HDL 的高速可综合FSM设计

    1.寄存器输出型状态机 VS 组合逻辑输出型状态机 2.状态编码方法 这块讲的不好,也比较少. 3.系统设计中模块划分的指导性原则

  8. 自己动手写处理器之第二阶段(2)——Verilog HDL简单介绍

    将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第六篇.我尽量每周四篇 2.3 Verilog HDL简单介绍 本书实现的OpenMIPS处理器是使用Verilog HDL编 ...

  9. 关于初次使用Verilog HDL语言需要懂的基本语法

    关于初次使用Verilog HDL语言需要懂的基本语法 1.常量 数字表达式全面的描述方式为:<位宽><进制><数字> 8’b10101100,表示位宽为8的二进制 ...

随机推荐

  1. Entity Framework技巧系列之三 - Tip 9 – 12

    提示9. 怎样直接删除一个对象而无需检索它 问题 最常见的删除Entity Framework中实体的方式是将你要删除的实体传入Context中并像如下这样删除: 1 // 按ID查找一个类别 2 / ...

  2. Lowest Bit

    Lowest Bit Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Su ...

  3. 在Linux中设置共享目录

    1.  是否安装了samba服务 sudo apt-get install samba sudo apt-get install smbfs 2.  创建需要共享的目录/ home/usr/share ...

  4. adb 卸载android系统程序

    下面是通过 pm list packages -f 列出手机中的软件,然后跟模拟器中的软件进行对比后得出的可以安全卸载的列表.   注意:卸载之后就没有Google Market了,还想用google ...

  5. queue(),dequeue()

    这两个方法,一个是往里面添加队列,一个是执行队列 也是分静态方法和实例方法, 同样,实例方法最后调用静态方法 源码主要分析一下延迟delay方法,如何起作用的,写的有点仓促,先记录一下 在这里参照了网 ...

  6. Linq序列间的操作

    一.Union并集操作相同的数据只显示一次 二.Concact连接 相同的数据也会重复显示 三.except差集 我有的你没有的显示 四.intersect交集相同的显示 五.zip序列的合并 六.d ...

  7. xmlHTTP技术资料

    一.数据库远程管理技术 基于互联网的广域网现代应用中的一个重要环节是数据库远程监控.首先简单回顾一下互联网上的数据库远程管理技术的发展过程和方式: 早期通过编写CGI-BIN程序模块进行数据库远程管理 ...

  8. RING0,RING1,RING2,RING3

    Intel的CPU将特权级别分为4个级别:RING0,RING1,RING2,RING3.Windows只使用其中的两个级别RING0和RING3,RING0只给操作系统用,RING3谁都能用.如果普 ...

  9. ViewPager和View组合 实现页面的切换

    //--------------主页面------------------------------- package com.bw.test; import java.util.ArrayList;i ...

  10. C语言开发工具

    1.编写程序的工具: indent命令将自动调整C代码的缩进风格,个人比较喜欢indent -kr 2.编译C语言程序: 1.gcc编译器: gcc是一个ANSI C兼容编译器,C++编译器也可以编译 ...