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

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

  ADC0809的8位数数据BCD编码方式,低四位与高四位分开进行编码,其对应值我也是从网上得来的,具体对应值请看代码,编完码得到12位宽的数据后,对两个编码进行相加,如代码中的cout[11:0] = L[11:0] + H[11:0],这里注意,高四位[11:8]、中四位[7:4]、低四位[3:0]。

假如ADC0809得到的数据是8'hb4,从代码中可以看到,低四位4'h4:  L <= 12'h008;高四位4'hb:  H <= 12'h352;,H+L = 12’h35A,低位为A,大于9,向中位产生进位C0= 1,其低位得加6得到0,故cout[11:0]=12'h360,电压也就是3.60V,然后把360送给数码管进行显示。同理如果中位相加大于9也得向高位进位C1,此时的中位要变为加6后的值。

代码实现:

display_control.v

  1 module  display_control(
  2                         //input
  3                         sys_clk,//27MHZ
  4                         rst_n,
  5                         seg_data,//ADC0809传送进来的数据
  6                         
  7                         //output
  8                         slec_wei,
  9                         slec_duan
 10                     );
 11 input rst_n;
 12 input [7:0] seg_data;
 13 input sys_clk;
 14 
 15 output [3:0] slec_wei;
 16 output [6:0] slec_duan;
 17 
 18 /*****************************************/
 19 parameter     SEG_NUM0     = 7'h3f,
 20             SEG_NUM1     = 7'h06,
 21             SEG_NUM2     = 7'h5b,
 22             SEG_NUM3     = 7'h4f,
 23             SEG_NUM4     = 7'h66,
 24             SEG_NUM5     = 7'h6d,
 25             SEG_NUM6     = 7'h7d,
 26             SEG_NUM7     = 7'h07,
 27             SEG_NUM8     = 7'h7f,
 28             SEG_NUM9     = 7'h6f,
 29             SEG_NUMa    = 7'h77,
 30             SEG_NUMb    = 7'h7c,
 31             SEG_NUMc    = 7'h39,
 32             SEG_NUMd    = 7'h5e,
 33             SEG_NUMe    = 7'h79,
 34             SEG_NUMf    = 7'h71;
 35 parameter   T5MS         = 18'd134_999;
 36 /************************************/
 37 //低四位BCD编码
 38 reg [11:0] L;
 39 always @ (posedge sys_clk)
 40     case(seg_data[3:0]) //L = n * 12'h002(n=1、2、3、、f)
 41         4'h1:        L <= 12'h002;
 42         4'h2:        L <= 12'h004;
 43         4'h3:        L <= 12'h006;
 44         4'h4:        L <= 12'h008;
 45         4'h5:        L <= 12'h010;
 46         4'h6:        L <= 12'h012;
 47         4'h7:        L <= 12'h014;
 48         4'h8:        L <= 12'h016;
 49         4'h9:        L <= 12'h018;
 50         4'ha:        L <= 12'h020;
 51         4'hb:        L <= 12'h022;
 52         4'hc:        L <= 12'h024;
 53         4'hd:        L <= 12'h026;
 54         4'he:        L <= 12'h028;
 55         4'hf:        L <= 12'h030;
 56         default :    L <= 12'h000;
 57     endcase
 58 /************************************/
 59 //高四位BCD编码
 60 reg [11:0] H;
 61 always @ (posedge sys_clk)
 62     case(seg_data[7:4])  //H = n * 12'h032(n=1、2、3、、f)
 63         4'h1:        H <= 12'h032;  //12'b0000_0011_0010;
 64         4'h2:        H <= 12'h064;  //12'b0000_0110_0100;
 65         4'h3:        H <= 12'h096;  //12'b0000_1001_0110;
 66         4'h4:        H <= 12'h128;  //12'b0001_0010_1000;
 67         4'h5:        H <= 12'h160;  //12'b0001_0110_0000;
 68         4'h6:        H <= 12'h192;  //12'b0001_1001_0010;
 69         4'h7:        H <= 12'h224;  //12'b0010_0010_0100;
 70         4'h8:        H <= 12'h256;  //12'b0010_0101_0110;
 71         4'h9:        H <= 12'h288;  //12'b0010_1000_1000;
 72         4'ha:        H <= 12'h320;  //12'b0011_0010_0000;
 73         4'hb:        H <= 12'h352;  //12'b0011_0101_0010;
 74         4'hc:        H <= 12'h384;  //12'b0011_1000_0100;
 75         4'hd:        H <= 12'h416;  //12'b0100_0001_0110;
 76         4'he:        H <= 12'h448;  //12'b0100_0100_1000;
 77         4'hf:        H <= 12'h480;  //12'b0100_1000_0000;
 78         default :     H <= 12'h000;  //12'b0000_0000_0000;
 79     endcase
 80 /************************************/
 81 //判断低四位是否大于9并进位
 82 reg c0;
 83 always @ (posedge sys_clk)
 84 begin
 85     if(H[3:0] + L[3:0] > 4'd9) 
 86         c0 <= 1;
 87     else
 88         c0 <= 0;
 89 end
 90 /************************************/
 91 //判断中间四位是否大于9并进位
 92 reg c1;
 93 always @(posedge sys_clk) 
 94 begin
 95     if(H[7:4] + L[7:4] > 4'd9) 
 96         c1 <= 1;
 97     else
 98         c1 <= 0;
 99 end
100 /***********************************************/
101 //对进位进行计算,中四位减去2,低四位加上1,是为了校准显示电压与实测电压更为接近,根据情况而定
102 reg [11:0] cout; 
103 always @(c1 or c0)
104 begin
105     case({c1,c0})
106         2'b00: begin 
107             cout[11:8] <= H[11:8] + L[11:8];
108             cout[7:4] <= H[7:4] + L[7:4] - 4'd2;//减去4'd2是为了校准显示电压,与实际测试更为接近
109             cout[3:0] <= H[3:0] + L[3:0] + 1'd1;//减去1'd1是为了校准显示电压,与实际测试更为接近
110         end 
111         
112         2'b01: begin 
113             if((H[7:4] + L[7:4] + 4'b0001) > 9) begin  
114                 cout[11:8] <= H[11:8] + L[11:8] + 4'b0001;
115                 cout[7:4] <= H[7:4] + L[7:4] + 4'b0111 - 4'd2;//加上6并加上来自低位上的进位
116                 cout[3:0] <= H[3:0] + L[3:0]+ 4'b0110 + 1'd1;//加上6
117             end
118             else begin 
119                 cout[11:8] <= H[11:8] + L[11:8];
120                 cout[7:4] <= H[7:4] + L[7:4] + 4'b0001 - 4'd2;
121                 cout[3:0] <= H[3:0] + L[3:0] + 4'b0110 + 1'd1;
122             end 
123         end
124         
125         2'b10:begin 
126             cout[11:8] <= H[11:8] + L[11:8] + 4'b0001;
127             cout[7:4] <= H[7:4] + L[7:4] + 4'b0110 - 4'd2;
128             cout[3:0] <= H[3:0] + L[3:0] + 1'd1;
129         end  
130         
131         2'b11:begin 
132             cout[11:8] <= H[11:8] + L[11:8] + 4'b0001;
133             cout[7:4] <= H[7:4] + L[7:4] + 4'b0110 - 4'd2;
134             cout[3:0] <= H[3:0] + L[3:0] + 4'b0110 + 1'd1;
135         end 
136     endcase
137 end
138 
139 /**********************************************/
140 //5ms计数器
141 reg [17:0] cnt; 
142 always @(posedge sys_clk or negedge rst_n)
143 if(!rst_n) 
144     cnt <= 18'd0;
145 else if(cnt == T5MS) 
146     cnt <= 18'd0;
147 else
148     cnt <= cnt + 1'b1;
149 /**********************************************/    
150 //通过移位方式进行流水工作,定时开关
151 reg [2:0] slec_wei_temp;
152 always @(posedge sys_clk or negedge rst_n)
153     if(!rst_n) begin
154         slec_wei_temp <= 3'd011;
155     end
156     else if(cnt == T5MS) begin
157         if(slec_wei_temp == 3'b110)
158             slec_wei_temp <= 3'b011;
159         else
160             slec_wei_temp <= {1'b1,slec_wei_temp[2:1]};
161     end
162 
163 assign slec_wei = {1'b1,slec_wei_temp};
164 /*****************************************/    
165 reg [6:0] data0;
166 always @ (posedge sys_clk)
167 case(cout[11:8])    //进行编码 高
168     4'h0: data0 <= SEG_NUM0;
169     4'h1: data0 <= SEG_NUM1;
170     4'h2: data0 <= SEG_NUM2;
171     4'h3: data0 <= SEG_NUM3;
172     4'h4: data0 <= SEG_NUM4;
173     4'h5: data0 <= SEG_NUM5;
174     4'h6: data0 <= SEG_NUM6;
175     4'h7: data0 <= SEG_NUM7;
176     4'h8: data0 <= SEG_NUM8;
177     4'h9: data0 <= SEG_NUM9;
178     default:data0 <= SEG_NUM0;
179 endcase
180 /*****************************************/    
181 reg [6:0] data1;
182 always @ (posedge sys_clk)
183 case(cout[7:4])    //进行编码  中
184     4'h0: data1 <= SEG_NUM0;
185     4'h1: data1 <= SEG_NUM1;
186     4'h2: data1 <= SEG_NUM2;
187     4'h3: data1 <= SEG_NUM3;
188     4'h4: data1 <= SEG_NUM4;
189     4'h5: data1 <= SEG_NUM5;

190     4'h6: data1 <= SEG_NUM6;
191     4'h7: data1 <= SEG_NUM7;
192     4'h8: data1 <= SEG_NUM8;
193     4'h9: data1 <= SEG_NUM9;
194     default:data1 <= SEG_NUM0;
195 endcase
196 /*****************************************/    
197 reg [6:0] data2;
198 always @ (posedge sys_clk)
199 case(cout[3:0])    //进行编码  低
200     4'h0: data2 <= SEG_NUM0;
201     4'h1: data2 <= SEG_NUM1;
202     4'h2: data2 <= SEG_NUM2;
203     4'h3: data2 <= SEG_NUM3;
204     4'h4: data2 <= SEG_NUM4;
205     4'h5: data2 <= SEG_NUM5;
206     4'h6: data2 <= SEG_NUM6;
207     4'h7: data2 <= SEG_NUM7;
208     4'h8: data2 <= SEG_NUM8;
209     4'h9: data2 <= SEG_NUM9;
210     default:data2 <= SEG_NUM0;
211 endcase
212 /***********************************************/
213 reg [1:0] num;
214 always @ (posedge sys_clk or negedge rst_n)
215 if(!rst_n)
216     num <= 2'd0;
217 else if(cnt == T5MS)
218     num <= num + 1'b1;
219 else if(num == 2'd3)
220     num <= 2'd0;
221 /***********************************************/    
222 reg [6:0] slec_duan;
223 always @ (posedge sys_clk)
224 case(num)
225     2'd0: slec_duan <= data0;
226     2'd1: slec_duan <= data1;
227     2'd2: slec_duan <= data2;
228 endcase
229 
230 endmodule 
View Code

adc0809_control.v模块和adc0809_top模块请看基于Verilog HDL的ADC0809CCN数据采样中的代码。

当代码写完之后,发现显示的数据与实际电压有点偏差,高了0.2V左右,后来我测试了一下ADC0809的工作电压是4.8V,不是5V,我想可能是因为跟这个参考电压有关,为了让显示的数据与实际测试尽量接近,可以在代码中进行校准,我在中四位cout[7:4]减2,低cout[3:0]加1,其结果还是比较接近实际值。

 

 

 

posted @ 2013-08-27 22:10  MyBooks  阅读(2490)  评论(3编辑  收藏  举报