跟着我从零开始入门FPGA之(组合逻辑设计)

来源:本站
导读:目前正在解读《跟着我从零开始入门FPGA之(组合逻辑设计)》的相关信息,《跟着我从零开始入门FPGA之(组合逻辑设计)》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《跟着我从零开始入门FPGA之(组合逻辑设计)》的详细说明。
简介:简述组合逻辑设计

组合逻辑设计

组合逻辑是神马?

所谓组合逻辑就是,一堆输入注定了一个(或多个)输出,明天你再送同样的这一堆输入,可以得到跟今天完全相同的结果。或者说,输出的值跟先前任何状态没有一毛钱的关系,只跟当前的输入有关系。

来个最简单的:

assign out = in1 & in2;

这是个与门,out的值只跟in1和in2有关。

这时候?语句很有作用了,比如

assign out = sel ? in1 : in2;

这是一个二选一的选择器。

你肯定觉得二选一太简单了,来个4选一看看

assign out = (sel==2'b00) ? in0 : (sel==2'b01) ? in1 : (sel==2'b10) ? in2 : (sel==2'b11) ? in3;

不知道你感觉如何,反正我从第二个问号开始花眼,咋办?

首先一个办法,?表达式的复合,我们可以用括号来区分层次,但仍然感觉很不直观。

想到了什么,C语言的switch/case,

OK,我们就用Verilog的case语句写一下

always @(sel or in0 or in1 or in2)

case(sel)

2'b00:out = in0;

2'b01:out = in0;

2'b10:out = in0;

2'b11:out = in0;

endcase

OK,我们看看这个case语句是什么?没错,他就是那个真值表的美丽化身.

怎么,你还想到了卡诺图辅助逻辑表达式化简,当年读书时候,整天对着田字格横看竖看的,很神奇的。

现在我们有Verilog语言了,化简的事情交给综合器好了。

啥,你不知道综合器是啥?C语言的C编译器,你知道吧,他俩基本是一个地位的。

always的小老鼠后面的括号里不是有很多“变量”吗,那叫敏感信号。

只要敏感信号任何一个有变动,下面的语句就执行一次,其实这是个形象的说法,几乎是专门给C语言工程师定制的一个解释。

说到逻辑电路,我们找个非典型的用途吧-----地址译码

CPU就说是8051吧,其实其他的也一样

我们有个外设,内部有8个寄存器,我们打算把它安排到地址0xF080~0xF0087,设计它的片选信号

比较笨的方法:

assign sel = (addr==16'hF080) | (addr==16'hF081) | ...............

我就不敲完了,8个啊,复制完了,还要一个个修改,还要校对,够苦B的了

always @(addr)

case(addr)

16'hF080, 16'hF081, 16'hF082, 16'hF083, 16'hF084, 16'hF085, 16'hF086, 16'hF087:

sel = 1;

default:

sel = 0;

endcase

这个case语句简单多了吧,16'hF080的含义就是此数据有16个bit,h表示后面是十六进制表示的。

F080你要不知道什么意思,估计你们学校是体育老师讲计算机基础课,当然也可能是政治老师。

其实,case里面连续写8个项,然后一个冒号,感觉也很是苦B那我们手工分析下0xF080~0xF0087的特征,高位的3个Nibble是F08,低位Nibble是0~7

我们再用二进制的方式看看:

1111 0000 1000 0000

1111 0000 1000 0001

1111 0000 1000 0010

1111 0000 1000 0011

1111 0000 1000 0100

1111 0000 1000 0101

1111 0000 1000 0110

1111 0000 1000 0111-

--------------------------------------

1111 0000 1000 0xxx

这3个小x的含义我就不说了,这点归纳的逻辑都没有的话,您真不适合做工程师,适合做公务员。

always @(addr)

casex(addr)

16'b1111_0000_1000_0xxx:

sel = 1;

default:

sel = 0;

endcase

是不是帅呆了,如果你不是太粗心的话,应该看到了这个是casex而不是case

其实帅不是目的,泡到妞才是根本。

看一个assign语句就可以搞定的事,何必罗嗦这么多呢。

assign sel = (addr==16'b1111_0000_1000_0xxx);

估计你还看到了一个小东西,那下划线。

没错,他就是个摆设,增加可读性的摆设,去掉也可以,不过我舍不得去掉。

C语言里如果要判断这个sel信号,一般用bit mask的方法

sel = ((addr&0xFFF8)==0xF0808);

看来照猫画虎,这招也可以用在这里,虽然代码稍微差异,思路近似。

关于case语句的一个注意事项,就是所谓的full-case,这个很重要

always @(addr)

casex(addr)

16'b1111_0000_1000_0xxx:

sel = 1;

endcase

那么,当地址不落在我们指定范围内的时候,没有语句来处理。

没来命令,就是要原地驻军。其实相当于,

always @(addr)

casex(addr)

16'b1111_0000_1000_0xxx:

sel = 1;

default:

sel = sel;

endcase

天啊,sel=sel,这就是传说中的意外的latch,这跟我们的意图不一致即使逻辑上可以完成指定功能,他也额外用掉了一个寄存器。

记住,用case语句的时候一定要full-case处理,除非你设计的就是寄存器寄存器的latch是时序逻辑里面的内容欲知后市如何,请听下回分解。

提醒:《跟着我从零开始入门FPGA之(组合逻辑设计)》最后刷新时间 2024-03-14 01:11:13,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《跟着我从零开始入门FPGA之(组合逻辑设计)》该内容的真实性请自行鉴别。