module adc8_5v(sys_clk,sys_rst,data8_in,data16_out,adc_clkout,sign,data_medium_out);
input wire sys_clk,sys_rst;
input wire [7:0] data8_in;
output [7:0] data_medium_out;
output wire adc_clkout;
output wire [15:0] data16_out;
output wire sign;
reg [1:0] cnt_sysclk;
reg adc_clkin;
reg adc_en;
reg [10:0] cnt_medium;
reg [18:0] adc_data_sum_medium;
reg [7:0] adc_data_medium;
reg [27:0] volt_reg;
wire [27:0] data_PN_p;
wire [27:0] data_PN_n;
parameter cnt_medium_MAX=1024;
parameter cnt_mediumBit_MAX=10;
assign data_medium_out=data8_in;
//时钟4分频(频率为12.5MHz)(做为AD的驱动时钟)
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
begin
adc_clkin<=1'b0;
cnt_sysclk<=2'd0;
end
else if(cnt_sysclk==2'd1)
begin
cnt_sysclk<=2'd0;
adc_clkin<=~adc_clkin;
end
else
begin
cnt_sysclk<=cnt_sysclk+1'b1;
adc_clkin<=adc_clkin;
end
end
//用于产生前期默认的数据(使能采样)
always@(posedge adc_clkin or negedge sys_rst)
begin
if(!sys_rst)
begin
adc_en<=1'b0;
cnt_medium<=11'd0;
end
else if(cnt_medium==cnt_medium_MAX)
begin
adc_en<=1'b1;
cnt_medium<=cnt_medium;
end
else
begin
adc_en<=adc_en;
cnt_medium<=cnt_medium+1'b1;
end
end
//用于收集多个接地的基础数据(这里为2^10)
always@(posedge adc_clkin or negedge sys_rst)
begin
if(!sys_rst)
adc_data_sum_medium<=19'd0;
else if(cnt_medium==cnt_medium_MAX)
adc_data_sum_medium<=adc_data_sum_medium;
else
adc_data_sum_medium<=adc_data_sum_medium+data8_in;
end
//取平均值
always@(posedge adc_clkin or negedge sys_rst)
begin
if(!sys_rst)
adc_data_medium<=8'd0;
else if(cnt_medium==cnt_medium_MAX)
adc_data_medium<=adc_data_sum_medium>>cnt_mediumBit_MAX;
else
adc_data_medium<=adc_data_medium;
end
//放大(2^13*1000倍)
assign data_PN_p=(adc_en==1'b1)? 8192_0000/((255-adc_data_medium)*2):0;
assign data_PN_n=(adc_en==1'b1)? 8192_0000/((adc_data_medium+1)*2):0;
//测量数据放大1000倍
always@(posedge adc_clkin or negedge sys_rst)
begin
if(!sys_rst)
volt_reg<=28'd0;
else if(adc_en==1'b1)
if((data8_in>(adc_data_medium-3))&&(data8_in<(adc_data_medium+3)))
volt_reg<=28'd0;
else if(data8_in<adc_data_medium)
volt_reg<=(data_PN_n*(adc_data_medium-data8_in))>>13;
else if(data8_in>adc_data_medium)
volt_reg<=(data_PN_p*(data8_in-adc_data_medium))>>13;
else
volt_reg<=28'd0;
end
//数据在上升沿更新,所以adc驱动程序为下降沿采样数据
assign adc_clkout=~adc_clkin;
assign sign=(data8_in<adc_data_medium)? 1'b1:1'b0;
assign data16_out=volt_reg;
endmodule