FPGA基础知识点

这篇具有很好参考价值的文章主要介绍了FPGA基础知识点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FPGA知识点

Verilog基础语法

基础知识

逻辑值
  • 逻辑0:表示低电平,也就是对应电路GND

  • 逻辑1:表示高电平,也就是对应电路VCC

  • 逻辑X:表示未知,有可能是高电平也有可能是低电平

  • 逻辑Z:表示高阻态,外部没有激励信号,是一个悬空状态

数字进制格式

Verilog数字进制格式包括二进制(b)八进制(o)十进制(d)十六进制(h)

一般常用的为二进制、十进制和十六进制。

二进制表示如下:

4b’0101表示4位二进制数字0101

十进制表示如下:

4’d2表示4位十进制数字2(二进制0010)

十六进制B表示如下:

4’ha表示4位十六进制数字a(二进制1010)

可以增加下划线来增加可读性

16’b1001_1010_1010=16’h9AA9

标识符

标识符(identifier)用于定义模块名端口名信号名等。

标识符可以是任意一组字母数字$符号和**_(下划线)符号**的组合;

但标识符的第一个字符必须字母或者下划线

标识符是区分大小写的。

标识符推荐写法:

  • 不建议大小写混合使用

  • 普通内部信号建议全部小写

  • 信号命名最好体现信号的含义,简洁、清晰、易懂;

以下是一些推荐的写法:

  • 用有意义的有效名字如sum、cpu、addr等

  • 用下划线区分词,如cpu_addr

  • 采用一些前缀或者后缀,比如时钟采用clk前缀:clk_50,clk_cpu

数据类型

在Verilog语言中,主要有三大类数据类型:

寄存器数据类型线网数据类型参数数据类型

真正在数字电路中起作用的数据类型应该是寄存器数据类型线网数据类型

寄存器类型

寄存器表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器储存的值

寄存器数据类型的关键字是reg,reg类型数据的默认初始值为不定值X

//reg define
.reg [31:0] delay_cnt;  //延时计数(表示这是一个32位寄存器,高位在前,低位在后)
Reg key_reg;  //默认位宽为1

reg类型的数据只能在always语句initial语句中被赋值。

  • 如果该过程语句描述的是时序逻辑,即always语句带有时钟信号,则该寄存器变量对应为触发器

  • 如果该过程语句描述的是组合逻辑,即always语句不带有时钟信号,则该寄存器变量对应为硬件连线

线网类型

线网数据类型表示结构实体(例如门)之间的物理连线。

线网类型的变量不能储存值,它的值是由驱动它的元件所决定的。

驱动线网类型变量的元件有门、连接赋值语句、assign等。

如果没有驱动元件连接到线网类型的变量上,则该变量就是高阻的,即其值为z。

线网数据类型包括wire型tri型,其中最常用的就是wire类型

//wire define 
wire key_flag;
参数类型

参数其实就是一个常量,在Verilog HDL中用parameter定义常量。

我们可以一次定义多个参数,参数与参数之间需要用逗号隔开。

每个参数定义的右边必须是一个常数表达式。

//parameter define 4.3'RGB LCD
parameter H_SYNC  = 11'd41; //行同步
parameter H_BACK  = 11'd2;  //行显示后沿
parameter H_DISP  = 11'd480 //行有效数据
parameter H_FRONT = 11'd2   //行显示前沿
parameter H_TOTAL = 11'd525 //行扫描周期

参数型数据常用于定义状态机的状态数据位宽延迟大小等。

采用标识符来代表一个常量可以提高程序的可读性可维护性

模块调用时,可通过参数传递来改变被调用模块中已定义的参数。

运算符

