zoukankan      html  css  js  c++  java
  • Verilog代码设计之 “神精匠工” ------ 转载

    本文转自微信公众号:Silicon_Peasant,原文链接:https://mp.weixin.qq.com/s/e3kp7EcsoOxifyFGHctb4A

    “神精匠工”

    注意,这是从右到左读的。

    工匠精神,做工程的就应该有工匠精神,或者说叫偏执,或者说叫强迫症,文化人说法,这叫讲究。这些首先在你的代码风格上体现。

    对齐

    tab键还是空格键?留言区说出你的故事。我把编辑器设置成tab自动替换成4个空格。

    用空格对齐代码,提高代码观赏性。

    assign signal_b = signal_a;assign data_b = data_a;assign cs_en = 1'b1;
    assign signal_b = signal_a;assign data_b = data_a;assign cs_en = 1'b1;

    第二种写法更美观,always块里面的语句也应该对齐。

    命名

    给模块起名字,给信号起名字,真的很难,但是不管怎样都不要用拼音,会遭人鄙视。

    阶梯式assign

    assign data_out[5:0] = data_vld0 ? data0[5:0] :    data_vld1 ? data1[5:0] :     data_vld2 ? data2[5:0] :     data_vld3 ? data3[5:0] : 6'b0;

    由于if-else和case不能传播不定态,有的EDA工具有X态传播选项,可以强行传播,但是并不是所有的EDA工具都有这个功能,所以有些书上建议都用组合逻辑用assign。

    这种写法没什么问题,但是有一点,覆盖率不好收,如果一些情况没跑到需要一个个分析。覆盖率会把数据信号当作一个情况列出来,比如数据信号data没出现过0 的情况,实际上数据信号没出现0的情况是正常的,这就要你一个一个的exclude掉。

    所以不要写很长的assign做选择器,有优先级用if-else,或根据具体情况用case。这样哪一行哪一种情况没跑到会一目了然。当然if中的条件太多,覆盖率也不好收,条件太多组合的情况多,分析起来繁琐。如果上述信号的vld不同时出现也可以采用这种写法,减少cell的使用数量。这样也是有覆盖率的问题,这只是一种特殊情况,很长的assign选择器尽量不要写。

    assign data_out[5:0] = ({6{data_vld0}} & data0[5:0])    | ({6{data_vld1}} & data1[5:0])    | ({6{data_vld2}} & data2[5:0])    | ({6{data_vld0}} & data3[5:0]);

    关于X态传播,一定要注意,带有reset的寄存器面积和时序会稍微差一些,控制通路的寄存器必须带有复位,数据通路的寄存器可以不带复位,但是要注意使用时如果使用数据通路的数据去做了控制条件,就必须要复位,否则如果X态没有查出来,事情就大了。

    布线太密的原因

    寄存器位宽太大。

    reg [10000-1:0] data;

    这样写在功能上没什么问题,但是如果你之后有对这个数据做了很多逻辑,可能会造成后端布线太密,从后端的角度看到其实cell数量并不多,就是线比较密,比如说这个数据后面再放个选择器,或者输出给其他模块,就相当于一万根线连到很多地方,布线很紧张,如果时序有问题需要绕线,或者需要ECO,做成的可能性很小。

    尽量不要这样做逻辑,除非对面积没限制,要么最后只能改架构。

    第二个原因是负载太大。同一个信号在很多地方使用,布线也会变复杂,比如最常见的是参数信号,在很多模块都会有用到的情况,用寄存器复制的方法。

    always @(posedge clk or negedge rst_n)begin    if(!rst_n)begin        data_para0 <= 4'b0;        data_para1 <= 4'b0;        data_para2 <= 4'b0;    end    else begin        data_para0 <= data_para;        data_para1 <= data_para;        data_para2 <= data_para;                endend

    画俩图大概意思一下。这样每个寄存器的驱动变少。

    加比选

    面积:加法器 > 比较器 > 选择器

    乘法器本质上也是全加器。

    所以就有先选后比,先选后加,先选后乘。

    assign sum[4:0] = enable ? (data_a + data_b) : (data_c + data_d);
    assign add_a[3:0] = enable ? data_a : data_c;assign add_b[3:0] = enable ? data_b : data_d;assign sum[4:0] = add_a + add_b;
    画个图意思一下。

    数据通路与控制通路

    数据通路打拍可以不带复位,带着使能信号去打拍,减少信号翻转,减少功耗。保证数据用的时候不是X态,

    组合逻辑路径是否需要插入pipeline,插入pipeline的位置需要注意。寄存器能少用就少用。

    尽量不要用除法,首先除法器面积更大,除法也会有余数,余数是否需要保留就很麻烦。除以常数可以做成乘以定点常数的方法。

    乘以常数用移位加,也可直接用*号。例如a * 2‘d3,工具会帮你优化成 a << 2’d1 + a。甚至可能优化得更好。(杠:不要过度依赖工具)。关于用移位加还是*号的问题,博主做过综合后的面积对比,相对来说,工具还是优化那么一点点。直接用 * 号吧。

    尽量不要用减法,减法要考虑到减翻的问题,尽量用加法。

    方案设计

    方案最重要,一个好的方案往往事半功倍。

    状态机设计要状态明确,一个状态尽量只做一件事情。状态机大法好。

    做成IP化设计,功能分割尽量独立并可复用性,相同的功能用同一块IP,保证IP的没问题,最后像搭积木一样,搭建起数字系统。多积累些常用IP,常用的一些写法的代码。

  • 相关阅读:
    【题解】Codeforces Round #600(Div.2)
    【题解】CF 1073 G. Another LCP
    【题解】CF 1129C. Morse Code
    【题解】CF 1200E. Compress Words
    Cpp Chapter 8: Adventures in Functions Part4
    Cpp Chapter 8: Adventures in Functions Part3
    Python Chapter 9: 使用Tkinter进行GUI程序设计 Exercise
    Python Chapter 9: 使用Tkinter进行GUI程序设计 Part 4
    Python Chapter 9: 使用Tkinter进行GUI程序设计 Part 3
    Python Chapter 9: 使用Tkinter进行GUI程序设计 Part 2
  • 原文地址:https://www.cnblogs.com/hxing/p/12535211.html
Copyright © 2011-2022 走看看