FPGA平台开发基础

本文介绍了FPGA开发的基础,包括Verilog HDL语言语法,如变量类型、赋值方式和时序控制,并通过3-8译码器的实例展示了开发流程。开发涉及模块化设计、逻辑综合和硬件电路映射,同时强调了时序优化的重要性。文章还提供了测试平台的编写方法,帮助嵌入式工程师理解和沟通FPGA项目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章介绍了FPGA平台的使用语言的基本语法,并用一个3-8译码器模块的实例引导嵌入式工程师熟悉FPGA开发的一般流程。FPGA的嵌入式程序最终都会映射成数字逻辑电路,在开发的过程中要保持对实际生成电路的敏感,功能做对的基础上还要考虑时序优化,更别提纷繁复杂的接口协议实现。
本篇文章只是从语言的角度做了一些简单介绍,帮助基于其他平台开发的嵌入式工程师FPGA平台开发有一个大概的认识,能够跟FPGA工程师更顺畅的沟通。

硬件描述语言语法:

Verilog HDL是一种硬件描述语言(HDL:Hardware Description Language),以文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。
FPGA的开发以模块的为基础设计,模块的概念类似于C语言中的函数,提供输入,输出端口,能被其他模块实例调用,也可以调用其他模块实例。顶层模块常被称为“测试平台”(Testbench)。下面是语言的基本组成:

  • 语言要素:空白符。注释。大小写敏感。标识符及保留字。转义标识符。
  • 数据类型:四值逻辑:逻辑低电平,逻辑高电平,高阻态,未知电平逻辑。数字电路中的信号可以用逻辑值,信号强度加以描述。

Verilog所用的所有变量都属于两个基本类型,线网类型和寄存器类型。线网只能通过连续赋值,由赋值符右侧连接的驱动源决定。寄存器的值可以保持当前的赋值。模块的输入端口可以与外界的线网或寄存器类型的变量连接,但是这个模块输出端口只能连接到外界的线网。下面是不同变量的表示形式。

  • 数字表示的基本语法是:<位宽>'<数制的符号><数值>
  • 向量与数组:reg [7:0] my_input [65535:0]; //声明一个有65536个元素的8位向量寄存器。向量是数据类型,而数组是数据的一种组成方式。
  • 参数可以在模块实例化的时候被更改。例如四位数全加器和十六位全加器可以通过参数的实例化同一个通用全加器模块。
  • 运算符:按位操作符,逻辑操作符。缩减操作符最高位与最低位依次进行操作。算数:加,减,乘,除,求幂。关系以及移位。拼接({,}),两个操作数分别作为高地位进行拼接。重复({n{m}}):将操作数m重复n次。

FPGA开发基础:

寄存器变量在过程中赋值。在Verilog中,有两种赋值运算,一种叫做阻塞赋值,其运算符为=,另一种叫做非阻塞赋值,其运算符为<=。在顺序代码块中使用非阻塞赋值,则执行这这一句的同时。线网变量的连续赋值如下:assign #5 out = in1 & in2; //in1和in2逻辑与的结果在5个时间周期后才施加在out上。
事件时序控制的意思是,如果指定的事件发生,则代码被触发执行。他的关键字为@。
z = @(negedge clk) (x+y); //先立即计算表达式(x+y),然后在变量clk下降沿,将表达式的结果赋值给z。经典用法1:一旦某一变量发生变化,就执行某操作always @(a)begin x = x+1;end。
电平敏感时序控制:wait(a),当变量a为真,则执行后面的代码块。
FPGA的过程的时序控制可以通过三种方式实现:延迟时序控制、事件时序控制以及电平敏感时序控制。所有的系统任务名称前都带有美元符号$使之与用户定义的任务和函数相区分。常用的编译指令有文本宏预定义define、include。
begin、end组合代表了这个代码块的各行代码是顺序执行的,这种代码块称为顺序代码块。逻辑综合的含义是将高抽象级别的Verilog代码转化为低抽象级别的逻辑门级电路。自动化逻辑综合工具的出现,硬件描述语言,所需器件工艺信息(工艺库)可以直接被逻辑综合工具读取,通过其内部的自动综合算法,输出符合设计约束的逻辑门级网表。
在这里插入图片描述

开发步骤与实例

FPGA代码需要进行层次化管理。
综合的依据是逻辑设计的描述和各种约束条件,综合的结果则是一个硬件电路的实现方案。
选择芯片和设计的时候要预留一定的逻辑资源余量,以便加入测试部分等。而这也是硬件设计区别于软件设计的一个重要特性。
常见的FPGA芯片厂商有Xilinx(赛灵思);Altera公司(阿尔特拉)。开发步骤:

  1. 文本/原理图的编辑与修改。
  2. 编译。
  3. 综合。
  4. 行为仿真和功能仿真。
  5. 适配。
  6. 功能仿真和时序仿真。
  7. 下载。
  8. 硬件仿真和测试。

FPGA练手小实例:

  • 分频器。
  • 计数器。
  • D触发器。
  • 三态门。
  • 8-3编码器。
  • 8-3优先编码器。
  • 3-8译码器。
  • 8位移位寄存器。
  • 多路选择器。
  • 串行加法器。
  • 简单的运算单元ALU。(根据不同的)

