設計背景:
模數轉換器,又稱a/d轉換器,簡稱adc,通常是指一個將模擬信號轉換為抗干擾性更強的數字信號的電子器件。一般的adc是將一個輸入電壓信號轉換為一個輸出的數字信號。由于數字信號本身不具有實際意義,僅僅表示一個相對大小,故任何一個adc都需要一個參考模擬量作為轉換標準。比較常見的參考標準為最大的可轉換信號大小,而輸出的數字量則表示輸入信號相對于參考信號的大小。本設計則通過對模數轉換芯片(tlc549)的采樣控制,實現一個簡易的數字電壓表。
設計原理:
tlc549典型的配置電路如下圖所示:
tlc549的端口描述如下:
tlc549是一個8位的串行模數轉換器,a/d轉換時間最大為17us,最大轉換速率為4mhz。下圖為tlc549的訪問時序,從圖中可以看出,tlc549的使用只需對外接輸入輸出時鐘(i/o clk)和芯片選擇(/cs)、輸入的模擬信號(analog in)的控制。
分析時序圖可知:當片選信號(/cs)拉低時,adc前一次的轉換數據(a)的最高位a7立即出現在數據線data out上,之后的數據在時鐘i/o clock的下降沿改變,可在i/o clock的上升沿讀取數據。轉換時,/cs要置為高電平。在設計操作時,要注意tsu(cs)、tconv、twh(cs)和i/o clock的頻率這幾個參數。tsu(cs)為cs拉低到i/o clock第一個時鐘到來的時間,至少要1.4us;twh(cs)為adc的轉換時鐘,不超過17us,tconv的值也不超過17us;i/o clock為 1.1mhz。其他參數可參考數據手冊。
由于adc是8位的,所以采樣的電壓值為:
v =(d*vref)/256
其中v為采樣的電壓值;d為adc轉換后讀取的8位二進制數;vref為參考電壓值,此處為2.5v。
設計架構圖:
本設計通過調節電位器rw1改變adc的模擬輸入值,數據采樣讀取后由數碼管顯示,最后用萬用表測量輸入電壓,并與讀取在數碼管上的數據(單位為mv)作比較。設計的架構圖如下:
設計架構圖對應端口的功能描述表:
tlc549_driver模塊采用序列機實現接口訪問時序,并且產生1mhz的adc_clk和采集到adc_data;control模塊,將采集到的adc數據(adc_data)換算成對應的電壓值,并經過二進制到bcd轉換以后傳送到數碼管;dig_led_drive模塊負責數碼管的驅動,將傳遞過來的數據顯示出來。
設計代碼:
tlc549_driver模塊代碼:
0moduletlc549_driver(clk,rst_n,en,adc_din,adc_clk,adc_cs_n,data,get_flag);
1
2inputclk;//系統50mhz時鐘輸入
3inputrst_n;//全局復位
4inputen;//adc轉換使能,高電平有效
5
6inputadc_din;//adc串行數據輸入
7
8outputregadc_clk;//adc時鐘信號輸出
9outputregadc_cs_n;//adc片選信號輸出
10outputregget_flag;//數據轉換完成標志
11outputreg[7:0]data;//adc轉換以后的電壓值
12
13reg[10:0]cnt1;//系統時鐘計數器
14reg[7:0]data_tmp;//數據寄存器
15
16//系統時鐘上升沿計數
17always@(posedgeclkornegedgerst_n)
18begin
19if(!rst_n)
20cnt1<=11'd0;
21elseif(!en)
22cnt1<=11'd0;
23elseif(cnt1==11'd1310)
24cnt1<=11'd0;
25else
26cnt1<=cnt1+1'b1;
27end
28
29always@(posedgeclkornegedgerst_n)
30begin
31if(!rst_n)
32begin
33adc_clk<=1'b0;
34adc_cs_n<=1'b1;
35data_tmp<=8'd0;
36data<=8'd0;
37end
38elseif(en)
39begin
40case(cnt1)
411:adc_cs_n<=1'b0;//1~71(tsu)
4271:beginadc_clk<=1;data_tmp[7]<=adc_din;end
4396:adc_clk<=0;
44121:beginadc_clk<=1;data_tmp[6]<=adc_din;end
45146:adc_clk<=0;
46171:beginadc_clk<=1;data_tmp[5]<=adc_din;end
47196:adc_clk<=0;
48221:beginadc_clk<=1;data_tmp[4]<=adc_din;end
49246:adc_clk<=0;
50271:beginadc_clk<=1;data_tmp[3]<=adc_din;end
51296:adc_clk<=0;
52321:beginadc_clk<=1;data_tmp[2]<=adc_din;end
53346:adc_clk<=0;
54371:beginadc_clk<=1;data_tmp[1]<=adc_din;end
55396:adc_clk<=0;
56421:beginadc_clk<=1;data_tmp[0]<=adc_din;end
57446:beginadc_clk<=0;adc_cs_n<=1'b1;get_flag<=1;end
58447:begindata<=data_tmp;get_flag<=0;end//447~1310(twh)
591310:;
60default:;
61endcase
62end
63else
64begin
65adc_cs_n<=1'b1;
66adc_clk<=1'b0;
67end
68end
69
70endmodule
control模塊代碼:
0modulecontrol(clk,rst_n,get_flag,adc_data,seg_data);
1
2inputclk;//系統時鐘輸入
3inputrst_n;//系統復位
4inputget_flag;//adc采集數據完成標志
5input[7:0]adc_data;//adc采集數據輸入
6
7outputreg[23:0]seg_data;//數碼管待顯示數據
8
9reg[3:0]qianwei;//千位
10reg[3:0]baiwei;//百位
11reg[3:0]shiwei;//十位
12reg[3:0]gewei;//個位
13reg[15:0]tenvalue;//采樣的電壓值
14
15//采集電壓值計算
16always@(posedgeclkornegedgerst_n)
17begin
18if(!rst_n)
19tenvalue<=0;
20elseif(get_flag)//新的數據采集完成,可以進行計算
21tenvalue<=(adc_data*100*25)/256;
22end
23
24//二進制轉bcd值
25always@(posedgeclkornegedgerst_n)
26begin
27if(!rst_n)
28begin
29qianwei<=0;
30baiwei<=0;
31shiwei<=0;
32gewei<=0;
33end
34else
35begin
36qianwei<=tenvalue/1000;//2
37baiwei<=(tenvalue/100)%10;//5
38shiwei<=(tenvalue/10)%10;//0
39gewei<=tenvalue%10;//0
40end
41end
42
43//數碼管顯示數值
44always@(posedgeclkornegedgerst_n)
45begin
46if(!rst_n)
47seg_data<=0;
48else
49seg_data<={
50qianwei,//千位
51baiwei,//百位
52shiwei,//十位
53gewei,//個位
548'hff//空閑
55};
56end
57
58endmodule
dig_led_drive模塊代碼:
0
1
2
3moduledig_led_drive(clk,rst_n,data,dig_led_seg,dig_led_sel);
4
5inputclk;//系統時鐘輸入
6inputrst_n;//系統復位
7input[23:0]data;//待顯示數據
8
9output[7:0]dig_led_seg;//數碼管段選
10output[2:0]dig_led_sel;//數碼管位選
11
12parametersystem_clk=50_000_000;
13
14// ?localparam cnt1_max = 24;
15localparamcnt1_max=system_clk/1000/2-1;
16
17reg[14:0]cnt1;//分頻計數器
18regclk_1k;//掃描時鐘,1khz
19reg[2:0]sel_r;//數碼管位選
20reg[7:0]seg_r;//數碼管段選
21reg[3:0]disp_data;//單位顯示數據緩存
22
23//1khz時鐘分頻計數器
24always@(posedgeclk)
25begin
26if(!rst_n)cnt1<=0;
27elseif(cnt1==cnt1_max)cnt1<=0;
28elsecnt1<=cnt1+1'b1;
29end
30
31//得到1khz時鐘
32always@(posedgeclkornegedgerst_n)
33begin
34if(!rst_n)
35clk_1k<=0;
36elseif(cnt1==cnt1_max)
37clk_1k<=~clk_1k;
38end
39
40//位選信號控制
41always@(posedgeclk_1kornegedgerst_n)
42begin
43if(!rst_n)
44sel_r<=3'd0;
45elseif(sel_r==3'd3)
46sel_r<=3'd0;
47else
48sel_r<=sel_r+1'b1;
49end
50
51//根據不同的數碼管位選擇不同的待顯示數據
52always@(*)
53begin
54if(!rst_n)
55disp_data=4'd0;
56else
57begin
58case(sel_r)
593'd0:disp_data=data[23:20];
603'd1:disp_data=data[19:16];
613'd2:disp_data=data[15:12];
623'd3:disp_data=data[11:8];
633'd4:disp_data=data[7:4];
643'd5:disp_data=data[3:0];
65default:disp_data=4'd0;
66endcase
67end
68end
69
70//數據譯碼,將待顯示數據翻譯為符合數碼管顯示的編碼
71always@(*)
72begin
73if(!rst_n)
74seg_r=8'hff;
75else
76begin
77case(disp_data)
784'd0:seg_r=8'hc0;
794'd1:seg_r=8'hf9;
804'd2:seg_r=8'ha4;
814'd3:seg_r=8'hb0;
824'd4:seg_r=8'h99;
834'd5:seg_r=8'h92;
844'd6:seg_r=8'h82;
854'd7:seg_r=8'hf8;
864'd8:seg_r=8'h80;
874'd9:seg_r=8'h90;
884'd10:seg_r=8'h88;
894'd11:seg_r=8'h83;
904'd12:seg_r=8'hc6;
914'd13:seg_r=8'ha1;
924'd14:seg_r=8'h86;
934'd15:seg_r=8'h8e;
94default:seg_r=8'hff;
95endcase
96end
97end
98
99assigndig_led_seg=seg_r;
100assigndig_led_sel=sel_r;
101
102endmodule
ad_tlc549頂層模塊代碼:
0modulead_tlc549(clk,rst_n,adc_din,adc_clk,adc_cs_n,dig_led_sel,dig_led_seg);
1
2inputclk;
3inputrst_n;
4inputadc_din;
5
6outputadc_clk;
7outputadc_cs_n;
8output[2:0]dig_led_sel;
9output[7:0]dig_led_seg;
10
11wireget_flag;
12wire[7:0]adc_data;
13wire[23:0]seg_data;
14
15tlc549_drivertlc549_driver(
16.clk(clk),
17.rst_n(rst_n),
18.en(1'b1),
19.adc_din(adc_din),
20.adc_clk(adc_clk),
21.adc_cs_n(adc_cs_n),
22.data(adc_data),
23.get_flag(get_flag)
24);
25
26controlcontrol(
27.clk(clk),
28.rst_n(rst_n),
29.get_flag(get_flag),
30.adc_data(adc_data),
31.seg_data(seg_data)
32);
33
34dig_led_drivedig_led_drive(
35.clk(clk),
36.rst_n(rst_n),
37.data(seg_data),
38.dig_led_seg(dig_led_seg),
39.dig_led_sel(dig_led_sel)
40);
41
42endmodule
ad_tlc549_tb頂層測試代碼如下:
0`timescale1ns/1ps
1
2modulead_tlc549_tb;
3
4regclk;
5regrst_n;
6regadc_din;
7
8wireadc_clk;
9wireadc_cs_n;
10wire[2:0]dig_led_sel;
11wire[7:0]dig_led_seg;
12
13initialbegin
14clk=1;
15rst_n=0;
16adc_din=0;
17#200.1
18rst_n=1;
19
20#1400adc_din=1;//aa
21#1000adc_din=0;
22#1000adc_din=1;
23#1000adc_din=0;
24#1000adc_din=1;
25#1000adc_din=0;
26#1000adc_din=1;
27#1000adc_din=0;
28
29#17000
30#1400adc_din=1;//98
31#1000adc_din=0;
32#1000adc_din=0;
33#1000adc_din=1;
34#1000adc_din=1;
35#1000adc_din=0;
36#1000adc_din=0;
37#1000adc_din=0;
38
39end
40
41ad_tlc549ad_tlc549_dut(
42.clk(clk),
43.rst_n(rst_n),
44.adc_din(adc_din),
45.adc_clk(adc_clk),
46.adc_cs_n(adc_cs_n),
47.dig_led_sel(dig_led_sel),
48.dig_led_seg(dig_led_seg)
49);
50
51always#10clk=~clk;
52
53endmodule
仿真圖:
設計仿真圖如下所示:
來源:網絡
以上是網絡信息轉載,信息真實性自行斟酌。