当前位置:   article > 正文

FPGA平台开发基础_fpga开发

fpga开发

本篇文章介绍了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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

下面是针对这个模块的测试文件(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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/535568
推荐阅读
相关标签
  

闽ICP备14008679号