当前位置:网站首页>【数字IC手撕代码】Verilog固定优先级仲裁器|题目|原理|设计|仿真
【数字IC手撕代码】Verilog固定优先级仲裁器|题目|原理|设计|仿真
2022-08-02 04:11:00 【myhhhhhhhh】
芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 |
---|
四社区联合力荐!近500篇数字IC精品文章收录! |
【数字IC精品文章收录】学习路线·基础知识·总线·脚本语言·芯片求职·EDA工具·低功耗设计Verilog·STA·设计·验证·FPGA·架构·AMBA·书籍 |
Verilog固定优先级仲裁器
一、前言
本系列旨在提供100%准确的数字IC设计/验证手撕代码环节的题目,原理,RTL设计,Testbench和参考仿真波形,每篇文章的内容都经过仿真核对。快速导航链接如下:
1.奇数分频
2.偶数分频
3.半整数分批
4.小数/分数分频
5.序列检测器
6.模三检测器
7.饮料机
8.异步复位,同步释放
9.边沿检测(上升沿,下降沿,双边沿)
10.全加器,半加器
11.格雷码转二进制
12.单bit跨时钟域(打两拍,边沿同步,脉冲同步)
13.奇偶校验
14.伪随机数生成器[线性反馈移位寄存器]
15.同步FIFO
16.无毛刺时钟切换电路
17.固定优先级仲裁器
18.轮询仲裁器
应当说,手撕代码环节是面试流程中既重要又简单的一个环节,跟软件类的岗位相比起来,数字IC的手撕代码题目固定,数量有限,属于整个面试中必得分的一个环节,在这个系列以外,笔者同样推荐数字IC求职者使用“HdlBits”进行代码的训练
链接如下
HDLBits — Verilog Practice
二、题目
数字IC工程师在使用多主设备的总线过程中,需要考虑到不同主设备申请总线控制权的优先级问题,请使用Verilog语言,考虑四个主设备,设计固定优先级仲裁器,该仲裁器默认时的总线控制的优先级永远保持为为A>B>C>D。
三、原理
默认情况下的优先级排序为A>B>C>D,input 请求情况request 的四位二进制,从高到低也分别代表主设备A、B、C、D的总线控制请求,output的grant输出one hot编码,即“1000,0100,0010,0001”四种情况中的一种,给出的案例如下,按照四个周期依次输入控制请求,仲裁器在按照固定优先级算法的条件下会依次响应设备A,D,A,B
周期 | 请求情况(request) | 优先级排序 | 响应情况(grant) |
---|---|---|---|
1 | 1010 | ABCD | 1000(A) |
2 | 0001 | ABCD | 0001(D) |
3 | 1111 | ABCD | 1000(A) |
4 | 0011 | ABCD | 0010(B) |
需要注意的是,虽然我们在上面的例子中提出周期的概念,但对于仲裁器来讲,它是一个纯组合逻辑电路。
3.1 case/if语句法
我们有很多种方法来实现固定优先级仲裁器,第一种介绍的方法为if/case法:
说起来其实非常简单,使用if语句先判断request的最高位,假如为1,输出1000,假如不为1,再判断request的次高位是否唯一,去输出0100,以此类推进行设计即可。
需要注意的是,上述的语句除了可以使用if来完成外,也可以使用case来完成。初学者常常用if语句是串行的,有判断优先级,而case语句是并行的,没有判断优先级的角度去理解verilog语言对于if语句和case语句的综合过程,在这个思路下,if语句对应综合出来的逻辑具有优先级,靠前的逻辑少,路径短,靠后的逻辑多,路径长,而case语句的综合是一个parallel的结构,这个说法对于if语句是正确的,而对于case语句来说对也不对
一个正确的说法是,case语句,即可以实现parallel结构,也可以实现优先级编码。
具体内容可参见case语句的综合结果,你究竟会了吗?
因此,我们可以使用case语句代替if语句去判断固定优先级的仲裁器应该输出什么grant值,RTL代码参见下文即可。
3.2 for循环法
除此以外,for语句也可以用来设计固定优先级仲裁器,对于固定主设备数量的固定优先级仲裁器而言,固定循环次数的for语句,可以综合成实际电路,这个原则是我们为什么可以使用for语句进行固定优先级仲裁器的基础,但是受限于篇幅有限,我们不给出具体的for循环rtl代码了。
3.3 补码相与法
这是一个很巧妙的方法,而我们使用到了2进制的补码的一个特性,即一个数和它的补码相与,得到的结果是一个独热码,独热码为1的那一位是这个数最低的1,这个特性和我们想要寻找,四位二进制的1,在什么时候第一次出现的想法,不谋而合。
需要注意的是,我们这里把现在给出的request当作补码,去求它的原码,再相与,以下会给处详细解释:
我们可以这么去思考这个问题,一个二进制4bit的数,减去1,会向这个数第一个非零的位置借位,改变这一位的值,假如与减1后的数进行与操作,那么只有产生进位的这一位在取反后依旧为1,二者相与,得到一个独热码
举例:(注意这里的request是[0:3]而非[3:0])
request[0:3] | request原码 | 相与 | 出现1的位数 |
---|---|---|---|
1001 | 0001 | 0001 | 第零位 |
0100 | 1100 | 0100 | 第二位 |
0111 | 1001 | 0001 | 第零位 |
0001 | 1111 | 0001 | 第零位 |
0000(这里要在前面做一个1的位扩展) | 1111 | 0000 | 无 |
四、RTL设计
4.1 case语句法固定优先级仲裁器
module fixed_arb(request,grant);
input [3:0] request;
output [3:0] grant;
reg [3:0] grant_reg;
[email protected](*)
case(1'b1)
request[3] : grant_reg = 4'b1000;
request[2] : grant_reg = 4'b0100;
request[1] : grant_reg = 4'b0010;
request[0] : grant_reg = 4'b0001;
default: grant_reg = 4'b0000;
endcase
assign grant = grant_reg;
endmodule
根据原理可知,这种写法的case语句实际上是一个串行结构,以上的内容当然也可以使用if嵌套的形式进行替代,if先判断最高位,依次判断至第零位,default条件下,grant输出4‘b0000,这里就不再赘述了
4.2 加法器法固定优先级仲裁器
我们之所以在下文的rtl设计中去颠倒grant的高低位,是跟A>B>C>D还是A<B<C<D相关,其中{A,B,C,D}分别代表grant[3:0]从高到低的四位,若为A<B<C<D的优先级,则其实不需要高低位颠倒,而对于前者来说则需要,这里请读者注意,为了考虑4’b0000的情况,我们还做了一个位扩展,当然,assign的等式左边与等式右边位宽不相等,lint肯定会有error,但我们这里忽略,并按照舍弃高位,保留低位的方式来进行默认操作。
module fixed_arb_2(request,grant);
input [3:0] request;
output [3:0] grant;
assign {
grant[0],grant[1],grant[2],grant[3]}=
{
1'b1,request[0],request[1],request[2],request[3]} &
~({
1'b1,request[0],request[1],request[2],request[3]}-1'b1);
endmodule
五、仿真
5.1 case法仿真文件
`timescale 1ns / 1ps
module fixed_arb_tb();
reg [3:0] request;
wire [3:0] grant;
fixed_arb u1(request,grant);
always #5 request = $random;
initial
begin
request = 4'b0000;
#200;
$stop;
end
endmodule
5.2 补码相与法仿真文件
`timescale 1ns / 1ps
module fixed_arb_tb_2();
reg [3:0] request;
wire [3:0] grant;
fixed_arb_2 u1(request,grant);
always #5 request = $random;
initial
begin
request = 4'b0000;
#200;
$stop;
end
endmodule
六、仿真结果分析
6.1 case法结果分析
可以发现,第一个输出1的request对应的位置,为grant信号输出唯一的1的位置,设计成立。
6.2 补码相与法结果分析
效果与6.1一样,即从左到右判断第一个出现1的位置,grant输出对应位置的信号。
边栏推荐
- 安装部署 Kubernetes 仪表板(Dashboard)
- Pycharm平台导入scikit-learn
- 张成分析(spanning test):portfolio_analysis.Spanning_test
- 2022-08-01:以下go语言代码输出什么?A:panic;B:5;C:6;D:编译错误。 package main import ( “fmt“ ) func main() {
- 科研笔记(六) 基于环境感知的室内路径规划方法
- 使用GD32F207的高级定时器来产生PWM波出现的隐藏BUG
- Deep Blue Academy-Visual SLAM Lecture 14-Chapter 6 Homework
- HyperLynx中层叠设计实例
- UI自动化测试框架搭建——标记性能较差用例
- 吴恩达机器学习系列课程笔记——第九章:神经网络的学习(Neural Networks: Learning)
猜你喜欢
随机推荐
如何评价最近爆红的FastAPI?
lvm扩容(实战无废话)
自定义一个下划线分词器
UI自动化测试框架搭建——标记性能较差用例
吴恩达机器学习系列课程笔记——第十六章:推荐系统(Recommender Systems)
数据复制系统设计(3)-配置新的从节点及故障切换
gergovia的交易tijie
详解CAN总线:什么是CAN总线?
吴恩达机器学习系列课程笔记——第七章:正则化(Regularization)
falco 【1】入门
科研笔记(五) SLAC WiFi Fingerprint+ Step counter融合定位
【C语言程序】求直角三角形边长
Deep Blue Academy - Visual SLAM Lecture Fourteen - Chapter 5 Homework
使用 Fastai 构建食物图像分类器
Deep blue college - handwritten VIO operations - the first chapter
Andrew Ng's Machine Learning Series Course Notes - Chapter 18: Application Example: Image Text Recognition (Application Example: Photo OCR)
最后写入胜利(丢弃并发写入)
MapFi paper structure organization
C语言:结构体总结
STM32 OLED显示屏