snifer

【赛灵思FPGA】[原创]基于Xilinx FPGA的通用信号采集器

0
阅读(3387)

上一篇写了基于Xilinx FPGA的通用信号发生器的案例,反响比较好,很多朋友和我探讨相关的技术,其中就涉及到信号的采集,为了使该文更有血有肉,我在写一篇基于Xilinx FPGA的通用信号采集器,望能形成呼应,以解答大家的疑问。

目的:

1.通过设计实现信号采集与分析,掌握组合逻辑设计方法;

2.通过设计实现信号的采集与分析,掌握信号采集原理。

原理:

利用FPGA芯片,用verilog语言编写逻辑,控制AD0809进行AD转换。

AD0809是带有8位AD转换器、8路多路开关以及微处理机兼容的控制逻辑的CMOS组件,它是逐次逼近式的AD转换器。

AD0809的内部结构图如下:

由上图可知,多路开关可选通8 个模拟通道,允许8路模拟量分时输入,共用AD转换器进行转换,三态输出锁存器用于锁存AD转换完成后的数字量,当OE为高时才可以从锁存器取出转换后的数据。

通道选择如下图所示:

START为转换启动信号。当START上跳沿时,所有内部寄存器清零;下跳沿时,开始进行A/D 转换;在转换期间,START应保持低电平。EOC 为转换结束信号。当EOC 为高电平时,表明转换结束;否则,表明正在进行A/D 转换。OE为输出允许信号,用于控制三条输出锁存器向单片机输出转换得到的数据。OE=1,输出转换得到的数据;OE=0,输出数据线呈高阻状态。

时序如下图所示:

