CPLD与ADC0804接口设计
0赞这个实验做得比较郁 闷,因为从上午开始一直摸不着头绪,虽然整体模块设计早早搞定。但是调试阶段可谓费尽周折,原因是没有抓住主要矛盾。一直以为是ADC0804的驱动部分没有做好, 直到最后才发现原因出在显示部分。
但是发现问题后,却苦恼于如何用查表法来把8bit的AD转换结果的各个数位分 别存入寄存器中以便最后的数码管显示使用。显然的通常在软件的设计中,这样的问题用两个除法或者取余运算就可以解决的,但是在硬件上是不可以的,乘除运算 是相当耗费资源的(当然了,如果硬件中不得不设计到这样的模块时,调用它是没问题的)。所以一般的计算在硬件上都是用其它的方法来替代乘除运算的,比如常 用的加法或者查表法(关于卷积和的查表算法前面的日志中谈过了,也是一个相当经典的设计思路)。
这里的256个可能取值如何把各个位上的数值分别赋给相应寄存器就比较让人费神,得到的经验就是:我用100级的case语句比10级的if…else if………else…语句要来得节约硬件 资源(整个设计240个LE后者就不够用了)。个中原因也是显而易见的,判断if else对于只用一些逻辑门的 硬件来说是多么的复杂的任务而,呵呵,大概就是这样了。所以以后在硬件设计的时候应该多比较这些语法,多总结,才能设计出更低成本更高性能的产品。硬件和 软件设计不同,有时候往往越简单的语句用法反而越节约资源。
好了,感慨了好一会,看来实验是没白做——学到东西了。这个设计其实很简单,就是通过CPLD来控制ADC0804工作,然后把从ADC0804读出的数值显示在数码 管上。(这个实验好像有点老掉牙哈。~_~)
还有就是在控制AD器件的时候,我是把50MHz的主频做了50分频,然后利用到了状 态机的设计,延时是用的计数(借助于分频的思想),不知道这样的想法对不对,或者说是有更成熟的延时设计方法(期待高手指点)。
该设计的RTL视图如下:(三个模块)
AD0804与CPLD的接口控制部分的状态机设计视图(ISE在状态机的设计上可以 采用原理图的设计,有一个专门的设计界面只要相应的画出下面这个状态图就可以自动生产代码,而QUARTUS似乎只能自己写代码, 不知道是我没有发现QUARTUS的这个状态机设计方法还是它确实不够强大):
控制部分的Verilog代码如下:
(没写注释还是因为该死的键盘,写程序的时候可不想像现在这么累人的来回切换,明天赶紧换个去)
module adc_work(clk,rst_n,data,cs_n,rd_n,wr_n,intr_n,key,data_reg);
input clk;
input rst_n;
input[7:0] data;
input intr_n;
input key;
output cs_n,rd_n,wr_n;
output[7:0] data_reg;
reg[1:0] idle,start,start_wait,convert,current_state,next_state;
reg[15:0] delay;
reg cs_n,rd_n,wr_n;
reg[7:0] data_reg;
reg read_flag;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
current_state <= 0;
delay <= 0;
data_reg <= 0;
end
else begin
case(current_state)
idle: begin
if(delay<10) begin
delay <= delay+1; end
else begin
current_state <= next_state;
delay <= 0; end
end
start: begin
current_state <= next_state;
end
start_wait: begin
current_state <= next_state;
end
convert: begin
if(delay<2) begin
delay <= delay+1; end
else begin
data_reg <= data;
current_state <= next_state;
delay <= 0; end
end
default: ;
endcase
end
end
always @ (current_state or intr_n or rst_n) begin
if(!rst_n) begin
idle <= 0;
start <= 1;
start_wait <= 2;
convert <= 3;
read_flag <= 0;
end
else begin
case (current_state)
idle: begin
cs_n <= 1;
wr_n <= 1;
rd_n <= 1;
read_flag <= 0;
next_state <= start; end
start: begin
cs_n <= 0;
wr_n <= 0;
rd_n <= 1;
read_flag <= 0;
next_state <= start_wait; end
start_wait: begin
wr_n <= 1;
cs_n <= 1;
rd_n <= 1;
read_flag <= 0;
if(!intr_n) next_state <= convert;
else next_state <= start_wait;
end
convert: begin
cs_n <= 0;
rd_n <= 0;
wr_n <= 1;
read_flag <= 1;
next_state <= idle; end
default: next_state <= idle;
endcase
end
end
endmodule
还有就是那个所谓的查表法,因为百位上只有0、1、2三种可能,所以用if else了:
if(data_reg<100) begin
led_seg[2] <= led_reg[0];
data_dis <= data_reg; end
else if(data_reg<200) begin
led_seg[2] <= led_reg[1];
data_dis <= data_reg-100; end
else begin
led_seg[2] <= led_reg[2];
data_dis <= data_reg-200; end
data_dis是把百位数值减去后的寄存器,剩下的十位和个位就要用到它,如下:
case (data_dis)
0: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[0]; end
1: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[1]; end
2: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[2]; end
3: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[3]; end
4: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[4]; end
5: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[5]; end
6: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[6]; end
7: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[7]; end
8: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[8]; end
9: begin led_seg[1] <= led_reg[0]; led_seg[0] <= led_reg[9]; end
10: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[1]; end
11: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[2]; end
12: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[2]; end
13: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[3]; end
14: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[4]; end
15: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[5]; end
16: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[6]; end
17: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[7]; end
18: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[8]; end
19: begin led_seg[1] <= led_reg[1]; led_seg[0] <= led_reg[9]; end
20: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[0]; end
21: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[1]; end
22: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[2]; end
23: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[3]; end
24: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[4]; end
25: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[5]; end
26: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[6]; end
27: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[7]; end
28: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[8]; end
29: begin led_seg[1] <= led_reg[2]; led_seg[0] <= led_reg[9]; end
30: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[0]; end
31: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[1]; end
32: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[2]; end
33: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[3]; end
34: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[4]; end
35: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[5]; end
36: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[6]; end
37: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[7]; end
38: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[8]; end
39: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[9]; end
40: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[0]; end
41: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[1]; end
42: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[2]; end
43: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[3]; end
44: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[4]; end
45: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[5]; end
46: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[6]; end
47: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[7]; end
48: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[8]; end
49: begin led_seg[1] <= led_reg[4]; led_seg[0] <= led_reg[9]; end
50: begin led_seg[1] <= led_reg[3]; led_seg[0] <= led_reg[0]; end
51: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[1]; end
52: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[2]; end
53: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[3]; end
54: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[4]; end
55: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[5]; end
56: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[6]; end
57: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[7]; end
58: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[8]; end
59: begin led_seg[1] <= led_reg[5]; led_seg[0] <= led_reg[9]; end
60: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[0]; end
61: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[1]; end
62: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[2]; end
63: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[3]; end
64: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[4]; end
65: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[5]; end
66: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[6]; end
67: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[7]; end
68: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[8]; end
69: begin led_seg[1] <= led_reg[6]; led_seg[0] <= led_reg[9]; end
70: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[0]; end
71: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[1]; end
72: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[2]; end
73: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[3]; end
74: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[4]; end
75: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[5]; end
76: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[6]; end
77: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[7]; end
78: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[8]; end
79: begin led_seg[1] <= led_reg[7]; led_seg[0] <= led_reg[9]; end
80: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[0]; end
81: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[1]; end
82: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[2]; end
83: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[3]; end
84: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[4]; end
85: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[5]; end
86: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[6]; end
87: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[7]; end
88: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[8]; end
89: begin led_seg[1] <= led_reg[8]; led_seg[0] <= led_reg[9]; end
90: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[0]; end
91: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[1]; end
92: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[2]; end
93: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[3]; end
94: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[4]; end
95: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[5]; end
96: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[6]; end
97: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[7]; end
98: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[8]; end
99: begin led_seg[1] <= led_reg[9]; led_seg[0] <= led_reg[9]; end
default: ;
endcase
其实不想给自己这么大工作量,但是一时还是想不到更好的算法,所以只有勉为其难了。