TLV1548型ADC芯片内部结构 ,TLV1544型只有4个模拟输入引脚。
TLV1548有8个。
A0~A7为8个模拟通道,REF±为2个参考电压通道,DATA_IN为SPI数据接口输入端,Samples and Hold Function 为采样和保持功能。Analog MUX为模拟多路器。10-bit ADC转换数据功能。
DSP(数字信号处理)。
使用FPGA模拟SPI接口
TLV1544通过SPI接口与控制器进行通信的时序图如下所示:
FPGA下降沿更新D1,上升沿写入AD/DA模块;FPAG上升沿读取D0,AD/DA模块下降沿更新D0.
DO为数信号,DI为模拟信号。
CONTROL_DO为开始采样使能信号,ADC_SEL为4个模拟通道选择信号,TLV1544_SDO为输入给FPGA采样数据,ADC_DONE为此次转换完成信号,ADC_DATE为采样结果,TLV1544_SDI为输出给ADC模块地址信号。DATE_VALUE表示ADC_DATE数据有效刚好把所有的DO数据提取到ADC_DATE数据中。
module TLV1544_CONTROL(
CLK,
RST_N,
CONTROL_DO, //开始采样使能信号
ADC_SEL, //4个模拟通道选择信号
TLV1544_SDO, //ADC采样转化的数字信号
TLV1544_EOC,
ADC_DONE, //一次采样完成
ADC_DATE, //采样结果
TLV1544_FS, //SPI模式下默认高电平
TLV1544_nCS, //低电平有效
TLV1544_CLOCK,
DATE_VAUEL, //ADC_DATE数据有效信号(ADC为转换之前)
TLV1544_SDI
);
input CLK;
input RST_N;
input CONTROL_DO; //开始采样使能信号
input [3:0] ADC_SEL; //4个模拟通道选择信号
input TLV1544_SDO; //ADC采样转化的数字信号
input TLV1544_EOC;
output reg ADC_DONE; //一次采样完成
output reg [9:0]ADC_DATE; //采样结果
output wire TLV1544_FS; //SPI模式下默认高电平
output reg TLV1544_nCS; //低电平有效
output reg TLV1544_CLOCK;
output reg DATE_VAUEL; //ADC_DATE数据有效信号(ADC为转换之前)
output reg TLV1544_SDI; //地址信号位
reg [7:0]count;
reg [9:0]r_date;
assign TLV1544_FS = 1'b1;
//计数
always @(posedge CLK or negedge RST_N)
if(!RST_N)
count <= 8'b0;
else if((TLV1544_EOC ==1) && count <204 && (CONTROL_DO ==1 || count>0))
count <= count + 8'b1;
else if((TLV1544_EOC ==0) && count <204)
count <= count ;
else if((TLV1544_EOC ==1) && count ==204)
count <= 8'b0;
//序列机
always @(posedge CLK or negedge RST_N)
if(!RST_N) begin
ADC_DONE <= 0;
ADC_DATE <= 0;
TLV1544_nCS <= 0;
TLV1544_CLOCK <= 0;
DATE_VAUEL <= 0;
r_date <= 10'b0;
end else
begin
case(count)
0: begin
TLV1544_CLOCK <=0;
TLV1544_nCS <=1;
TLV1544_SDI <= 0;
ADC_DONE <= 0;
r_date <= 10'b0;
DATE_VAUEL <= 0;
end
1: begin
TLV1544_CLOCK <=0;
TLV1544_nCS <=0;
TLV1544_SDI <= ADC_SEL[3];
end
9: begin
TLV1544_CLOCK <=1;
r_date[9] <= TLV1544_SDO;
end
19:
begin
TLV1544_CLOCK <=0;
TLV1544_SDI <= ADC_SEL[2];
end
29:
begin
TLV1544_CLOCK <=1;
r_date[8] <= TLV1544_SDO;
end
39:
begin
TLV1544_CLOCK <=0;
TLV1544_SDI <= ADC_SEL[1];
end
49:
begin
TLV1544_CLOCK <=1;
r_date[7] <= TLV1544_SDO;
end
59:
begin
TLV1544_CLOCK <=0;
TLV1544_SDI <= ADC_SEL[0];
end
69:
begin
TLV1544_CLOCK <=1;
r_date[6] <= TLV1544_SDO;
end
79: TLV1544_CLOCK <=0;
89:
begin
TLV1544_CLOCK <=1;
r_date[5] <= TLV1544_SDO;
end
99:TLV1544_CLOCK <=0;
109:
begin
TLV1544_CLOCK <=1;
r_date[4] <= TLV1544_SDO;
end
119:TLV1544_CLOCK <=0;
129:
begin
TLV1544_CLOCK <=1;
r_date[3] <= TLV1544_SDO;
end
139:TLV1544_CLOCK <=0;
149:
begin
TLV1544_CLOCK <=1;
r_date[2] <= TLV1544_SDO;
end
159:TLV1544_CLOCK <=0;
169:
begin
TLV1544_CLOCK <=1;
r_date[1] <= TLV1544_SDO;
end
179:TLV1544_CLOCK <=0;
189:
begin TLV1544_CLOCK <=1;
if(TLV1544_EOC)
DATE_VAUEL <= 1;
else
DATE_VAUEL <= 0;
ADC_DATE <= {r_date[9:1],TLV1544_SDO};
end
199:
begin
TLV1544_CLOCK <=0;
TLV1544_nCS <= 1;
end
204: ADC_DONE <= 1'b1;
default: DATE_VAUEL <= 0;
endcase
end
endmodule
`timescale 1ns/1ns
`define Clk_period 20
module TLV1544_CONTROL_tb;
reg CLK;
reg RST_N;
reg CONTROL_DO; //开始采样使能信号
reg [3:0] ADC_SEL; //4个模拟通道选择信号
reg [9:0]TLV1544_SDO; //ADC采样转化的数字信号
reg TLV1544_EOC;
wire ADC_DONE; //一次采样完成
wire [9:0]ADC_DATE; //采样结果
wire TLV1544_FS; //SPI模式下默认高电平
wire TLV1544_nCS; //低电平有效
wire TLV1544_CLOCK;
wire DATE_VAUEL; //ADC_DATE数据有效信号(ADC为转换之前)
wire [3:0] TLV1544_SDI; //地址信号位
TLV1544_CONTROL TLV1544_CONTROL0(
.CLK(CLK),
.RST_N(RST_N),
.CONTROL_DO(CONTROL_DO),
.ADC_SEL(ADC_SEL),
.TLV1544_SDO(TLV1544_SDO),
.TLV1544_EOC(TLV1544_EOC),
.ADC_DONE(ADC_DONE),
.ADC_DATE(ADC_DATE),
.TLV1544_FS(TLV1544_FS),
.TLV1544_nCS(TLV1544_nCS),
.TLV1544_CLOCK(TLV1544_CLOCK),
.DATE_VAUEL(DATE_VAUEL),
.TLV1544_SDI(TLV1544_SDI)
);
initial CLK =1;
always #(`CLK_period/2) CLK =~CLK;
initial begin
RST_N = 0;
CONTROL_DO = 0;
ADC_SEL = 0;
TLV1544_SDO = 0;
TLV1544_EOC = 1;
#(`CLK_period*10);
RST_N = 1;
ADC_SEL = 0;
#(`CLK_period*2);
CONTROL_DO = 1;
#`CLK_period;
CONTROL_DO = 0;
@(posedge (TLV1544_CONTROL0.count==8'd189));
#(`CLK_period);
TLV1544_EOC=0;
#(`CLK_period*20+1);
TLV1544_EOC=1;
#(`CLK_period*1000);
#(`CLK_period*2);
CONTROL_DO = 1;
#`CLK_period;
CONTROL_DO = 0;
@(posedge (TLV1544_CONTROL0.count==8'd189));
#(`CLK_period);
TLV1544_EOC=0;
#(`CLK_period*20+1);
TLV1544_EOC=1;
#(`CLK_period*1000);
$stop;
end
initial begin
forever begin
TLV1544_SDO = ~TLV1544_SDO;
#360;
end
end
endmodule
可以看到DO数据在TLV1544_CLOCK上升沿读取数据到r_date,在count位189时将r_date的值传输到ADC_DATE。
SSOP是一款16 路恒流输出芯片。
为满足整个工程资源优化,SPI通信时钟选择10MHZ。
时序设计图如下:
采用线性序列机的思想,以count计数为条件编写case语句。
`timescale 1ns / 1ps
module ssop_control(
input clk , //10MHZ
input rst_n ,
input con_en , // pulse. width>=0.1us
input [15:0] con_data ,
output reg ssop_sin ,
output reg ssop_oe ,
output reg ssop_le ,
output reg ssop_state ,
output wire ssop_clk //10MHZ
);
reg [4:0] count ;
reg [15:0] r_con_data ;
reg [15:0] m_r_con_data;
assign ssop_clk = ~ clk ;
always @(posedge clk or negedge rst_n)
if(!rst_n)
r_con_data <= 1'b0 ;
else
r_con_data <= con_data ;
always @(posedge clk or negedge rst_n)
if(!rst_n)
m_r_con_data <= 1'b0 ;
else
m_r_con_data <= r_con_data ;
always @(posedge clk or negedge rst_n)
if(!rst_n)
count <= 5'b0;
else
if(con_en || ( count > 5'b0 ))
begin
if(count == 5'h10) //'d16
count <= 5'b0 ;
else
count <= count + 1'b1;
end
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
ssop_sin <= 1'b0;
ssop_oe <= 1'b1;
ssop_le <= 1'b0;
ssop_state <= 1'b0;
end
else
begin
case(count)
5'h1:
begin
ssop_sin <= m_r_con_data[15];
ssop_oe <= 1'b0;
ssop_le <= 1'b1;
ssop_state <= 1'b1;
end
5'h2:
ssop_sin <= m_r_con_data[14];
5'h3:
ssop_sin <= m_r_con_data[13];
5'h4:
ssop_sin <= m_r_con_data[12];
5'h5:
ssop_sin <= m_r_con_data[11];
5'h6:
ssop_sin <= m_r_con_data[10];
5'h7:
ssop_sin <= m_r_con_data[9];
5'h8:
ssop_sin <= m_r_con_data[8];
5'h9:
ssop_sin <= m_r_con_data[7];
5'ha:
ssop_sin <= m_r_con_data[6];
5'hb:
ssop_sin <= m_r_con_data[5];
5'hc:
ssop_sin <= m_r_con_data[4];
5'hd:
ssop_sin <= m_r_con_data[3];
5'he:
ssop_sin <= m_r_con_data[2];
5'hf:
ssop_sin <= m_r_con_data[1];
5'h10:
ssop_sin <= m_r_con_data[0];
default :
begin
ssop_sin <= 1'b0;
ssop_oe <= 1'b1;
ssop_le <= 1'b0;
ssop_state <= 1'b0;
end
endcase
end
endmodule
模拟两次数据发送。
`timescale 1ns / 1ns
`define CLK_PER 100
module ssop_tb();
reg rst_n ;
reg clk ;
reg con_en ;
reg [15:0] con_data ;
wire ssop_sin ;
wire ssop_oe ;
wire ssop_le ;
wire ssop_state ;
wire ssop_clk ;
initial clk = 1;
always #(`CLK_PER/2) clk = ~ clk;
ssop_control ssop_control_inst(
.clk (clk), //10MHZ
.rst_n (rst_n),
.con_en (con_en), // pulse. width>=0.1us
.con_data (con_data),
.ssop_sin (ssop_sin ),
.ssop_oe (ssop_oe ),
.ssop_le (ssop_le ),
.ssop_state (ssop_state),
.ssop_clk (ssop_clk ) //10MHZ
);
initial
begin
rst_n = 0;
con_en = 0;
con_data= 0;
#(`CLK_PER*5+1);
rst_n = 1;
//first send data
con_data= 16'hfaaa;
#(`CLK_PER*2+1);
con_en = 1;
#(`CLK_PER*2+1);
con_en = 0;
#(`CLK_PER*200);
//second send data
con_data= 16'hebdc;
#(`CLK_PER+1);
con_en = 1;
#(`CLK_PER*2+1);
con_en = 0;
#(`CLK_PER*600);
$stop;
end
endmodule