您好,欢迎来到图艺博知识网。
搜索
您的当前位置:首页FPGA入门学习心得

FPGA入门学习心得

来源:图艺博知识网


前言

本文主要分享自己的FPGA入门学习心得,芯片为 EP4CE10F17C8N,编程语言为Verilog HDL主要从 如下重要过程下手:基础语法学习指南,对一些主要关键词进行分析,ip核的认识及学习,自行编写简单程序,根据所用模块手册编写时序。

一、基础语法学习指南

Verilog HDL语言是一种类C的 硬件描述语言,其语法有组合逻辑与时序逻辑,包含选择语句,阻塞与非阻塞赋值,模块封装与实列等,学习起来还是比较简单,内容不多,语法与C语言有诸多相似,但是区别也非常大,如只有选择语句没有循环语句。如果要学单片机的思维学FPGA则会走很多弯路,因为其本质完全不一样,单片机文件编译成二进制文件写入存储器,然后读取执行指令,而FPGA则是编译成逻辑门组合及连线,按逻辑整体运行,所以与单片机区别非常大,不能将学习单片机时的思维照搬到FPGA上,这样将事倍功半。

二、主要关键词

1.wire

wire这个关键词是声明变量为组合逻辑信号,一般是物理连接某个电路,其输入一旦变化,则自身瞬间响应变化,该关键词通常作为输入输出变量声明。

2.reg

reg这个关键词是声明变量为时序逻辑信号,一般是表示触发器,其输入一旦变化,自身并不会瞬间响应,还会受时钟信号控制。

3.assign

assign这个关键词是声明一个组合逻辑电路,一般是直接赋值或者使用三目运算符做选择器,该关键词的赋值对象需要为wire型变量,代码如下(示例):

assign {C,Sum}=A+B;

该代码实现一个全加器电路

4.always

assign这个关键词是声明一个时序逻辑电路,其内部代码通常由时钟信号控制,其代码如下(示例):

always @(posedge CLK or negedge RST)
	if(!RST)
		cnt<=32'd0;
	else if(cnt==99999999)
		cnt<=32'd0;
	else
		cnt<=cnt+32'd1;

该代码是实现一个计数器电路

三、IP核的认识及学习

1.IP核的认识

IP核是厂商或开发者推出的集成且复杂的功能块,其有如rom、ram、pll、FIFO、等重要模块,也有为某特定功能定制的IP核。IP核分为软核、固核和硬核,利用IP核设计电子系统,引用方便,修改基本元件的功能容易。有了IP核,可以使开发速度得到非常大的提升。

2.pll-IP核的创建及使用

首先,需要打开如下选项

pll_ip	pll_ip_inst (
	.inclk0 ( inclk0_sig ),//基础时钟
	.c0 ( c0_sig ), //通道0时钟输出
	.c1 ( c1_sig ),
	.c2 ( c2_sig ),
	.c3 ( c3_sig ),
	.locked ( locked_sig )//锁相环是否锁定
	);

以上是PLL的使用,其他软IP模块的实现与上述过程基本一至,如何选择及配置就需要根据项目需求来确定了。

四、呼吸灯

在学完基础语法后,我自行编写了呼吸灯的程序,如下程序

module LED_Brs
(
	input CLK,
	input res,
	output reg [2:0] LED
);
reg [0:0]  bit_turn;		//计数状态
reg [8:0]  cnt_PWM_set;	//脉宽设置
reg [8:0]  cnt_PWM;		//脉宽计数
reg [31:0] cnt;			//周期计数
always @(posedge CLK or negedge res)
if(!res)
	begin
		bit_turn<=1'b0;
		cnt_PWM_set<=1'b0;
		cnt_PWM<=1'b0;
		cnt<=1'b0;				
	end
