rtl 开发必会技能

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

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

    建议使用下面这种写法

    if(exp_a)begin
    
        if(exp_b) begin
    
        end  
        else begin 
    
        end
    
    end  else begin
    
    end
    
    if(exp_a)begin
    
        data_out <= (exp_b)? xxx :xxx;
     
    end  else begin
    
    end
    

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

    防止如下问题的出现:

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

    代码出现问题很难分析

    代码理解困难

    代码看起来比较冗余

    if(exp_a && exp_b)begin // 条件1
    
    
    end
    else if(exp_a  && (~exp_b))begin//条件2 
    
    
    end
    else if(~exp_a)begin // 条件3
    
    
    end
  3. Function 的使用
function automitic [msb:lsb] function_name;
    input [xx:0]  port_a;
    input [xx:0]  port_b;
    logic [msb:lsb] temp_data;
    logic flag;
begin
    temp_data='d0;
    flag=1'b0
    if(xxx)begin
         if(port_a ... port_b )
            temp_data = xxx;
    end else begin
            temp_data=xxx;
    end 
    function_name ={ temp_data,flag };
end 
endfunction
    1. 在逻辑中,function 和always@(*)功能差不多,function 实现简单
  1. Mux 是先使用还是后使用
    1. 对于入口数据,先mux后再使用
    2. 对于出口数据,先处理完成一路后与另外一路mux
  2. Generate for的使用
    genvar i; 
    // gen many modules
    generate 
    for(i=0;i<xxx;i=i+1)begin: GEN_XXX_PROC
        xxx_module u_xxx_modele(
         .port1(xxx[i]),
         .port2(xxx[i]),
         .port3(xxx[i]),
         .port4(xxx[i]),
        );
    end
    endgenerate
    // gen many same logic
    generate 
    for(i=0;i<xxx;i=i+1)begin: GEN_XXX_PROC
        always@(posedge clk)begin
            if(!rst_n)begin
               xxx[i] <= 'd0;     
            end 
            else begin 
             if(....)
             xxx[i]<=xxx;
             else (...)
             xxx[i]<=xxx;
            end
        end 
    end
    endgenerate
  3. Generate if的使用
generate 
if( xxx==<constant_expression>))begin:gen_exp0


end else begin:gen_exp_1


end
endgenerate
  1. Generate case的使用
generate 
case( xxx==<constant_expression>))begin
    exp0:begin end
    exp1:begin end
    exp2:begin end
    default:begin end
end
endgenerate
Generate if和generate case是针 对paramerter的值 做判断的
  1. Integer 的使用
integer i;
//例化多个always块
for (i=0;i<xxx;i=i+1)begin
    always@(*)begin
        data[i] =xxx;
    end
end

// 一个always 块内嵌入for loop
always@(posedge clk)begin
    if(!rst_n)begin
        ....
    end
    else begin
        ....
        else if(xxx)begin
            for(i=0;i<xxx;i=i+1)begin
                data[i] <=data[i+1]
            end 
        end
    end
end
  1. 状态机的使用
    // gen cur_sts logic
    always@(posedge clk)begin
        if(!rst_n)
            cur_sts<=IDLE;
         else 
             cur_sts<=nxt_sts;
    end
    // gen nxt_sts logic
    always@(*)begin
        case(cur_sts)    
        IDLE:begin
            if(...)
                nxt_sts=xxx;
            else 
                nxt_sts=xxx;
        end 
        ...:begin  end    
        default: nex_sts=IDLE;
        endcase
    end
       
     //gen main process logic 
     always@(posedge clk )begin 
         if(!rst)
             out_data<='d0;
         else begin
            case(cur_sts)
             IDLE:begin  
                 if(...)
                 out_data<=xxx;
                 else 
                 out_data<=xxx;
              end
             ....:begin   end 
             default:out_data<='d0;
            endcase
         end
     end   
  2. Verilog part_select的使用
data[base_ptr+:length]  == data[(base_Ptr+length-1'b1):base_ptr]
data[base_ptr-:length]  ==  data[base_ptr:(base_ptr+1'b1-length)]
 //example
 //1。 -----------for  big_endian-----------
 data[0+:8]  == data[7:0]
 data[7-:8]  == data[7:0]
  //1。 -----------for  little_endian-----------
  data[0+:8]  == data[0:7]
  data[7-:8]  == data[0:7] 
  1. 字节序的高位对齐和低位对齐,大端(网络字节序)和小端
      大端字节序有利于硬件数据拼接处理,数据接左移后即可继续处理;
      大端字节序符合人类的阅读顺序;
      软件实现简单;
      硬件可以使用function实现字节序的颠倒
    function automatic [63:0] bytes_rvs;
    input data_in[63:0];
    logic  [63:0] data_tmp;
    integer i; 
    begin
    data_tmp ='d0;
    for (inti=0;i<8;i=i+1)begin
        data_tmp[(i*8)+:8] <= data_in[((7-i)*8)+:8];
    end
    bytes_rvs = data_tmp;
    end
    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 条件分别处理每一个信号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值