学习笔记:FPGA设计Verilog基础(二)——Verilog文件命名+信号命名规则

1、Verilog命名规则

1.1、顶层文件
对象+功能+top

比如:video_oneline_top

1.2、逻辑控制文件
介于顶层和驱动层文件之间
对象+ctr

比如:ddr_ctr.v

1.3、驱动程序命名
对象+功能+dri

比如:lcd_dri.v、uart_rxd_dri.v

1.4、参数文件命名
对象+para

比如:lcd_para.v

1.5、模块接口命名:文件名+u
比如 :lcd_dir  lcd_dir_u(........)

1.6、模块接口命名:特征名+文件名+u
比如 :mcb_read  c3_mcb_read_u

1.7、程序注释说明:一般出现在新建工程文件内的顶部,或者由//、/*  */、**等符号标示出来的地方。

//////////////////////////////////////////////////////////////////////////////////
// Company: milinker corperation
// Engineer:jinry tang
// WEB:www.milinker.com
// BBS:www.osrc.cn
// Create Date: 07:28:50 07/31/2015
// Design Name: FPGA STREAM
// Module Name: FPGA_USB
// Project Name: FPGA STREAM
// Target Devices: XC6SLX16-FTG256/XC6SLX25-FTG256 Mis603
// Tool versions: ISE14.7
// Description: CY7C68013A SLAVE FIFO comunication with fpga
// Revision: V1.0
// Additional Comments:
//1) _i input
//2) _o output
//3) _n activ low
//4) _dg debug signal
//5) _r delay or register
//6) _s state mechine
//////////////////////////////////////////////////////////////////////////////////

1.8、端口注释

input Video_vs_i,//输入场同步入

1.9、信号命名

命名总体规则:对象+功能(+极性)+特性

1.10、时钟信号
对象+功能+特性

比如:phy_txclk_i、sys_50mhz_i

1.11、复位信号
对象+功能+极性+特性

比如:phy_rst_n_i、sys_rst_n_i

1.12、延迟信号
对象+功能+特性 1+特征 2

比如:fram_sync_i_r0、fram_sync_i_r1

1.13、特定功能计数器
对象+cnt
比如:line_cnt、div_cnt0、div_cnt1
功能+cnt
比如:wr_cnt、rd_cnt
对象+功能+cnt
比如:fifo_wr_cnt、mcb_wr_cnt、mem_wr_cnt
对象+对象+cnt

比如:video_line_cnt、video_fram_cnt

1.14、一般计数器
cnt+序号
用于不容易混淆的计数

比如:cnt0、cnt1、cnt2

1.15、 时序同步信号
对象+功能+特性

比如:line_sync_i、fram_sysc_i

1.16、 使能信号
功能+en
比如:wr_en、rd_en
对象+功能+en

比如:fifo_wr_en、mcb_wr_en

2、Verilog基础语法

C 语言和 Verilog 的关键词和结构对比:

C 语言和 Verilog 运算符对比:

3.Verilog 关键字

3.1信号部分:

    input 关键词,模块的输入信号,比如 input Clk,Clk 是外面关键输入的时钟信号;

    output 关键词,模块的输出信号,属于wire型,比如 output[3:0]Led; 这个地方正好是一组输出信号。其中[3:0]表示 0~3 共 4 路信号。

    inout 模块输入输出双向信号。这种类型属于wire型,我们的例子24LC02 中有使用。数总线的通信中,这种信号被广泛应用;

    wire 关键词,线信号。例如:wire C1_Clk; 其中 C1_Clk 就是 wire 类型的信号;

  线信号,三态类型,我们一般常用的线信号类型有 input,output,inout,wire;

     reg 关键词,寄存器和线信号不同,它可以在 always 中被赋值,经常用于时序逻辑中。比如 reg[3:0]Led;表示了一组寄存器。

 3.2 结构部分

module()
…
endmodule

代表一个模块,我们的代码写在这个两个关键字中间。

3.2.1 always@()

    always@()括号里面是敏感信号。1、这里的 always@(posedge Clk)敏感信号是 posedge Clk ,含义是在上升沿的时候有效,敏感信号还可以 negedge Clk 含义是下降沿的时候有效,这种形式一般时序逻辑都会用到。

    2、还可以是*这个一符号,如果是一个*则表示一直是敏感的,一般用于组合逻辑

