老生常谈-Coding Style为什么这么重要?(Verilog编码风格)

本文介绍了Verilog编程的编码风格和注意事项,强调了代码的可读性、可维护性和团队一致性的重要性。提出了命名规则、编码要求、四十条编码建议,并提供了个人编码示例,包括代码头信息、输入输出端口声明、always块的使用和模块例化。此外,还提醒开发者关注设计文档、避免竞争冲突、合理使用时钟和复位信号等关键点。

写在前面的话

经常遇见两个人在Debug的时候,第一句话往往是“你的代码风格挺好的”或者“你这代码好乱啊,我都看不懂”之类的话。其实,Verilog编码风格一直是一个令人反感的话题,因为没有完美的编码风格,也不能说一个人的编码风格不好,这好像就在说他字写得丑、人长得不好看一样,伤害到他内心的自尊。

其实每个人都有属于自己的代码风格,阅读与自己风格相似的代码总是更容易理解,心情也十分开心,而一旦遇见一个和自己风格迥异的代码段,往往都没有看下去的欲望,满脑的不舒服。但是有一点需要注意的是,每个人写的代码,不仅仅是自己的,也是世界的,重要的是自己的代码属于“靠谱的”,而不是晦涩难懂、凌乱的。

代码要求

Verilog同其他语言一样,有一些基本的要求,例如代码整洁度可读性可修改性可维护性以及重复移植性等。除此之外,还需兼顾逻辑功能正确仿真速度快综合结果优等更高要求。

对于一个开发小组或公司部门,应该共同制定一套每个开发者都认同的编码风格,共同遵守、编写最简洁的代码风格。

命名规则

选择有意义的信号和变量名,对这些进行简化统一是非常重要的,命名包括信号、变量、状态等含义。
下面列举一些通用规则:
(1)使用有意义、有效的名字。
在特定代码段,例如for和generate,没必要将指针单独列举,直接使用i、j这类就好。
(2)使用缩写,统一缩写名称。
(3)最右侧下划线表示低电平有效,高电平有效信号避免使用下划线。
(4)首字符大写,其余小写。
(5)避免使用保留字。
(6)后缀非常重要。

常用后缀如下:

后缀意义
_Clk时钟信号
_Rstn低电平复位
_n低电平有效
_n低电平有效
_a异步信号
_r寄存器输出
_t临时信号
_next锁存前信号
_z连接到三态输出
_f下降沿有效

常用缩写如下:

全称缩写中文含义
acknowledgeack应答
addressadr地址
arbiterarb仲裁
clockclk时钟
controlctrl控制信号
countcnt计数器
checkchk校验
decodede译码
encodeencd编码
data indin数据输入
data outdout数据输出
decreasedec
enableen使能
errorerr错误
framefrm
generategen生成
grantgnt申请通过
increaseinc
inputin输入
lengthlen长度(帧长)
outputout输出
pointerptr指针
rd enableren读使能
readrd读(操作)
readyrdy应答信号准备好
receiverx接收
transmittx发送
validvld有效信号
requestreq请求
resetrst复位
writewr写操作

四十条编码注意点