else if(cnt<16'd5000)//周期
	begin
		cnt<=1'b1+cnt;
	end	
else 
	begin
		cnt<=1'b0;

		if(cnt_PWM<99)
			cnt_PWM<=1'b1+cnt_PWM;
		else 
			begin
				cnt_PWM<=1'b0;
				if(!bit_turn)//渐亮
					begin
					cnt_PWM_set<=cnt_PWM_set+1'b1;
					if(cnt_PWM_set>8'd99)		
							bit_turn=!bit_turn;//满亮度跳转
					end
				else //渐灭
					begin
					cnt_PWM_set<=cnt_PWM_set-1'b1;	
					if(cnt_PWM_set<8'd1)
						begin
							bit_turn<=!bit_turn;//满暗度跳转
							cnt_PWM_set<=1'b0;
							cnt<=1'b0;
						end
					end
			end
	
	end		
always @(posedge CLK or negedge res)
if(!res)
	LED<=3'b111;
else if(cnt_PWM>cnt_PWM_set)
	LED<=3'b0;
else 		
	LED<=3'b111;

endmodule	

五、AD9851时序编写

FPGA很大一个特点就是进行时序的设计,他可以自由编写各种通用时序协议,以及个人设计的独特的时序协议。所以我基于AD9851这一款芯片练习了一下时序协议的编写,代码如下


module  ad9851_ctrl
#(
	parameter CNT_MAX = 24'd9_999_999,
	parameter clk_MAX = 28'd180_000_000,
	parameter ju_2_32 = 36'd4_294_967_296
)
(
	 input   wire   	     sys_clk    ,  
	 input   wire   	     sys_rst    ,  
	 input   wire   	     key_in     ,  
	 input   wire [27:0]   f_in       ,
	 input   	  [4:0]    p_in       ,//相位控制字
	 output  reg  [7:0]    data_out   ,    
	 output  reg 		     AD985x_clk ,
	 output  reg		     AD985x_fq  
	 
);

reg  [2:0] 	stae 			;
reg       	clk_flag		;
reg       	over_flag 	;
reg  [2:0] 	w0_3=3'b001 ;		//芯片功能设置
wire [60:0] f3;
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

assign f3=(ju_2_32*f_in/clk_MAX );		//频率控制字
always @(posedge sys_clk or negedge sys_rst)
	if(sys_rst==1'b0)
		stae <= 3'd0;
	else if(stae >= 3'd6)
		stae <= 3'd0;
	else if(key_in==1&&stae==3'd0)
		stae <= 1'b1;
	else if(stae > 3'd0 && AD985x_clk == 1'b1&&stae<3'd6)
		stae <= stae + 1'b1; 
	else
		stae <= stae;

always @(posedge sys_clk or negedge sys_rst)
	if(sys_rst==1'b0)
		clk_flag<=1'b0;	
	else if(AD985x_fq==1'b1)
		AD985x_fq=1'b0;
	else if(stae==3'd0)
		clk_flag<=1'b0;	
	else if(AD985x_clk == 1'b0&&clk_flag == 1'b0)
	begin
		case(stae)
			3'd1:
			begin
				data_out<={p_in,w0_3};
				clk_flag<=1'b1;
			end
			3'd2:
			begin
				data_out<=f3[31:24];
				clk_flag<=1'b1;
			end				
			3'd3:
			begin
				data_out<=f3[23:16];
				clk_flag<=1'b1;
			end				
			3'd4:
			begin
				data_out<=f3[15:8];
				clk_flag<=1'b1;
			end	
			3'd5:
			begin
				data_out<=f3[7:0];
				clk_flag<=1'b1;
			end
			3'd6:
			begin
				AD985x_fq<=1'b1;
				clk_flag<=1'b0;
			end
		default:
			begin
				//
				clk_flag<=1'b0;
			end
			
			endcase
	end
	else 
	begin
		AD985x_fq<=1'b0;
		clk_flag <= 1'b0;
	end
always @(posedge sys_clk or negedge sys_rst)
	if(sys_rst==1'b0)
		AD985x_clk <= 1'b0;
	else if(stae==3'd0)
		AD985x_clk <= 1'b0;	
	else if(clk_flag==1'b1)
		AD985x_clk <= 1'b1;
	else
		AD985x_clk <= 1'b0;		
		
		
always @(posedge sys_clk or negedge sys_rst)
	if(sys_rst==1'b0)
		over_flag <= 1'b0;
	else if(over_flag==1'b1&&clk_flag==1'b0)
		over_flag <= 1'b0;	
	else if(stae == 3'd6)
		over_flag <= 1'b1;
	else
		over_flag <= over_flag;

endmodule



总结

以上是我入门FPGA的一些感悟以及学习心得,学到这里只是刚刚入门FPGA,要熟练掌握FPGA需要非常多的基础知识及综合能力,如需要有数字电路设计的逻辑及技巧、精通各种时序协议的规则及设计时序协议能力、精通如USB、TCP\IP其协议栈,会编写其驱动等等,还需要会时序分析,使系统时序满足项目需求。这些都是学好FPGA的难点,需要一个个学习,慢慢积累。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuoyibo.net 版权所有 湘ICP备2023021910号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务