Verilog中的操作运算符按照功能可分为以下类型:

  1. 算术运算符

    符号 使用方法 说明
    + a+b a加上b
    - a-b a减去b
    * a*b a乘以b
    / a/b a除以b
    % a%b a模除b
  2. 关系运算符

    符号 使用方法 说明
    > a>b a大于b
    < a<b a小于b
    <= a>=b a大于等于b
    >= a<=b a小于等于b
    == a==b a等于b
    != a!=b a不等于b
  3. 逻辑运算符

    符号 使用方法 说明
    !a a的非,a如果为0,那么a的非是1
    && a&&b a与上b,如果a和b都为1,a&&b结果才为1,表示真
    || a||b a或上b,如果a或者b有一个为1,a ||b结果为1,表示真
  4. 条件运算符

    符号 使用方法 说明
    ?: a?b;c 如果a为真,就选择b,否则选择c
  5. 位运算符

    符号 使用方法 说明
    ~ ~a 将a的每个位进行取反
    & a&b 将a的每个位与b相同的位进行相与
    | a|b 将a的每个位与b的相同位进行相或
    ^ a^b 将a的每个位与b的相同位进行异或

    如果a和b位宽不一致,系统会在较短的位宽的数据前面补0,补到二者位宽一致,再进行位运算

  6. 移位运算符

    符号 使用方法 说明
    << a<<b 将a左移b位
    >> a>>b 将a右移b位

    两种移位运算都用0来填充移出的空位

    左移时,位宽增加;右移时,位宽不变

    4'b1001 << 2 = 6'b100100
    4'b1001 >> 1 = 4'b0100
    
  7. 拼接运算符

    符号 使用方法 说明
    {} {a,b} 将a和b拼接起来,作为一个新信号
    c = {a,b[3:0]}; 
    c[11:0] = {a[7:0],b[3:0]};
    

运算符优先级

fpga中标识符四个组成部分,fpga开发

Verilog程序框架

Verilog注释

verilog中有两种注释方式
一、以//开头的语句,它表示以//开头到本行结束都属于注释语句
二、以/*开头,以*/结束,在两个符号之间的语句都是注释语句,因此可以扩展到多行。

Verilog关键字

fpga中标识符四个组成部分,fpga开发

常用关键字

fpga中标识符四个组成部分,fpga开发

Verilog程序框架

Verilog的基本设计单元是”模块“(block)

一个模块是由两部分组成的,一部分描述接口,另一部分描述逻辑功能。

module block (a,b,c,d);//定义模块
	input a,b;//输入接口
	output c,d;//输出接口

assign c = a | b;//描述模块的功能
assign d = a & b;

endmodule

每个verilog 程序包括4个主要的部分:

端口定义、IO说明、内部信号声明、功能定义。

module flow_led(
    input sys_clk,         //系统时钟
    input sys_rst_n,      //系统复位,低电平有效
    
    output reg [3:0] led   //4个led灯 四位 reg表示输出端口是一个寄存器类型的端口
);
    //reg define
    reg [23:0] counter;//寄存器型 24位 计数器
    //main code 
    //计数器对系统时钟计数,计时0.2秒
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            counter <= 24'd0;
        else if(counter < 24'd1000_0000)
            counter <= counter + 1'b1;
        else 
            counter <= 24'd0;
    end
    
    //通过移位寄存器控制IO口的高低电平,从而改变LED的显示状态、
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            led <=4'b0001;
        else if(counter == 24'd1000_0000)
            led[3:0] <={led[2:0],led[3]};
        else 
            led <= led;
    end//这两个always模块在执行时是同时执行的,而在里面是顺序执行的
    
endmodule
    

功能定义有三种方法:

  1. assign语句

    描述组合逻辑

  2. always语句

    描述组合/时序逻辑

  3. 实例化元件

    如:and#2 u1(q,a,b)

上述三种逻辑功能是并行

注意:

在always块中,逻辑是顺序执行的。而多个always块之间是并行的。

模块的调用

在模块调用时,信号通过模块端口在模块之间传递。

module seg_led_static_top (
	input sys_clk,         //系统时钟
    input sys_rst_n,       //系统复位信号(低电平有效)
    
    output [5:0] sel,      //数码管位选
    output [7:0] seg_led   //数码管段选
);
    //parameter define
    parameter TIME_SHOW = 25'd2500_0000;//数码管变化的时间间隔0.5s
    
    // wire define 
    wire add_flag;//数码管的通知信号
    
    //main code 
    
    //每隔0.5s产生一个时钟周期的脉冲信号
    time_count #(
        .MAX_NUM (TIME_SHOW) //这里是参数,MAX_NUM 给参数传递一个新值TIME_SHOW
    )   u_time_count(
        .clk (sys_clk),
        .rst_n (sys_rst_n),
        
        .flag (add_flag)//输出信号连接到上层的wire类型的变量里面,输出段必须连接到一个wire类型的变量,否则会报错,并且位宽必须保持一致
    );
    module time_count(
    	input clk,
    	input rst_n,
        
        output reg flag
    );
    //parameter define
    parameter MAX_NUM = 5000_0000;
    //reg define
    reg [24:0] cnt;
    //另外一种端口连接方式:
    //每隔0.5s产生一个时钟周期的脉冲信号
        time_count #(
            .MAX_NUM (TIME_SHOW)
        ) u_time_count(
        	sys_clk,
            sys_rst_n,
            
            add_flag
        );

