lcytms
发表于 2017-2-8 20:29:05
进行分析综合检查。
进行仿真设置。
查看仿真结果。
片选信号cs_n被拉低后,adc_clk依次输出8个脉冲。
adc_clk时钟上升沿采样,下降沿时数据更新。
随后片选信号cs_n置高。
时间间隔与设计要求一致。
仿真功能正确。
lcytms
发表于 2017-2-8 20:32:31
本帖最后由 lcytms 于 2017-2-8 20:35 编辑
向工程文件夹添加第四讲的数码管模块seg7.v。
module seg7 (clk, rst_n, data, sel, seg);
input clk, rst_n;
input data;
output reg sel;
output reg seg;
reg clk_1k;
parameter T1ms = 25_000; //half_width
reg count;
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
count <= 0;
clk_1k <= 1;
end
else
begin
if (count < T1ms - 1)
begin
count <= count + 20'b1;
end
else
begin
count <= 0;
clk_1k <= ~clk_1k;
end
end
end
reg state;
reg data_temp;
always @ (posedge clk_1k or negedge rst_n)
begin
if (!rst_n)
begin
sel <= 3'b000;
state <= 0;
end
else
begin
case (state)
0 : begin
sel <= 3'b000;
data_temp <= data;
state <= 1;
end
1 : begin
sel <= 3'b001;
data_temp <= data;
state <= 2;
end
2 : begin
sel <= 3'b010;
data_temp <= data;
state <= 3;
end
3 : begin
sel <= 3'b011;
data_temp <= data;
state <= 4;
end
4 : begin
sel <= 3'b100;
data_temp <= data;
state <= 5;
end
5 : begin
sel <= 3'b101;
data_temp <= data;
state <= 0;
end
default : state <= 0;
endcase
end
end
always @ (*)
begin
if (!rst_n)
begin
seg = 8'b1111_1111; //null
end
else
begin
case (data_temp)
0 : seg = 8'b1100_0000; //d0
1 : seg = 8'b1111_1001; //d1
2 : seg = 8'b1010_0100; //d2
3 : seg = 8'b1011_0000; //d3
4 : seg = 8'b1001_1001; //d4
5 : seg = 8'b1001_0010; //d5
6 : seg = 8'b1000_0010; //d6
7 : seg = 8'b1111_1000; //d7
8 : seg = 8'b1000_0000; //d8
9 : seg = 8'b1001_0000; //d9
10 : seg = 8'b1000_1000; //dA
11 : seg = 8'b1000_0011; //db
12 : seg = 8'b1100_0110; //dC
13 : seg = 8'b1010_0001; //dd
14 : seg = 8'b1000_0110; //dE
15 : seg = 8'b1000_1110; //dF
default : seg = 8'b1111_1111; //null
endcase
end
end
endmodule
lcytms
发表于 2017-2-8 20:37:23
本帖最后由 lcytms 于 2017-2-8 20:45 编辑
新建数码管数据预处理模块pre_seg7.v。
module pre_seg7(clk, rst_n, data_in, BCD4);
input clk, rst_n;
input data_in;
output BCD4; //数码管显示数据
reg data; //转换后的数据
parameter T100ms = 5_000_000; // time to update data for display
reg cnt100ms;
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
cnt100ms <= 0;
data <= 0;
end
else
begin
if (cnt100ms < T100ms - 1)
cnt100ms <= cnt100ms + 26'd1;
else
begin
cnt100ms <= 0;
data <= (data_in * 2500) / 256;
end
end
end
assign BCD4[ 3: 0] =data % 10;
assign BCD4[ 7: 4] =data / 10 % 10;
assign BCD4 =data / 100 % 10;
assign BCD4 =data / 1000 % 10;
endmodule
lcytms
发表于 2017-2-8 20:47:43
本帖最后由 lcytms 于 2017-2-8 20:50 编辑
新建数码管显示后处理模块post_seg7.v。
module post_seg7 (sel, seg_o, seg);
input sel;
input seg_o;
output reg seg;
always @ (*)
begin
case (sel)
0 : seg = 8'b1111_1111; // null
1 : seg = 8'b1111_1111; // null
2 : seg = {1'b0, seg_o}; // add decimal point
default : seg = seg_o;
endcase
end
endmodule
lcytms
发表于 2017-2-8 20:53:42
本帖最后由 lcytms 于 2017-2-8 20:55 编辑
新建top.v顶层模块,将以上四个模块都加入到top.v顶层模块中进行例化。
将top.v模块设置为顶层模块。
编写top.v模块如下。
module top(clk, rst_n, adc_in, cs_n, adc_clk, sel, seg);
input clk, rst_n;
input adc_in; //输入串行数据
output adc_clk; //输出 I/O CLOCK
output cs_n; //片选信号 低有效
output sel;
output seg;
wire data8;
wire BCD4;
wire seg_o;
adc adc(.clk(clk), .rst_n(rst_n), .sid(adc_in), .adc_clk(adc_clk), .cs_n(cs_n), .data(data8));
pre_seg7 pre_seg7(.clk(clk), .rst_n(rst_n), .data_in(data8), .BCD4(BCD4));
seg7 seg7 (.clk(clk), .rst_n(rst_n), .data({8'b0, BCD4}), .sel(sel), .seg(seg_o));
post_seg7 post_seg7 (.sel(sel), .seg_o(seg_o), .seg(seg));
endmodule
lcytms
发表于 2017-2-8 20:58:06
本帖最后由 lcytms 于 2017-2-8 20:59 编辑
运行.tcl文件设置好FPGA管脚
将ad.tcl文件拷贝到工程文件夹的根目录下面。
在主界面Tools菜单下选择Tcl scripts,运行ad.tcl文件,对FPGA芯片管脚进行设置。
ad.tcl文件相关内容如下所示。
#set_global_assignment -name FAMILY "Cyclone IV"
#set_global_assignment -name DEVICE ep4ce6e22c8n
set_location_assignment PIN_23 -to clk
# KEY 轻触按键
set_location_assignment PIN_69 -to rst_n
# AD
set_location_assignment PIN_99 -toadc_clk
set_location_assignment PIN_87 -toadc_in
set_location_assignment PIN_98 -tocs_n
# SEG7 x 8 七段数码管
set_location_assignment PIN_119 -to sel
set_location_assignment PIN_115 -to sel
set_location_assignment PIN_114 -to sel
set_location_assignment PIN_127 -to seg
set_location_assignment PIN_128 -to seg
set_location_assignment PIN_124 -to seg
set_location_assignment PIN_121 -to seg
set_location_assignment PIN_120 -to seg
set_location_assignment PIN_126 -to seg
set_location_assignment PIN_129 -to seg
set_location_assignment PIN_125 -to seg
lcytms
发表于 2017-2-8 21:01:10
FPGA芯片配置结果如图所示。
lcytms
发表于 2017-2-8 21:03:34
.sof文件下载到FPGA
全编译FPGA工程,生成.sof文件,连接至芯ZX-2开发板并上电。
打开Programmer通过Jtag口,将.sof文件下载到FPGA进行在线仿真。
.sof文件下载界面如下图所示。
lcytms
发表于 2017-2-8 21:06:08
本帖最后由 lcytms 于 2017-2-8 21:08 编辑
开发板运行效果
开发板运行效果如下图所示。
经检查,开发板运行效果与设计相符。
程序下载后,使用一字改锥调整蓝色可变电阻器的阻值。
观察数码管显示电压值,并使用数字万用表测量开发板上的AD芯片模拟电压输入脚(2脚ANIN)的实际电压,比较二者是否一致。
比如,数码管显示1.250,同时数字万用表测得模拟电压值为1.24V。
功能验证正确。
lcytms
发表于 2017-2-8 21:09:03
本帖最后由 lcytms 于 2017-2-9 11:29 编辑
好了,今天的课程就讲到这里。
通过今天的课程,我们学习了AD转换芯片工作的基本原理,并对AD驱动逻辑电路进行了建模、仿真,结合第四讲的数码管一起编写一个完整的演示逻辑,进行了下板检查。
希望大家掌握AD转换芯片工作的基本原理,并熟练运用Verilog语言编写相关驱动逻辑。
另外,我们在第二十一讲 SPI中讲到了SPI串行外设接口的基本原理,大家可以结合本次课程学习的基于SPI协议进行通信控制的AD转换芯片TLC549驱动应用案例,加深对SPI驱动逻辑的理解。
更复杂的知识和技巧我们将逐步通过后面的课程展现给大家。
课程到此结束,谢谢大家的关注!