• rtl 开发必会技能


     
    1. 使用|data和data!=0 的区别
      1. |data写法简单,但是漏写| 的可能,测试仿真器会检查data==1'b1
      2. data!=0写法繁琐,但是辨识度高, 推荐使用
    2. 多个分之判断的代码改写(组合逻辑,时序逻辑,function 里面均可以使用)

      如何理解这种设计呢, 类似在if 条件的一个判断分之下,加了一级的mux逻辑。

      建议使用下面这种写法

      1. if(exp_a)begin
      2. if(exp_b) begin
      3. end
      4. else begin
      5. end
      6. end else begin
      7. end
      1. if(exp_a)begin
      2. data_out <= (exp_b)? xxx :xxx;
      3. end else begin
      4. end

      使用下面分片的代码块,起层次关系更加明确;

      防止如下问题的出现:

      条件1 和 条件2 的先后优先级/ 有重叠区域  等问题。

      代码出现问题很难分析

      代码理解困难

      代码看起来比较冗余

      1. if(exp_a && exp_b)begin // 条件1
      2. end
      3. else if(exp_a && (~exp_b))begin//条件2
      4. end
      5. else if(~exp_a)begin // 条件3
      6. end
    3. Function 的使用
    1. function automitic [msb:lsb] function_name;
    2. input [xx:0] port_a;
    3. input [xx:0] port_b;
    4. logic [msb:lsb] temp_data;
    5. logic flag;
    6. begin
    7. temp_data='d0;
    8. flag=1'b0
    9. if(xxx)begin
    10. if(port_a ... port_b )
    11. temp_data = xxx;
    12. end else begin
    13. temp_data=xxx;
    14. end
    15. function_name ={ temp_data,flag };
    16. end
    17. endfunction
      1. 在逻辑中,function 和always@(*)功能差不多,function 实现简单
    1. Mux 是先使用还是后使用
      1. 对于入口数据,先mux后再使用
      2. 对于出口数据,先处理完成一路后与另外一路mux
    2. Generate for的使用
      1. genvar i;
      2. // gen many modules
      3. generate
      4. for(i=0;i<xxx;i=i+1)begin: GEN_XXX_PROC
      5. xxx_module u_xxx_modele(
      6. .port1(xxx[i]),
      7. .port2(xxx[i]),
      8. .port3(xxx[i]),
      9. .port4(xxx[i]),
      10. );
      11. end
      12. endgenerate
      13. // gen many same logic
      14. generate
      15. for(i=0;i<xxx;i=i+1)begin: GEN_XXX_PROC
      16. always@(posedge clk)begin
      17. if(!rst_n)begin
      18. xxx[i] <= 'd0;
      19. end
      20. else begin
      21. if(....)
      22. xxx[i]<=xxx;
      23. else (...)
      24. xxx[i]<=xxx;
      25. end
      26. end
      27. end
      28. endgenerate
    3. Generate if的使用
    1. generate
    2. if( xxx==<constant_expression>))begin:gen_exp0
    3. end else begin:gen_exp_1
    4. end
    5. endgenerate
    1. Generate case的使用
    1. generate
    2. case( xxx==<constant_expression>))begin
    3. exp0:begin end
    4. exp1:begin end
    5. exp2:begin end
    6. default:begin end
    7. end
    8. endgenerate
    Generate if和generate case是针 对paramerter的值 做判断的
    1. Integer 的使用
    1. integer i;
    2. //例化多个always块
    3. for (i=0;i<xxx;i=i+1)begin
    4. always@(*)begin
    5. data[i] =xxx;
    6. end
    7. end
    8. // 一个always 块内嵌入for loop
    9. always@(posedge clk)begin
    10. if(!rst_n)begin
    11. ....
    12. end
    13. else begin
    14. ....
    15. else if(xxx)begin
    16. for(i=0;i<xxx;i=i+1)begin
    17. data[i] <=data[i+1]
    18. end
    19. end
    20. end
    21. end
    1. 状态机的使用
      1. // gen cur_sts logic
      2. always@(posedge clk)begin
      3. if(!rst_n)
      4. cur_sts<=IDLE;
      5. else
      6. cur_sts<=nxt_sts;
      7. end
      8. // gen nxt_sts logic
      9. always@(*)begin
      10. case(cur_sts)
      11. IDLE:begin
      12. if(...)
      13. nxt_sts=xxx;
      14. else
      15. nxt_sts=xxx;
      16. end
      17. ...:begin end
      18. default: nex_sts=IDLE;
      19. endcase
      20. end
      21. //gen main process logic
      22. always@(posedge clk )begin
      23. if(!rst)
      24. out_data<='d0;
      25. else begin
      26. case(cur_sts)
      27. IDLE:begin
      28. if(...)
      29. out_data<=xxx;
      30. else
      31. out_data<=xxx;
      32. end
      33. ....:begin end
      34. default:out_data<='d0;
      35. endcase
      36. end
      37. end
    2. Verilog part_select的使用
    1. data[base_ptr+:length] == data[(base_Ptr+length-1'b1):base_ptr]
    2. data[base_ptr-:length] == data[base_ptr:(base_ptr+1'b1-length)]
    3. //example
    4. //1。 -----------for big_endian-----------
    5. data[0+:8] == data[7:0]
    6. data[7-:8] == data[7:0]
    7. //1。 -----------for little_endian-----------
    8. data[0+:8] == data[0:7]
    9. data[7-:8] == data[0:7]
    1. 字节序的高位对齐和低位对齐,大端(网络字节序)和小端
        大端字节序有利于硬件数据拼接处理,数据接左移后即可继续处理;
        大端字节序符合人类的阅读顺序;
        软件实现简单;
        硬件可以使用function实现字节序的颠倒
      1. function automatic [63:0] bytes_rvs;
      2. input data_in[63:0];
      3. logic [63:0] data_tmp;
      4. integer i;
      5. begin
      6. data_tmp ='d0;
      7. for (inti=0;i<8;i=i+1)begin
      8. data_tmp[(i*8)+:8] <= data_in[((7-i)*8)+:8];
      9. end
      10. bytes_rvs = data_tmp;
      11. end
      12. endfunction
      1. 大端又叫网络字节序,既网络发送的高位数据最终存储在内存低地址位置
      2. 小端是数据发送的高位会存在内存高位地址,低位存在内存低位地址
      3. 一个always 只控制一个信号
            在一个always 内操作2个信号,若2者存在关联关系:例如epp_fin和mer_fin,如果使用if else
            来写,存在epp_fin 拉高后mer_fin需要采集的信号被忽略。mer_fin 会在下一包eop才拉高,造成丢包问题。
             解决方法: 在一个always 内控制多个信号,若2者存在一个时钟同时拉高的可能,先判断是否同时拉高,在分别判断。 或者写2组if else 条件分别处理每一个信号。
  • 相关阅读:
    SpringBoot + Apache tika 轻松实现各种文档内容解析
    面试了个 985 毕业的同学,回答“性能调优”题时表情令我毕生难忘
    遇到了2个有相同的JavaBean类
    【真送礼物】1 分钟 Serverless 极速部署盲盒平台,自己部署自己抽!
    Linux常用指令(十)——服务器相关与互传文件
    python(牛客)试题解析1 - 简单
    小程序中的权限设计
    nRF5340(入门篇)之1.1 nrf5340芯片简介
    视频剪辑完成,应该如何给视频配音?三种配音方法快来学
    oppo手机便签隐藏了一条怎样打开?手机如何找到隐藏便签?
  • 原文地址:https://blog.csdn.net/Ruanyz_china/article/details/133844167