源代码
1.Verilog源代码,dataCollect.v
module dataCollect(sysclk, rst, adda, addb, addc, start, oe, 
		datain, led_sel, led_seg);
	input sysclk, rst;
	input wire [7:0] datain;
	output reg adda, addb, addc, start, oe;
	output reg[3:0] led_sel;
	output reg[7:0] led_seg;

	reg [3:0] counter1;
	reg [7:0] readdata;

	reg [9:0] counter2;
	reg [15:0] sum;
	reg [7:0] averdata;

 	reg [7:0] temp;
 	reg [3:0] dataout1, dataout2, dataout3;

	reg [3:0] counter3;

	parameter ZERO = 8'b11111100,ONE = 8'b01100000, TWO = 8'b11011010;
	parameter THREE = 8'b11110010, FOUR =8'b01100110;
	parameter FIVE = 8'b10110110, SIX = 8'b10111110, SEVEN =8'b11100000;
	parameter EIGHT = 8'b11111110, NINE = 8'b11110110, BLANK = 8'b00000000;


	always @(posedge sysclk or negedge rst)
	begin
		if (!rst)
		begin
			adda = 0;
			addb = 0;
			addc = 0;

			oe = 1;

			counter1 = 0;
		end
		else
		begin
			counter1 = counter1 + 1;
			case (counter1)
				3 : start = 0;
				4 : start = 1;
				5 : start = 0;
				10 : readdata = datain;
				15 : counter1 = 0;
				default : counter1 = counter1;
			endcase
		end
	end

	always @(posedge sysclk or negedge rst)
	begin
		if (!rst)
		begin
			counter2 = 0;
			sum = 0;
			averdata = 0;
		end
		else
		begin
			counter2 = counter2 + 1;
			if ((counter2%16) == 0)
				sum = sum + readdata;
			else if (counter2 > 512)
			begin
				averdata = sum / 32;
				sum = 0;
				counter2 = 0;
			end
		end
	end	 


	always @(averdata)
	begin
		temp = averdata;
		if (temp > 199)
			dataout3 = 2;
		else if (temp > 99)
			dataout3 = 1;
		else
			dataout3 = 0;
		
		temp = temp - dataout3 * 100;
		if (temp > 89)
			dataout2 = 9;
		else if (temp > 79)
			dataout2 = 8;
		else if (temp > 69)
			dataout2 = 7;
		else if (temp > 59)
			dataout2 = 6;
		else if (temp > 49)
			dataout2 = 5;
		else if (temp > 39)
			dataout2 = 4;
		else if (temp > 29)
			dataout2 = 3;
		else if (temp > 19)
			dataout2 = 2;
		else if (temp > 9)
			dataout2 = 1;
		else
			dataout2 = 0;

		temp = temp - dataout2 * 10;
		dataout1 = temp;

		if ((dataout3==0) && (dataout2==0))
		begin
			dataout3 = 10;
			dataout2 = 10;
		end
		else if (dataout3 == 0)
			dataout3 = 10;
		else
			dataout3 = dataout3;
	end


	always @(posedge sysclk or negedge rst)
	begin
		if (!rst)
		begin
			counter3 = 0;
			led_sel = 4'b0001;		
		end
		else
		begin
				if (counter3 == 4)
				begin
					counter3 = 0;
					if (led_sel == 4'b1000)
						led_sel = 4'b0001;
					else
						led_sel = led_sel << 1;
				end
				counter3 = counter3 + 1;
		end			
	end

	always @(led_sel, dataout1, dataout2, dataout3)
	begin
		case (led_sel)
			4'b0001 :
			begin
				case (dataout1)
					0 : led_seg = ZERO;
					1 : led_seg = ONE;
					2 : led_seg = TWO;
					3 : led_seg = THREE;
					4 : led_seg = FOUR;
					5 : led_seg = FIVE;
					6 : led_seg = SIX;
					7 : led_seg = SEVEN;
					8 : led_seg = EIGHT;
					9 : led_seg = NINE;
					default : led_seg = BLANK;
				endcase
			end
			4'b0010 :
			begin
				case (dataout2)
					0 : led_seg = ZERO;
					1 : led_seg = ONE;
					2 : led_seg = TWO;
					3 : led_seg = THREE;
					4 : led_seg = FOUR;
					5 : led_seg = FIVE;
					6 : led_seg = SIX;
					7 : led_seg = SEVEN;
					8 : led_seg = EIGHT;
					9 : led_seg = NINE;
					default : led_seg = BLANK;
				endcase
			end
			4'b0100 :
			begin
				case (dataout3)
					0 : led_seg = ZERO;
					1 : led_seg = ONE;
					2 : led_seg = TWO;
					3 : led_seg = THREE;
					4 : led_seg = FOUR;
					5 : led_seg = FIVE;
					6 : led_seg = SIX;
					7 : led_seg = SEVEN;
					8 : led_seg = EIGHT;
					9 : led_seg = NINE;
					default : led_seg = BLANK;
				endcase
			end
			4'b1000 :
			begin
				case (10)
					0 : led_seg = ZERO;
					1 : led_seg = ONE;
					2 : led_seg = TWO;
					3 : led_seg = THREE;
					4 : led_seg = FOUR;
					5 : led_seg = FIVE;
					6 : led_seg = SIX;
					7 : led_seg = SEVEN;
					8 : led_seg = EIGHT;
					9 : led_seg = NINE;
					default : led_seg = BLANK;
				endcase
			end
			default :
			begin
				led_seg = 1'hx;
			end
		endcase
	end

endmodule

2.引脚分配源代码,dataCollect.ucf
net sysclk loc = p80;
net rst loc = p57;

net adda loc = p14;
net addb loc = p16;
net addc loc = p18;

net oe loc = p23;
net start loc = p27;

net datain<7> loc = p30;
net datain<6> loc = p33;
net datain<5> loc = p35;
net datain<4> loc = p37;
net datain<3> loc = p42;
net datain<2> loc = p44;
net datain<1> loc = p46;
net datain<0> loc = p48;

net led_sel<3> loc = p3;
net led_sel<2> loc = p5;
net led_sel<1> loc = p7;
net led_sel<0> loc = p9;

net led_seg<7> loc = p206;
net led_seg<6> loc = p204;
net led_seg<5> loc = p202;
net led_seg<4> loc = p200;
net led_seg<3> loc = p195;
net led_seg<2> loc = p193;
net led_seg<1> loc = p191;
net led_seg<0> loc = p187;

 

OK了,可以使用了,按照为器件分配的引脚进行连线,系统时钟输入连1KMHZ,可以旋转电位器以改变输入电压,此时可观察到数据管上数据变化。

FPGA,融入其中,乐趣无穷。。。。