3.2.2 assign 

    assign用来给 output,inout 以及 wire 这些类型进行连线。assign 相当于一条连线,将表达式右边的电路直接通过 wire(线)连接到左边,左边信号必须是 wire 型(output 和 inout 属于 wire 型)。当右边变化了左边立马变化,方便用来描述简单的组合逻辑。示例:

wire a, b, y;
assign y = a & b;

这些语句含义上都和高级语言一样:

if(...)begin

............

End

if(...)begin

............

end

else begin

............

End

 

if(...)begin

............

end

else if(...)begin

............

end

 

case(...)

............

endcase

begin

....

end 块作用域范围类似于C的大括号,用法举例:

always@(posdge clk) begin
.....
end

3.3 符号部分:(我们这里 FALSH 为 0,TRUE 为 1)

    “;”分号用于每一句代码的结束,以表示结束,和 C 语言一样。
    “:”冒号,用在数组,和条件运算符以及 case 语句结构中。case 结构会在后面讲解。
    “<=”赋值符号,非阻塞赋值在一个 always 模块中,所有语句一起更新。它也可以表示小于等于,具体是什么含义编译环境根据当前编程环境判断,如果“<=”是用在一个 if 判断里如:if(a <= 10);当然就表示小于等于了。
    “=”阻塞赋值,或者给信号赋值,如果在 always 模块中,这条语句被立刻执行。阻塞赋值和非阻塞赋值将再后面详细举例说明。
    “+,-,*,/,% ”是加、减、乘、除运算符号,这些使用和 C 语言基本是一样的,当你用到这些符号时,编译后会自动生成或者消耗 FPGA 原有的加法器或是乘法器等。其中符号/,%会消耗大量的逻辑,谨慎使用。
    “<”小于,比如 A<B 含义就是 A 和 B 比较,如果 A 小于 B 就是 TURE,否则为 FALSE。
    “<=”小于等于,比如 A<=B 含义就是 A 和 B 比较,如果 A 小于等于 B 就是 TURE,否则为 FALSE。
    “>”大于,比如 A>B 含义就是 A 和 B 比较,如果 A 大于 B 就是 TURE,否则为 FALSE。
    “>=”大于等于,比如 A>=B 含义就是 A 和 B 比较,如果大于等于 B 就是 TURE,否则为 FALSE。
    “==”等于等于,比如 A==B 含义就是 A 和 B 比较,如果 A 等于 B 就是 TURE,否则为FALSE。

    “!=”不等于,A!=B 含义是 A 和 B 比较,如果 A 不等于 B 就是 TURE,否则为 FALSE.

    “>>”右移运算符,比如 A>>2 表示把 A 右移 2 位。
    “<<”左移运算符,比如 A<<2 表示把 A 左移 2 位。
    “~”按位取反运算符,比如 A=8’b1111_0000;则~A 的值为 8’b0000_1111;
    “&”按位于与,比如 A=8’b1111_0000;B=8’b1010_1111;则 A&B 结果为 8’b1010_0000;
   “^”异或运算符,比如 A=8’b1111_0000;B=8’b1010_1111;则 A^B 结果为 8’b0101_1111;
   “&&”逻辑与,比如 A==1,B==2;则 A&&B 结果为 TRUE;如果 A==1,B==0,则 A&&B 结果为 FALSE,一般用于条件判断。
    A = B ? C : D 是一个条件运算符,含义是如果 B 为 TRUE 则把 C 连线 A,否则把 D连线 A。B 通常是个条件判断,用小括弧括起:assign C1_Clk = (C1==25'd24999999) ? 1 : 0 ; C1_Clk,是一个 wire 类型的信号,当 C1==25'd24999999 时候,连线到 1,否则连线到 0.

    “{}” Verilog 中表示拼接符,{a,b}这个的含义是将括号内的数按位并在一起,比如:{1001,1110}表示的是 10011110。拼接是 Verilog 相对于其他语言的一大优势,在以后的编程中请慢慢体会。

3.4 参数部分

    parameter 定义一个符号 a 为常数(十进制 180 找个常量的定义等效方式):

parameter a = 180;//十进制,默认分配长度 32bit(编译器默认)
parameter a = 8’d180;//十进制
parameter a = 8’haa; //十六进制
parameter a = 8’b1010_1010; //二进制

    预处理命令

//--------------------------------
`include file1.v
//--------------------------------
`define X = 1;
//--------------------------------
`deine Y;
`ifdef Y
    Z=1;
`else
    Z=0;
`endif
//--------------------------------

      有的时候我们一些公共的宏参数,我们可以放在一个文件中,比如这个文件名字为xx.v 那么`include xx.v 就可以包含这个文件中定义的一些宏参数。我还是来详细说明下吧!

      话说 Verilog 的`include 和 C 语言的 include 用法是一样一样的,要说区别可能就在于那个点吧。

      include 一般就是包含一个文件,对于 Verilog 这个文件里的内容无非是一些参数定义,所以这里再提几个关键字:`ifdef、 `define、 `endif(他们都带个点,呵呵)。

      他们联合起来使用,确实能让你的程序多样化,就拿 VGA 程序说事吧。
      首先,你可以新建一个.v 文件(可以直接新建一个 TXT,让后将后缀换成.v)其实这个后缀没所谓,.v 也是可以的,我觉得,写成.v 更能体现出这个文件的意义。
      假设有个 lcd_para.v 文件,内容如下:

// 640 * 480
`ifdef VGA_640_480_60FPS_25MHz
`define H_FRONT 11'd16
`define H_SYNC 11'd96
`define H_BACK 11'd48
`define H_DISP 11'd640
`define H_TOTAL 11'd800
`define V_FRONT 11'd10
`define V_SYNC 11'd2
`define V_BACK 11'd33
`define V_DISP 11'd480
`define V_TOTAL 11'd525
`endif
// 800 * 600
`ifdef VGA_800_600_72FPS_50MHz
`define H_FRONT 11'd56
`define H_SYNC 11'd120
`define H_BACK 11'd64
`define H_DISP 11'd800
`define H_TOTAL 11'd1040
`define V_FRONT 11'd37
`define V_SYNC 11'd6
`define V_BACK 11'd23
`define V_DISP 11'd600
`define V_TOTAL 11'd666
`endif
//---------------------------------
`define H_Start (`H_SYNC + `H_BACK)
`define H_END (`H_SYNC + `H_BACK + `H_DISP)
`define V_Start (`V_SYNC + `V_BACK)
`define V_END (`V_SYNC + `V_BACK + `V_DISP)

     这 里 为 VGA 定 义 了 两 种 分 辨 率 , 通 过 `define VGA_800_600_60MHz 或`define VGA_640_480_60FPS_25MHz或`define VGA_800_600_72FPS_50MHz 来决定使用哪种分辨率。

       比如,我的 xxx.v 文件想调用 lcd_para.h,那么 xxx.v 我可以写到:

<span style="color:#ff0000">`define VGA_800_600_60MHz //这句要放在"lcd_para.h"的上面,不然编译不通过
`include "lcd_para.h"
</span>

        那么 xxx.v 文件中就可以用 lcd_para.v 中的参数了,且对应是 VGA_800_600_60MHz下的参数。

        其次`include "lcd_para.v" 这个路径也有一点讲究xxx.v 作为引用 lcd_para.v 的文件,它和 lcd_para.v 在同一文件夹下才能这么写,就是相对路径一说了。也就是以xxx.v 为当前路径去引索 lcd_para.v 文件的位子。所以如果他们不再一个文件夹那么请写出更详细(正确)的路径。顺便说一句,lcd_para.v 添不添加到工程是无所谓的,只要路径对了即可,当然我还是建议添加到工程,且和.v 文件放在同一文件夹下,以方便观察和管理。

4、Verilog 中数值表示的方式

如果我们要表示一个十进制是 180 的数值,在 Verilog 中的表示方法如下:
二进制:8’b1010_1010; //其中“_”是为了容易观察位数,可有可无。
十进制:8’d180;

16 进制:8’h AA;

发布了150 篇原创文章 · 获赞 200 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/qq_37764129/article/details/79510571