写Verilog通用模块的一些代码----持续更新

  在编写代码为了能够方便移植或者说为了一劳永逸,往往会考虑把模块代码写得更加的通用。比如可以进行传参配置,这里主要是通过位宽传参。笔者写过不少的代码,觉得写通用模块代码需要思考挺长的时间去处理数据赋值之类的,需要总结出公式才能使代码通用,为了方便查找,这里就总结下笔者常用到的一些写法,大部分的通用代码都使用了for循环进行遍历。

  1.位宽计数

  在节省资源的情况下会使用,能够精准计算出当前计数器需要的位宽,或者FIFO的位宽。不过这也只能对parameter或者localparam参数进行计算,否则vivado貌似会编译不过。这里把功能封装成一个函数,纯组合逻辑实现。功能就是计算当前数值需要的位宽,就是log2。假设要算DATA_WIDTH= 10;则log2(DATA_WIDTH)结果就为4。

1     function integer log2;
2         input    [WIDTH-1:0]    i_data;
3         begin
4             for(log2 = 0; i_data >0; log2 = log2 + 1)
5             begin
6                 i_data = i_data >> 1;
7             end
8         end
9     endfunction

  2.通用的译码器编码器

  正常译码解码器会使用case,这样就能够遍历所有情况。不过case没办法对通用的情况进行赋值。

  2.1编码:

1 integer        i;
2 always@(*)
3 begin
4     for(i = 0; i <= WIDTH - 1; i = i + 1)//WIDTH是i_din位宽
5     begin
6         if(i_din[i])
7             o_encode = i;                 //o_encode位宽是log2(WIDTH)
8     end
9 end

  例如3-8译码以下是网上其他博主写的代码截图,笔者的编码器把对应的位宽传进去,再把判断条件改成if(i_din[i] == 0)即可。

   2.2 解码:

 1 integer        j;
 2 always@(*)
 3 begin
 4     o_decode = 'd0;
 5     for(j = 0; j <= WIDTH - 1; j = j + 1)//WIDTH是i_din位宽
 6     begin
 7         if(i_din == j)
 8             o_decode[j] = 1'b1;             //o_decode位宽是2^(WIDTH-1)
 9     end
10 end

  例如3-8译码以下是网上其他博主写的代码截图

posted on 2023-08-20 18:18  Galois_V  阅读(103)  评论(0编辑  收藏  举报