我的Verilog HDL学习历程(一) Verilog基本语法与应避免的问题

作为一个Verilog初学者,想在此记录下自己的学习历程。

我的老师说的一句话我很赞同,不用刻意地去学很多Verilog的语法,
就像我们大多数人都不会抱着一本word2016使用大全来从头学word一样。Verilog只是一个工具,现学现卖,熟能生巧就行了。

下面首先介绍一下Verilog的一些基本的语法。

Verilog当中的常用数据类型

reg 寄存器型,但综合不一定生成寄存器
wire 线型
paramater 参数,使用参数可以避免大面积修改代码
memory 通过拓展reg型达到类似二维数组的效果

always块

always块,顾名思义就是总是执行的语句块。只要符合激励条件,就会被执行。一个module当中的always块都是并行执行的。
组合逻辑的always块:
always @ 后面应跟敏感信号,就是只要这些敏感信号发生变化,always块就会被执行。为了避免遗漏,常常直接写always @ *来包含所有输入的敏感信号。
always块的输入只能是线型。
举个栗子:8-3优先编码器

module pencoder_8_3(
    input [7:0] in,
    output reg [2:0] out
);
always @ *
begin
    casez(in)
        8'b1???????: out=3'b111;
        8'b01??????: out=3'b110;
        8'b001?????: out=3'b101;
        8'b0001????: out=3'b100;
        8'b00001???: out=3'b011;
        8'b000001??: out=3'b010;
        8'b0000001?: out=3'b001;
        8'b00000001: out=3'b000;
    endcase
end
endmodule // 8_3_pencoder

时序逻辑的always块

时序逻辑与组合逻辑略有不同。时序电路通常是由时钟控制的,因此always块的激励信号应当是时钟的边沿信号。当然有时候会包含其他的,例如复位信号。
并且一定注意,时序逻辑一定要用非阻塞赋值<=。至于原因和原理可以参考这篇:
Verilog中的阻塞与非阻塞赋值

话不多说,上例子:
非常简单的D触发器

module dff(
    input clk,
    input d,
    output reg q
);
always @(posedge clk) 
begin
    q<=d;
end
endmodule // dff

初学者应避免的问题

这才是本文的重点!!我想总结一下我遇到的问题

  • 一定是先有电路再有代码!不要通过语法来凑功能!
    Verilog只是一个工具,它是帮你把心中的电路表达出来,让EDA工具看懂。但它绝对不能像C、python那样,不能只追求“我实现了功能了”,写出的代码一定要物理可实现
    但是心里有电路,当然不需要事无巨细。这是RTL级,就是register transfer level,寄存器传输级。心里的电路不需要具体到与门或门,而是起码要知道输入输出是什么以及基本的框架。

  • 组合逻辑电路if-else情况要写全!
    这是描述电路的,一定要说清楚每种情况下的输出是什么,不然综合的时候就会出锁存器,就有一堆意想不到的问题。

  • 一个always块尽量只赋值一个变量!
    一个module大多情况下会有许多输出,但是一定不要写一个always把输出都挤到一起去!因为每个输出的赋值逻辑都不同,而且看上去会很乱。应当一个module写多个always块,尽量把输出变量分开写到多个always中。

  • 严禁在always块内调用别的模块
    就是严禁!
    再想到什么,会持续更新…

你可能感兴趣的:(Verilog,HDL,verilog,fpga)