module和task的引用

Posted on 2024-03-30 20:54  绿叶落秋风  阅读(35)  评论(0编辑  收藏  举报

模型功能

  • module的引用保证了模块可以进行层次划分,从而形成分级处理逻辑
  • task的作用是提取某一部分的逻辑,用于简化模块的过程描述
  • 两者都是实现了逻辑压缩,用于增加代码的可读性

模型框图

//module A design
module A(

);

endmodule
//module A use
A u_A(
  .clk(clk)
);
//task B design
task B(
  input r_a
);
endtask
//task use
B;

实现步骤

  1. module的引用,其直观作用是提供了一个特定输入后可以得到特定输出的黑盒子
  • module是新开了一个硬件区域,其逻辑由黑盒子里面的逻辑决定
  • 完全独立的区域,使得只需要考虑信号的时序就可以完成应用
  • 各种硬件IP核也是采用同样原理进行封装的
  1. task则是将一段代码移动到其他地方进行运行
  • task可以运行在always里面和外面
    • 这是其区别于module的地方
  • task简单来说就是将一段处理复杂的逻辑打包
  • 也就是说,同一个task名字指代的是同一个硬件
    • 对于always外的task,不能进行重复调用,否则会形成重复描述
    • 对于always内的task,重复的调用可以简化代码
  1. module的应用场景
  • module用于结构分割
    • 虽然module也可用于逻辑的划分
    • 但是这个显然和代码划分重叠了
    • 将module应用于结构划分更加符合其语法定义
  • 例子如下
    • 在UART通信中,将结构划分为字节发送、字节接收、字符串发送、字符串接收四个结构
    • 每个结构都具备独立的信号时序
    • 这样就实现了功能的简化
  1. task的应用场景
  • 如其作用,task适合的是代码压缩
  • 比如以下模块:
always@(posedge clk)
begin
  if(condition_1)
  begin
    TASK_WR_1;
  end
  else 
  if(condition_2)
  begin
    TASK_WR_2;
  end 
end 
  • 上述描述了使用任务将执行逻辑打包到其他的地方
  • 以免干扰主干逻辑的阅读,且利用名字使得主干逻辑简明容易修改
  1. task的复杂应用
  • task支持for循环(实际上是always支持for循环,task在always内部时继承了这种特性)
    • 这个就意味着可以实现单个硬件的for循环描述
    • 也就是可以将大量类似的if条件合并到for循环中,实现可配个数的if条件执行
  • 假设一个问题:寻找位宽为N的信号S的最高位所处的位数D,如8'h10输出4,8'h21输出5
    • 方法1:使用casex实现列举,可以实现一个有限N的位数寻找
    • 方法2:使用always内部的for实现单硬件的IF描述
//way 1
always@(posegde clk)
begin
  casex(S)
    'b1: D = 0;
    'b1x: D = 1;
    'b1xx: D = 2;
    'b1xxx: D = 3;
  endcase
end 
//way2
integer i;
always@(posedge clk)
begin
  TASK_SCAN_HIGH_BIT();
end 
task TASK_SCAN_HIGH_BIT();
  for(i = 0; i < N; i = i + 1)
  begin:FOR_N
    if(S[N])
      begin
          D = i;
      end 
  end 

endtask

  • 第二种方法看似没有简化代码,实则更加符合描述的需求
    • 第一种方法只是利用穷举实现了有限N的描述
    • 而第二种则是实现了数学等价,只要时序满足,则N可以为任意值
  • 至于这里为啥需要放在task里面
    • 显然这种形式的代码可能形成很复杂的逻辑,放在task可以避免由于条件变更导致代码冗杂
  • 第二种方法的理解
    • if(S[N])可以展开为:if(S[0]); if(S[1]); ...
    • 根据if后面优先级高于前面,则合并为if else则为: if(S[N-1]) ; else if(S[N-2]); ...
    • 则第一个条件即为高位满足条件
  1. 基于单硬件的FOR循环的复杂应用
  • 前面介绍了在task里面使用for循环实现高位bit寻找的逻辑
  • 实际上,for可以合并if条件,自然可以合并所有可以形成递进的if条件
    • 即使参数不形成递进关系,使用二维变量也可以形成地址递进,进而实现不同参数的递进实现
  • 基于这一点,也就是说,理论上可以将所有的相似的if条件合并,进而实现条件的参数可调
  • 这个对于参数化设计具备重要意义,具体的使用方法就是先实现小规模的if,然后再进行参数化
  • 好处,则体现在一些算法的优化上
    • 如果算法的计算步骤可以进行参数化调整
    • 那实现严格匹配时序且最小资源消耗的逻辑则成为可能
  • 在配合参数化编译脚本
    • 才可以真正发挥FPGA现场可编程的特性
    • 以最高的时序和面积完成算法最佳匹配

最终效果

调用接口