1.基于接口名称的模块例化
Instance <unit_instance>(
// <>内的内容可以根据自己的需要,自行命名
.sclk (sclk), //前者代表被例化的名字 ,后者sclk代表外部接线的名字
.rst_n (rst_n),
.data (qout),
.addr (addr)
);
2.输入输出端口的声明
输入接口用缩写port input 的首字母替代 pi_xx
//
//输入使能信号(高有效)
input wire [0:0] pi_en;
//
//输入片选信号(低有效)
input wire [0:0] pi_cs_n;
3.位宽匹配
wire [15:0] sin_data;
assign sin_data = 16'd1024;
4. 信号命名
counter_a;cnt_a;div_cnt;
data_dly1;data_dly2; // 此类命名可以方便理解延迟几拍
wr_addr
5.时钟复位信号的命名
Sys_clk;sclk;
sys_rst_n;// 低复位把n标出来
s_rst_n;
s_rst;
///
//不推荐此类命名
clk;clock
rst;reset;reset_n;rst_n
6.三态总线的写法
inout tri [7:0] bus_z;
input wire [7:0] bus_tri;
input wire [7:0] pio_bis;
7. Parameter 声明
参数定义推荐
parameter DATA_WIDTH = 16;
parameter DIV_END_NUM = 1024;
//参数定义最好写成大写
8. 禁止使用门控时钟
在FPGA设计中禁止使用门控时钟,这样时钟无法保证skew,而且容易因为延迟不一致造成毛刺产生和占空比失调
9. 用异步方法解决单比特数据跨时钟域方法
/
//
always @(posedge sclk_a or negedge s_rst_n)
//
always @(posedge sclk_a or negedge s_rst_n)
//
always @(posedge sclk_a or negedge s_rst_n)
10. 同步复位和异步复位
//同步复位
always @(posedge sclk)
//异步复位
always @(posedge sclk or negedge s_rst_n)
11. 避免生成锁存器
下面代码由于没有 2'b11 条件下的赋值操作会导致综合器产生锁存器
always @ (data)
case(data)
2'b00:sel_a=1'b1;
2'b01:sel_a=1'b0;
2'b10:sel_a=1'b1;
endcase
//
//
避免生成锁存器的:
赋值初始值
对应所有输入条件都有对应的输出
用else 或者elseif 结束条件分支
12.组合逻辑使用阻塞赋值
///
// 描述组合逻辑用阻塞赋值 “=”
always@(c_a or c_b)
if(c_a == 1'b1)
sel=1'b1;
else
sel=c_b;
13.时序逻辑用非阻塞赋值
/
//描述时序电路用非阻塞赋值 "<="
always @(posedge sclk or negedge s_rst_n)
if(s_rst_n == 1'b0)
po_data <= 8'd0;
else
po_data <= config_a
14. VHDL要点
1 死(程序的基本结构和规范);
2 活 (语法的灵活性和区别:比如assign/always ,阻塞赋值/非阻塞赋值);
3 6大法宝;
Wire reg assign always if case