(1)看重设计文档,设计之前要把设计思路、数据通路、项目细节等描述清楚,做到项目可控、可实现,从易到难,逐次递进。
(2)设计时尽量使用之前的IP,使用IP开发简单可靠。
(3)单个文件单个模块,文件命名和模块名相同。
(4)顶层模块只包含各个模块的例化连接。
(5)目录结构要做到合理有效。
(6)避免造成竞争冲突。
(7)避免实例化具体门级电路。
(8)模块内部避免三态电路。
(9)注意EDA工具的综合指令,不同综合工具对代码内的综合指令处理方式不同,综合指令放到单独的脚本,避免污染设计源文件。
(10)避免使用锁存器Latch
(11)注意复位信号造成的亚稳态,推荐异步复位同步释放。
(12)所有寄存器要同时复位。
(13)谨慎使用门控时钟,门控时钟用不好会引起毛刺,造成时序问题。
(14)避免使用模块内部的时钟信号,所有时钟在测试时要来源于外部的可控时钟。
(15)避免使用模块内部的复位信号,测试的时候复位来源于外部可控信号。
(16)当个模块尽量使用一个时钟,跨时钟域要单独处理。
(17)避免同时使用上升沿和下降沿。
(18)注意多周期路径和假路径,便于做STA分析。
(19)设计时要预留测试的模式,便于后期DFT。
(20)组合逻辑敏感列表直接写always@(*)。
(21)区分阻塞赋值和非阻塞赋值,不要混用。
(22)状态机电路要合理,推荐学习三段式状态机。
(23)注意case和if else 综合出的电路区别。
(24)begin不另起行。
(25)模块实例化要按照端口名字连接。
(26)无用的信号及时删除,在完成debug后,删除所有debug模块。
(27)避免使用全局变量,localparam。
(28)注意可综合语句,tb语法不要放到设计源文件。
(29)常数声明单独放到一个文件中。
(30)parameter位置靠前。
(31)标识符区分大小写。
(32)信号按功能集中划分区域排序。
(33)组合逻辑用 “=”。
(34)时序逻辑用"<=“。

(35)#delay 在综合会忽略。
(36)不要在多个语句块中,对同一个变量赋值。
(37)一个always块,只描述一个电路。
(38)区别function和task。
(39)尽量避免直接使用乘法、除法取余数等。
(40)输入信号是wire,输出可以wire或reg。
(41)尽量使用同步设计。
(42)不对时钟信号做判断。
(43)避免过长代码,分行写最好。
(44)多利用tab和空格对齐。
(45)模块例化、连线时注意位宽。
(46)例化时检查所有端口。

个人编码示例

这里将本人的编码风格展现出来,欢迎相互交流。

代码头

代码头关键信息包含,谁写的?是什么?什么时候写的?完成到哪了?是做什么的?

// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author :  1320343336@qq.com
// File   : cnn_mnist.v
// Create : 2022-09-15 17:06:16
// Revise : 2022-09-15 17:06:16
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion:  V1.2
// Description: CNN 顶层文件
// -----------------------------------------------------------------------------
// 所有注释部分的代码仅供debug 

输入输出端口声明

能看懂就行

module cnn_mnist(
    input                   sys_clk_p               ,
    input                   sys_clk_n               ,
    input                   rst_n                   ,
    input                   rx_pin                  ,
    //uart module 
    output    wire          tx_pin                  ,
    output    wire          tx_pin_stm32            , 
    //hdmi display module 
    output                  hdmi_clk                ,
    output[23:0]            hdmi_d                  ,
    output                  hdmi_de                 ,
    output                  hdmi_hs                 ,
    output                  hdmi_vs                 ,
    output                  hdmi_nreset             ,
    inout                   hdmi_scl                ,
    inout                   hdmi_sda   
    );

always块