Verilog高级知识点

结构语句

initial和always语句

initial(初始化)语句它在模块中只执行一次。它常用于测试文件地编写,用来产生仿真测试信号(激励信号),或者用于对存储器变量赋初值。

always语句一直在不断地重复活动。

但只有和一定的时间控制结合在一起才有作用。

initial begin
	sys_clk           <=1'b0;
    sys_rsr_n         <=1'b0;
    touch_key         <=1'b0;
    #20 sys_rst_n     <=1'b1; //#20: 延时20个单位时间,20ns
    #10 touch_key     <=1'b1;//#10:相对于上一个sys_rst_n延时的20ns再延时10ns把电位调高
    #30 touch_key     <=1'b0;
    #110 touch_key    <=1'b1;
    #30  touch_key    <=1'b0;
end
//产生50Mhz的时钟,周期为20ns
always #10 sys_clk <= ~sys_clk;//延时10ns取反
    

always的时间控制可以是沿触发,也可以是电平触发

可以是单个信号也可以是多个信号,多个信号中间要用关键字or连接。

always @(posedge sys_clk or negedge sys_rst_n) begin  //posedge上升沿、negedge下降沿
    //按顺序执行
    if(!sys_rst_n)
        counter <= 24'd0;
    else if(counter < 24'd1000_0000)
        counter <= counter + 1'b1;
    else 
        counter <= 24'd0;
end

沿触发的always块常常描述时序逻辑行为

由关键词or连接的多个事件名或信号名组成的列表称为“敏感列表”。

电平触发的always块常描述组合逻辑行为。

always @(a or b or c or d or e or f or g or h or p or m) begin
    out1 = a ? (b+c) : (d+e);
    out2 = f ? (g+h) : (p+m);
end

如果组合逻辑块语句的输入变量很多,那么编写敏感列表会很繁琐并且容易出错,

always @( * ) begin //@( * )表示后面语句块中所有输入变量的变化都是敏感的。
    out1 = a ? (b+c) : (d+e);
    out2 = f ? (g+h) : (p+m);
end

根据逻辑功能的不同特点,可以将数字电路分成两大类:

组合逻辑电路时序逻辑电路

  • 组合逻辑电路中,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关
  • 时序逻辑电路中,任意时刻的输出不仅取决于当时的输入的信号,而且还取决于电路原来的状态。或者说还与以前的输入有关,因此时序逻辑必须具备记忆功能

fpga中标识符四个组成部分,fpga开发

赋值语句

Verilog HDL语言中,信号有两种赋值方式

  • 阻塞赋值(blocking),如a = b

    串行执行

    阻塞赋值可以认为只有一个步骤的操作:即计算RHS并更新LHS。

    所谓阻塞的概念是指,在同一个always块中,后面的赋值语句是在前一句赋值语句结束后才开始赋值的。

    always @(posedge clk or negedge rst_n) begin 
        if (!ret_n)begin 
            a = 1;
            b = 2;
            c = 3;
        end
        else begin 
            a = 0;
            b = a;
            c = b;
        end
    end
    

fpga中标识符四个组成部分,fpga开发

  • 非阻塞赋值(Non_Blocking),如b <= a;

    并行执行

    非阻塞赋值的操作过程可以看作两个步骤:

    1. 赋值开始的时候,计算RHS;
    2. 赋值结束的时候,更新LHS。

    所谓非阻塞的概念是指,在计算非阻塞赋值的RHS以及更新LHS期间,运行其他的非阻塞赋值语句同时计算RHS和更新LHS。

    always @(posedge clk or negedge rst_n) begin 
        if (!ret_n)begin 
            a <= 1;
            b <= 2;
            c <= 3;
        end
        else begin 
            a <= 0;//右侧同时计算结果但不赋值,此时0还没赋值给a,a还是1
            b <= a;// a = 1
            c <= b;// b = 2
        end
    end
    

    非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial块和always块等过程块中。

fpga中标识符四个组成部分,fpga开发

在描述组合逻辑的always块中用阻塞赋值=,综合成组合逻辑的电路结构;

这种电路结构只与输入电平的变化有关系。

在描述时序逻辑的always块中用非阻塞赋值<=,综合成时序逻辑的电路结构;

这种电路结构往往与触发沿有关系,只有在触发沿时才可能发生赋值的变化。

注意:在同一个always块中不要即用非阻塞赋值又用阻塞赋值

不允许在多个always块中对同一个变量进行赋值!

条件语句

if -else语句
	// (1)
	if(a>b)
   		cout= data_1
    //(2)
        if(a>b)
            out = data_1;
		else
            out = data_2;
	//(3)
    if(表达式)
        语句
    else if(表达式)
        语句
    else if(表达式)
        语句
    else 
        语句

条件语句必须在过程块中使用

  • 过程块语句是指由initial和always语句引导的块语句

注意事项:

  1. 允许一定形式的简写,如:

    if(a)等同于if(a==1)

    if(!a)等同于if(a!=1)

  2. if语句对表达式的值进行判断,若为0,x,z则按假处理;若为1,按真处理

  3. if和else后面的操作语句可以用begin和end包含多个语句。

  4. 允许if语句的嵌套。

fpga中标识符四个组成部分,fpga开发

case语句(多分支选择语句)
  1. 分支表达式的值互不相同;

  2. 所有表达式的位宽必须相等;

    不能用‘bx来代替n’bx

  3. casez

    比较时,不考虑表达式中的高阻值z

  4. casex

    比较时不考虑高阻值z和不定值x
    fpga中标识符四个组成部分,fpga开发

fpga中标识符四个组成部分,fpga开发

状态机

状态机的概念

fpga中标识符四个组成部分,fpga开发

状态机(State Machine)

  • 有限状态机(Finite State Machine,简称FSM)
  • 在有限个状态之间按一定规律转换的时序电路。

状态机模型

fpga中标识符四个组成部分,fpga开发

fpga中标识符四个组成部分,fpga开发

状态寄存器由一组触发器组成,用来记忆状态机当前所处的状态,状态的改变只发生在时钟的跳变沿。

状态是否改变、如何改变,取决于组合逻辑F的输出,F是当前状态和输入信号的函数。

状态机的输出是由输出组合逻辑G提供的,G也是当前状态和输入信号的函数。

状态机设计

四段论

  • 状态空间定义

    //define state space 
    parameter SLEEP   =   2'b00;
    parameter STUDY   =   2'b01;
    parameter EAT     =   2'b10;
    parameter AMUSE   =   2'b11;
    
    //internal veriable
    reg [1:0] current_state;
    reg [1:0] next_state;
    
    //独热码
    //define state space;
    parameter SLEEP   =  4'b1000;
    parameter STUDY   =  4'b0100;
    parameter EAT     =  4'b0010;
    parameter AMUSE   =  4'b0001;
    
    //internal variable
    reg [3:0] current_state;
    reg [3:0] next_state;
    

    独热码:每个状态只有一个寄存器置位,译码逻辑简单。

  • 状态跳转

    //transition
    always @(posedge clk or negedge rst_n)begin//敏感列表:时钟信号以及复位信号边沿的组合
        if(!rst_n)
            current_state <= SLEEP;
        else
            current_state <= next_state;//时序逻辑里使用非阻塞赋值
    end
    
  • 下个状态判断(组合逻辑)

    //next state decision
    always @(current_state or input_signals)begin//敏感信号表:所有的右边表达式中的变量以及if、case条件中的变量
        case (current_state)//case的状态没给全也会产生锁存器,多余的状态用default
            SLEEP:begin
                if(clock_alarm)
                    next_state = STUDY;//使用阻塞赋值
                else 
                    next_state = SLEEP;
            end
            
            STUDY: begin
                if(lunch_time)
                    next_state = EAT;
                else //if /else 要配对,避免latch(锁存器)的产生,只在组合逻辑中产生
                    next_state = STUDY;
            end
            
            EAT: ...;
            
            AMUSE: ...;
            
            default: ...;
        endcase
    end
    
  • 各个状态下的动作

    //action
    wire read_book;
    assign read_book = (current_state == STUDY) ? 1'b1: 1'b0;
    
    always @(current_state)begin
        if(current_state == STUDY)
            read_book = 1;
        else 
            read_book = 0;
    end
    

fpga中标识符四个组成部分,fpga开发

fpga中标识符四个组成部分,fpga开发

fpga中标识符四个组成部分,fpga开发文章来源地址https://www.toymoban.com/news/detail-772972.html

到了这里,关于FPGA基础知识点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Go 基础篇】Go语言关键字和预定义标识符解析:探索编程的基石与核心要素

    在计算机编程中,(Keywords)和预定义标识符(Predefined Identifiers)是编程语言的核心要素,它们在语法结构和语言功能中起到重要作用。在Go语言(Golang)中,和预定义标识符定义了编程的基本规则和构建块,是实现功能的关键。本篇博客将深入探讨Go语言中的关

    2024年02月12日
    浏览(51)
  • [HTML]Web前端开发技术25(HTML5、CSS3、JavaScript )JavaScript基础消息对话框告警框确认框提示框命名规范1标识符2关键字3保留字注释标识符和变量——喵喵画网页

    希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 目录 前言 JavaScript程序 代码 消息对话框 消息对话框-告警框 消息对话框-确认框 消息对话框-提示框 JavaScript注释

    2024年02月20日
    浏览(38)
  • FPGA知识点(不断增加......)

    1.1读写同时进行的FIFO   对于读写同时进行的FIFO,有一个简便计算深度的公式:   FIFO_Depth = Burst_length -Burst_length* (rd_clk/ wr_clk)*(rd_rate) (其中Burst_length可以认为是连续两个cycle可以写入的数据量)   如:同步fifo,100个cycle可以写入80个数据,10个cycle可以读出8个数据,f

    2024年02月13日
    浏览(38)
  • FPGA面试-常用知识点

    本贴记录一下自己找工作过程中顺下来的知识点,如有错误的,请不吝指出,共同进步!   a) FPGA FPGA 基于 LUT ,LUT本质上就是一个RAM,每一个LUT可以看成一个有4位地址线的16x1的RAM。这也是为什么FPGA需要外接一个rom来上电配置。 包括 CLBs , I/O 块, RAM 块和可编程连线 。 在

    2024年04月26日
    浏览(30)
  • 平时积累的FPGA知识点(8)

    平时在FPGA群聊等积累的FPGA知识点,第八期: 有遇到过FFT IP核测量频率不准确的问题吗?大部分情况下都是准的,偶尔偏差比较大,IP核输入的数据用matlab计算出的频率是对的。 解释:可能是采样点数不对, 如果采样率是固定的,那只有点数会影响频率了。IP不会自动处理,要

    2024年02月20日
    浏览(33)
  • 平时积累的FPGA知识点(9)

    平时在FPGA群聊等积累的FPGA知识点,第9期: 解释:Xilinx公司的Zynq UltraScale+ RFSoC系列芯片进行项目开发,在某些芯片型号中,自身带有SD-FEC硬核资源,具体查询方式,可在Xilinx官方网站检索DS889手册。 SD-FEC集成块硬核资料可在Xilinx网站下载,PG256便是该IP产品手册。这个SD-FEC

    2024年02月20日
    浏览(33)
  • 平时积累的FPGA知识点(7)

    平时在FPGA群聊等积累的FPGA知识点,第七期: 解释:ug949 解释:无法单独指定IP的使用方式。 解释:是的,这一条命令对所有层次的子模块都起作用 解释:因为用report_high_fanout_net报告的net个数太少,把选项-max的值放大,同时添加选项fanout_greater_than 或者fanout_lesser_than 解释:

    2024年02月20日
    浏览(46)
  • 平时积累的FPGA知识点(6)

    平时在FPGA群聊等积累的FPGA知识点,第六期: 原因:没做时钟约束,万兆网接口的实现,本质上都是高速serdes,用IP的话,IP会自带约束。 解释:如果是7系列FPGA就要约束,之后的就不用。 解释:上次闪退的时候破坏了run文件夹里的内容,把这个文件夹删除了之后就可以正常

    2024年02月20日
    浏览(31)
  • 错误C2065:未声明的标识符 - 解决C++中的未声明标识符错误

    错误C2065:未声明的标识符 - 解决C++中的未声明标识符错误 在C++编程中,错误C2065是一种常见的编译错误,它表示使用了一个未声明的标识符。通常情况下,这个错误是由于忘记包含必要的头文件或者拼写错误导致的。本文将介绍如何解决这个错误,并提供相应的源代码示例

    2024年02月06日
    浏览(33)
  • 【100天精通python】Day2:python入门_ python的语言基础,编码规范,代码注释,缩进,保留字,标识符

    目录  1 编码规范 1.1 编码规范准则 1.2 编码规范示例 2  代码注释 3  缩进

    2024年02月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包