模型功能
- 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;
实现步骤
- module的引用,其直观作用是提供了一个特定输入后可以得到特定输出的黑盒子
- module是新开了一个硬件区域,其逻辑由黑盒子里面的逻辑决定
- 完全独立的区域,使得只需要考虑信号的时序就可以完成应用
- 各种硬件IP核也是采用同样原理进行封装的
- task则是将一段代码移动到其他地方进行运行
- task可以运行在always里面和外面
- 这是其区别于module的地方
- task简单来说就是将一段处理复杂的逻辑打包
- 也就是说,同一个task名字指代的是同一个硬件
- 对于always外的task,不能进行重复调用,否则会形成重复描述
- 对于always内的task,重复的调用可以简化代码
- module的应用场景
- module用于结构分割
- 虽然module也可用于逻辑的划分
- 但是这个显然和代码划分重叠了
- 将module应用于结构划分更加符合其语法定义
- 例子如下
- 在UART通信中,将结构划分为字节发送、字节接收、字符串发送、字符串接收四个结构
- 每个结构都具备独立的信号时序
- 这样就实现了功能的简化
- task的应用场景
- 如其作用,task适合的是代码压缩
- 比如以下模块:
always@(posedge clk)
begin
if(condition_1)
begin
TASK_WR_1;
end
else
if(condition_2)
begin
TASK_WR_2;
end
end
- 上述描述了使用任务将执行逻辑打包到其他的地方
- 以免干扰主干逻辑的阅读,且利用名字使得主干逻辑简明容易修改
- 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]); ...
- 则第一个条件即为高位满足条件
- 基于单硬件的FOR循环的复杂应用
- 前面介绍了在task里面使用for循环实现高位bit寻找的逻辑
- 实际上,for可以合并if条件,自然可以合并所有可以形成递进的if条件
- 即使参数不形成递进关系,使用二维变量也可以形成地址递进,进而实现不同参数的递进实现
- 基于这一点,也就是说,理论上可以将所有的相似的if条件合并,进而实现条件的参数可调
- 这个对于参数化设计具备重要意义,具体的使用方法就是先实现小规模的if,然后再进行参数化
- 好处,则体现在一些算法的优化上
- 如果算法的计算步骤可以进行参数化调整
- 那实现严格匹配时序且最小资源消耗的逻辑则成为可能
- 在配合参数化编译脚本
- 才可以真正发挥FPGA现场可编程的特性
- 以最高的时序和面积完成算法最佳匹配
最终效果
- 略
调用接口
- 略
======== ======\\ ======= -
|| || \\ // \\ /-\
|| || || // // \\
|| || // || // \\
====== ======= || === ========
|| || || \\ // \\
|| || \\ || // \\
|| || \\ // // \\
|| || ======= // \\
作者:绿叶落秋风,专注FPGA技术分析和分享,转载请注明原文链接:https://www.cnblogs.com/electricdream/p/18105947,文中资源链接如下:
1. GITHUB开源仓库