下面是一个3-8译码器modul的实现代码,功能是根据a,b,c三个输入信号来获得一个8位状态寄存器:

module decoder_38(a,b,c,out);

	input a,b,c; //输入端口

	output reg [7:0]out;  //高位在前,低位在后,共8位
	
	always@(a,b,c)begin   //敏感列表,当a,b,c中的一个发生变化就执行begin后面的语句。
		case({a,b,c})    //花括号将a,b,c拼接成一个信号
			3'b000:out = 8'b0000_0001; //always中的赋值必须是reg形式
			3'b001:out = 8'b0000_0010;
			3'b010:out = 8'b0000_0100;
			3'b011:out = 8'b0000_1000;
			3'b100:out = 8'b0001_0000;
			3'b101:out = 8'b0010_0000;
			3'b110:out = 8'b0100_0000;
			//3'b111:out = 8'b1000_0000;
			default:out = 8'b1000_0000;
		endcase
	end

endmodule

下面是针对这个模块的测试文件(testbench),模拟三个输入信号并获得out输出:

`timescale 1ns/1ps
module decoder_38_tb();
	
	reg signal_a, signal_b, signal_c;
	wire [7:0]out;
	
	decoder_38 decoder1(
		.a(signal_a),
		.b(signal_b),
		.c(signal_c),
		.out(out)
		);
		initial begin
			signal_a = 0; signal_b = 0; signal_c = 0;
			#200;
			signal_a = 0; signal_b = 0; signal_c = 1;
			#200;
			signal_a = 0; signal_b = 1; signal_c = 0;
			#200;
			signal_a = 0; signal_b = 1; signal_c = 1;
			#200;
			signal_a = 1; signal_b = 0; signal_c = 0;
			#200;
			signal_a = 1; signal_b = 0; signal_c = 1;
			#200;
			signal_a = 1; signal_b = 1; signal_c = 0;
			#200;
			signal_a = 1; signal_b = 1; signal_c = 1;
			#200;
			$stop;
		end	 
endmodule

FPGA 开发版资料 1数字逻辑电路基础实验 01_led1 #################################### led灯驱动实验 点亮全部8个led 02_led_twinkle #################################### led灯闪烁实验,8个LED灯会以一定频率闪烁 03_led_water #################################### led流水灯实验 04_key_led #################################### 读取按键信号实验 如果按下的是key1,那么点亮LED1 如果按下的是key2,那么点亮LED1-LED2 以此类推,如果下按key8,那么全部点亮8个led 05_ckey_led #################################### 拨码开关驱动控制LED 如果拨码开关推上去1,那么点亮LED1 如果拨码开关推上去2,那么点亮LED2 06_sled #################################### 静态数码管显示实验 8个数码管显示,依次显示显示"0到f" 07_dled #################################### 动态数码管显示实验 08_beep #################################### 蜂鸣器输出报警声实验 滴。。滴。。滴。。 09_uart #################################### PC机上开串口调试助手,发送一个字符到开发板(中间通过串口线相连) FPGA收到字符后,回发给PC机上,在串口助手上显示 10_ps2_keyboard_test #################################### FPGA通过ps2接收键盘数据,然后把接收到的字母A到Z键值转换相应的ASII码,通过串口发送到PC机上。 实验时,需要接键盘,还要用调试助手,下载程序后,在键盘上按下一个键,比如A,则在PC调试助手上可看到A 11_lcd1602 #################################### 本实验是用LCD1602显示英文 显示“HELLO WORLD!” 12_lcd12864 #################################### 本实验是用LCD12864显示英文 显示 Our FPGA EDA NIOS II SOPC FPGA 13_vga256 #################################### 连接开发板的VGA接口和电脑液晶屏, 即可显示640*480分辨率下的256种色彩 14_tlc549adc #################################### 利用状态机实现对TLC549的采样控制,实验时可调节电位器RW1(在开发板底板左下角),改变ADC 的模拟量输入值,数据采集读取后在数码管上显示。可以自己用万用表测一下输入电压, 然后与读取到的数据比较一下。注意:数码管显示的数据不是最终结果,还需要转换。 转换方法: 比如,采样电压值为V ,ADC转换后读取的8位二进制数为D,Vref为参考电压值,这里是2.5V 那么以下等式成立: V=(D/256)*Vref 15_tlc5620dac #################################### 利用状态机实现对tlc5620dac控制,实验时按key1,可选择DAC的通道,数码管1显示,按key2,key3可 输入8位数/模转换值,由数码管3,4显示,按key4,选择输出电压模式,由数码管8显示,0表示1倍,1表示2倍,按key5,将当前数据发送到DAC模块启动一次DA转换,这时可以万用表测量输出,也可以与理论值做下比较。 注意: TLC5620的输出电压为: V(A,B,C,D)=Vref*(Code/256)(1+RNG) Vref为参考电压值,这里是2.5V A B C D表示4个不同的通道,Code为8位二进制数,RNG为电压模式值,为0或1
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值