模块简介:
ADC0809 是采用CMOS 工艺制造的双列直插式单片8 位A/D 转换器。(分辨率) 分辨率8 位,精度7 位,带8 个模拟量输入通道,有通道地址译码锁存器,输出带三态数据锁存器。启动信号为脉冲启动方式,最大可调节误差为±1LSB。(转换精度)
引脚功能说明:
引脚名称 | 描述 |
D7-D0 | 8位数字量输出引脚。 |
IN0-IN7 | 8位模拟量输入引脚。 |
VCC | +5V工作电压。 |
GND | 地。 |
REF(+) | 参考电压正端。 |
REF(-) | 参考电压负端。 |
START | A/D转换启动信号输入端。 |
ALE | 地址锁存允许信号输入端。 |
(以上两种信号用于启动A/D转换) | |
EOC | 转换结束信号输出引脚,开始转换时为低电平,当转换结束时为高电平。 |
OE | 输出允许控制端,用以打开三态数据输出锁存器。 |
CLK | 时钟信号输入端(一般为500KHz)。 |
A、B、C | 地址输入线。 |
地址码与输入通道的对应关系:
地址码 | 通道 | 地址码 | 通道 | ||||
A | B | C | A | B | C | ||
0 | 0 | 0 | IN0 | 1 | 0 | 0 | IN4 |
0 | 0 | 1 | IN1 | 1 | 0 | 1 | IN5 |
0 | 1 | 0 | IN2 | 1 | 1 | 0 | IN6 |
0 | 1 | 1 | IN3 | 1 | 1 | 1 | IN7 |
核心代码实现:
module ADC0809_Dirve
#(
parameter clock_freq = 50_000_000,
div_value_width = ( ( clock_freq / 500_000 )/2) > 0 ? $clog2( ( clock_freq / 500_000 )/2) : 1
)(
input clk,
input rst,
input [7:0] adc_data,
input [2:0] adc_cs,
input EN,
input EOC,//ADC0809转换结束信号
output reg ADC_clk,//ADC0809时钟信号
output reg OE,//ADC0809输出使能信号
output reg [7:0] adc_result,//ADC0809输出结果
output reg ADC_START,//ADC0809启动信号
output reg [2:0] adc_cs_out,//ADC0809片选信号
output reg adc_done_out,//ADC0809转换结束信号
output reg [4:0]present_state
);
//分频器(为adc提供时钟)
//分频值计算
reg [div_value_width:0] div_value;
reg [div_value_width:0] div_cnt;
always@(posedge clk or negedge rst)
begin
if(!rst)
div_value <= 0;
else
div_value <= ( clock_freq / 500_000 )/2;
end
always@(posedge clk or negedge rst)
begin
if(!rst) begin
ADC_clk <= 0;
div_cnt <= 0;
end
else if(EN) begin
if(div_cnt >= div_value) begin
ADC_clk <= !ADC_clk;
div_cnt <= 0;
end
else begin
ADC_clk <= ADC_clk;
div_cnt <= div_cnt + 1;
end
end
else begin
ADC_clk <= 0;
div_cnt <= 0;
end
end
wire delay;
reg delay_en;
//ADC0809控制器
//reg [4:0]present_state;
reg [4:0]next_state;//当前状态和下一状态
parameter Init = 5'b00000,//初始状态
Wait = 5'b00001,//等待状态
cs_out = 5'b00010,//片选
adc_st = 5'b00011,//启动
adc_done= 5'b00100;//读取
always @ (posedge clk or negedge rst)
if(!rst)begin//复位
present_state<=Init;
end
else
present_state<=next_state;
always @ (*) begin
case (present_state)
Init:begin
OE = 1'b0;
adc_cs_out = 3'b000;
adc_result = 8'b00000000;
ADC_START = 1'b1;
delay_en = 1'b0;
adc_done_out = 1'b0;
next_state=Wait;
end
Wait:begin
delay_en = 1'b0;
ADC_START = 1'b1;
adc_done_out = 1'b0;
OE = 1'b1;
if(EN)begin
next_state=cs_out;
end
else begin
next_state=Wait;
end
end
cs_out:begin
delay_en = 1'b1;
adc_cs_out = adc_cs;
if(delay)begin
next_state=adc_st;
end
else begin
next_state=cs_out;
end
end
adc_st:begin
delay_en = 1'd0;
OE = 1'b1;
ADC_START = 1'b0;
if(EOC)begin
next_state=adc_done;
end
else begin
next_state=adc_st;
end
end
adc_done:begin
OE = 1'b1;
ADC_START = 1'b1;
adc_done_out = 1'b1;
adc_result = adc_data;
next_state=Wait;
end
default:
next_state=Wait;
endcase
end
//例化timer模块
timer timer_delay(
.timeout(delay),
.clk(clk),
.rst(!rst),
.en(delay_en)
);
endmodule