always @(posedge clk_50m or negedge rst_n) begin 
    if(~rst_n) begin
         wr_ram <= 1'b1     ;
    end 
    else if (addra == 'd784)begin
         wr_ram <= 1'b0     ;
    end
    else begin
        wr_ram  <=  wr_ram  ;
    end
end

模块例化

            hdmi_top inst_hdmi_top
        (
            .clk_148mhz  (clk_148mhz        ),
            .clk_100mhz  (clk_100mhz        ),
            .pll_locked  (pll_locked        ),
            .decision    (decision          ),      //4bit
            .rst_n       (rst_n             ),
            .valid_out_6 (valid_out_6       ),

            .clk_ram     (clk_50m           ),
            .wr_ram      (wr_ram            ),
            .wr_addr_ram (addra             ),      //10bit
            .din_ram     (ram_data          ),      //ram_data rom_data//8bit

            .hdmi_clk    (hdmi_clk          ),
            .hdmi_d      (hdmi_d            ),      //24bit
            .hdmi_de     (hdmi_de           ),
            .hdmi_hs     (hdmi_hs           ),
            .hdmi_vs     (hdmi_vs           ),
            .hdmi_nreset (hdmi_nreset       ),
            .hdmi_scl    (hdmi_scl          ),
            .hdmi_sda    (hdmi_sda          )
        );

<think>嗯,用户问的是Python代码中常见的# -*- coding: utf-8 -*-是什么意思。首先,我需要回忆一下自己学过的Python知识。 记得以前刚开始学Python的时候,经常在脚本的开头看到这行注释。可能和编码有关?因为有时候如果代码里有非ASCII字符,比如中文,不加这个的话会报错。比如SyntaxError: Non-ASCII character之类的错误。 那这个注释的具体作用是什么呢?应该是告诉Python解释器这个文件使用的编码格式。Python2的时候,默认的编码是ASCII,所以如果代码中有UTF-8的字符,就需要声明。而Python3默认已经是UTF-8了,可能就不需要再写了。不过有些时候为了兼容或者明确,还是会保留这个声明。 另外,这个格式看起来有点特别,用的是# -*- coding: utf-8 -*-。我记得还有其他的写法,比如# coding: utf-8,或者带等号的。但Emacs和Vim这样的编辑器可能会识别这种格式,用来设置文件的编码方式。所以除了Python解释器之外,编辑器也会用这个信息来正确显示文件内容。 用户可能是在别人的代码里看到这个,想知道它的用途,或者在写自己的代码时遇到了编码问题。需要解释清楚这个声明的作用,适用的Python版本,以及为什么有时候不需要它。还要提到不同写法的情况,以及编辑器的兼容性。 需要注意区分Python2和Python3的不同处理方式。比如在Python3中,默认编码已经是UTF-8,所以这个声明可能不是必须的,但加上也没问题。而Python2中如果不加的话,遇到非ASCII字符就会出错。所以可能需要说明版本差异。 另外,用户可能实际遇到了编码错误的问题,想知道如何解决,所以这个解释可以帮助他们理解如何正确声明文件编码,避免错误。可能还需要提到保存文件时也要确保编码匹配,比如用UTF-8保存,否则声明了也没用。 总结一下,回答的结构应该是先说明这个声明的作用,适用的Python版本,不同版本的区别,其他写法形式,以及编辑器的用途。可能还需要给出示例,比如如果不加的话会出现什么错误,加上之后如何解决。这样用户就能全面理解了。</think>在Python代码中,`# -*- coding: utf-8 -*-` 是一个**文件编码声明**,用于明确告诉Python解释器该源代码文件使用的字符编码格式。以下是详细说明: --- ### 核心作用 1. **解决非ASCII字符问题** 当代码中包含中文、日文、表情符号等**非ASCII字符**时,若未声明编码格式,Python解释器(尤其是Python 2)会抛出类似错误: ```python SyntaxError: Non-ASCII character '\xe4' in file... ``` 2. **统一文件编码** 确保代码文件保存的编码格式(如UTF-8)与声明一致,避免因编辑器默认编码不同导致的乱码或解析错误。 --- ### 版本差异 | Python版本 | 默认编码 | 是否需要显式声明 | |------------|----------------|------------------------------| | Python 2 | ASCII | **必须声明**(若含非ASCII字符)| | Python 3 | UTF-8 | 通常可省略,但显式声明更安全 | --- ### 语法格式 以下写法等效,选择一种即可: ```python # -*- coding: utf-8 -*- # Emacs/Vim风格(推荐,兼容性好) # coding: utf-8 # 简写形式 # coding=utf-8 # 带等号形式 ``` --- ### 注意事项 1. **必须放在文件第一或第二行** (若首行是Shebang指令 `#!/usr/bin/env python3`,则编码声明放第二行) 2. **文件实际编码需与声明一致** 例如:若声明为`utf-8`,需用支持UTF-8的编辑器保存文件(如VS Code、Notepad++)。 --- ### 示例场景 ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- print("你好,世界!") # 包含中文字符 ``` --- ### 延伸知识 - **Python 3的改进**:默认UTF-8编码,但显式声明可提高代码可移植性。 - **编辑器兼容**:部分编辑器(如VSCode)会自动识别此声明来设置编码显示方式。 建议始终保留此声明,以兼容老旧系统和确保跨环境一致性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值