您的位置 首页 测评

Verilog言语:还真的是人格分裂的言语

人有双重人格,或者叫人格分裂,那么语言呢?Verilog语言还真的是人格分裂的语言。前回书已经说到了,不能简单地把wire类型映射为组合逻辑,同时把reg类型映射为时序逻辑。事实上,这两个概念会交叉的

“人气腹语术师天愿在现场披露了被人偶伙伴攫取魂灵的腹语术师将妻子杀戮的扮演节目。天愿真的陷入了多重品格,指令自己杀戮妻子和子的人偶的品格呈现了。为了不(让自己)杀戮和弟子登川有外遇的妻子,天愿提出托付想要监督,可是第二天早上,和子真的被杀戮的作业发生了。天愿率直很或许是在自己的认识失掉的时分杀戮的……”(—-“本相只需一个”《名侦察柯南》一向是老衲喜爱的动画片)这个是第806回《腹语師的幻觉》的介绍。

人有双重品格,或许叫品格分裂,那么言语呢?Verilog言语还真的是品格分裂的言语。前回书现已说到了,不能简略地把wire类型映射为组合逻辑,一起把reg类型映射为时序逻辑。事实上,这两个概念会穿插的。也便是说,wire类型极或许被归纳为组合逻辑也或许归纳为时序逻辑,reg类型也是这样。

“‘reg’是什么?”最微软的答复是:注册表文件。这个天然没错,可是违反了“到哪座山,唱哪里歌”的准则。一般的“规范”答案是:寄存器型变量。看看‘reg’,不便是‘register’(寄存器)的缩写吗?大多数中文教材中都是这样说的。

下面为了说了解这桩作业,请答应老僧引证IEEE有关Verilog言语里边的原文:
“Assignments to a reg are made by procedural assignments (see 6.2 and 9.2). Since the reg holds a value between assignments, it can be used to model hardware registers. Edge-sensitive (i.e., flip-flops) and level sensitive (i.e., RS and transparent latches) storage elements can be modeled. A reg need not represent a hardware storage element since it can also be used to represent combinatorial logic.”

为了着重,表1里边给出了wire、reg类型和组合逻辑、时序逻辑之间的映射联系。

表1 wire、reg类型和组合逻辑、时序逻辑之间的映射联系

wire

reg

组合逻辑

时序逻辑

可见reg是“双面特务”的作业性质,为了能够“得心应手”,天然用法要比wire来的杂乱。类型wire被归纳为时序逻辑一般还真是写错了,不用细表。

1. 电平触发,组合完结
和reg“孟不离焦,焦不离孟”的是要害词always,这个要记清楚。人家wire和assign是夫妻,reg和always是一对,千万不要搞混了,这不是能拉郎配的时节。

“always”的语法结构是:
always @(sensitive_tabel)

其间,sensitive_tabel称作灵敏列表,其间包括always内部操作的一个或许多个触发条件。字符“@”发音是“艾特”(at),大伙儿发电子邮件(e-mail)的时分常用,不罗嗦。

正如上面说到的、规范立面的说法可所以边缘灵敏和电平灵敏两种。关于组合逻辑电路,这个灵敏列表里边一切条件均为电平灵敏。逻辑上,当灵敏列表里边的条件契合的时分,always内部的操作能够进行。可是,许多逻辑上可行的代码,由于没有实践电路的支撑,是无法完结的。

在Verilog言语95版别里边,电平触发的灵敏列表的写法是
triger1 or triger2 or triger3……

其间,triger1等为触发信号。当触发信号电平改变时,阐明灵敏列表里边条件契合。假如触发信号是向量,则其间一个比特的信号改变,就以为信号电平有改变。到了Verilog 2001版别,这个写法被愈加简化了:“,”和“or”都能够用来切割灵敏作业;而且,能够用“*”代表一切输入信号,这能够避免遗失。例1给出了一些契合语法的always的比如。

【例1】always与灵敏列表
always @ (triger1 or triger2 or triger3) //Version 95 and Version 2001
always @ (triger1 , triger2 , triger3) //Version 2001
always @ (*) //Version 2001
具有彻底电平灵敏列表的always模块,总叫人觉得便是组合逻辑了。再次着重数字电路是并行作业的,留意不要用“履行”这个词,不精确。对应的一切assign以及always带领的快都是并行的,其在代码中前后次序与输出成果无关。也便是说例2里边的两段代码是等效的。代码中,灵敏列表sensitive_table1和sensitive_table2对应操作Operation_A和操作Operation_B。
【例2】always所带操作次序与输出成果无关

always @(sensitive_table1)

Operation_A

always @( sensitive_table2)

Operation_B

always @( sensitive_table2)

Operation_B

always @(sensitive_table1)

Operation_A

理论上,assign后边只需一行,关于这个并行作业的了解不难,不会发生误解。到了always这儿,一般这今后的代码就有许多行了,一不留意就会犯错。

2. 条件判别,分枝多多
“用C言语的规范点评Verilog,好像用生果的规范点评蜜饯。”,可是他们确实许多写法有相似,这是很简单误导学习者的当地。

前文书关于“? :”挑选操作哪里介绍过,挑选与分枝在一般体系中是不行少的。那里介绍的代码办法,显然会发生阅览困难—-尤其是在条件比较多的时分。为了改进这一问题,也一起能够愈加契合我们曾经的习气,这一讲书老朽给贵客介绍“if”和“case”这两位我们了解的陌生人。

先看眼里的代码,条件句子if的办法有如表2中的三种。其间,condition等表明挑选的条件,operation等表明对应的操作。请留意,这儿的表达式“挑选”,意图是和电路对应,不是故意和他人不一样的哗众取宠。

表2条件句子if的格局

无分枝

单级分枝

多级分枝

办法

if (condition )

begin

operations

end

if (condition )

begin

operations_1

end

else

begin

operations_2

end

if (condition_1 )

begin

operations_1

end

else if (condition_2 )

begin

operations_2

end

else if……

……

begin

operations_m

end

对应电路

时序电路

时序电路

组合电路

时序电路

组合电路

表.2中“对应电路”一行也请施主们留意,if句子中条件的一切途径掩盖不全面,或许会发生时序电路的。关于reg类型的变量,需求满意“条件不满意的时分,坚持原值”;一起,组合电路不行“自赋值”(也便是相似“a = a”的办法)。当需求“坚持”的时分,纯组合电路是无法满意的。所以,归纳器会引进“锁存器”。不是归纳器自作主张,这是代码的要求。“天作孽犹可恕,自作孽不行活”,只能怪你自己了,哭吧!这个对应的器材是锁存器,不是这儿的要点,会在今后介绍。这儿要说的是:要发生组合逻辑,if的条件途径有必要全掩盖。

if句子中条件的一切途径掩盖不全面,或许会发生时序电路的。这个对应的器材是锁存器,不是这儿的要点,今后介绍。这儿要说的是:要发生组合逻辑,if的条件途径有必要全掩盖。

例3是一个单级条件句子if使用的比如,其功用是求有符号数绝对值。其间,输入为8比特有符号数,编码办法为补码;输出是输入数值的绝对值。具体算法是:

【例3】绝对值运算模块
module abs
(
input[7:0] signed_value,
output reg[6:0] result
);

//Definition for Variables in the module

//Load other module(s)

//Logical
always @(signed_value)
begin
if ( signed_value[7])
//Negative number input
begin
result = (~signed_value[6:0]) + 7h01;
end
else
//Positive number or zero input
begin
result = signed_value[6:0];
end
end

endmodule

3. 多种状况,并排判定
在条件许多的时分,用if句子来写仍是很费事的,搞不好便是是一个条件途径掩盖不彻底。这个时分,能够挑选case套餐。case句子是一种多分支挑选句子, Verilog言语供给的case句子直接处理多分支挑选。多分支的case有三种办法,如表3所示。

表3条件句子case的办法

case

casex

casez

比较办法

灵敏表达式与各项值之间的比较,是一种全等比较

假如分支表达式某些位的值为高阻z,那么对这些位的比较就会疏忽,不予考虑,而只重视其他位的比较成果。

casez会把z/?匹配成恣意,也会把恣意匹配成z/?

在casex句子中,则把这种处理办法进一步扩展到对x的处理,即假如比较两边有一方的某些位的值是z或x,那么这些位的比较就不予考虑。

casex会把z/?x匹配成恣意,也会把恣意匹配成z/?/x,即直接疏忽z/?/x

办法

case (variable)

costant_1:

begin

operations_1

end

costant_2:

begin

operations_2

end

……

default:

begin

operations_m

end

endcase

case (variable)

costant_1:

begin

operations_1

end

costant_2:

begin

operations_2

end

……

default:

begin

operations_m

end

endcase

case (variable)

costant_1:

begin

operations_1

end

costant_2:

begin

operations_2

end

……

default:

begin

operations_m

end

endcase

constant项

各个constant项为确认宽度的常数值,不包括x和z;

能够用“?”表明不关心该位数值

各个constant项为确认宽度的常数值,可包括x但不能包括z

各个constant项为确认宽度的常数值,可包括z但不能包括z

constant比如

3’b000:3比特宽度全0;

3’b0?0:3比特宽度第二比特不关心,其他比特为0

3’b000:3比特宽度全0;

3’b0?0:3比特宽度第二比特不关心,其他比特为0;

3’b00x:3比特宽度最低比特为x,其他比特为0

3’b000:3比特宽度全0;

3’b0?0:3比特宽度第二比特不关心,其他比特为0;

3’b00z:3比特宽度最低比特为不关心,其他比特为0

可归纳性

可归纳

依靠归纳软件

依靠归纳软件

case括弧内的变量称为操控表达式,case分支项中的常数称为分支表达式。操控表达式一般表明为操控信号的某些位,分支表达式则用这些操控信号的具体状态值来表明,因而分支表达式又能够称为常量表达式。当操控表达式的值与分支表达式的值持平时,就履行分支表达式后边的句子。假如一切的分支表达式的值都没有与操控表达式的值相匹配的,就履行default后边的句子。

default项可有可无,一个case句子里只能有一个default项。 当分支表达式能够掩盖操控表达式悉数分枝途径时,default能够不写。可是,有时分这个全掩盖不是那么简单看出来的,所以主张最好写上default,哪怕有冗余这个default永久不或许被完结。也请我们定心,这种冗余归纳软件会大伙儿去掉的,不用忧虑糟蹋电路资源。

每一个case分项的分支表达式的值有必要互不相同,否则就会呈现对立现象(对表达式的同一个值,有多种履行计划)。

履行完case分项后的句子,则跳出该case句子结构,停止case句子的履行。(通晓C言语的大虾们请特别留意这点,这儿case操作履行完之后不用写break了。)

在用case句子表达式进行比较的过程中,只需当信号的对应位的值能清晰进行比较时,比较才干成功,因而要具体阐明case分项的分支表达式的值。

case句子的一切表达式的值的位宽有必要持平,只需这样操控表达式和分支表达式才干进行对应位的比较。一个经常犯的过错是用bx、bz 来代替nbx、nbz,这样写是不对的,由于信号x、z的缺省宽度是机器的字节宽度,一般是32位(此处 n 是case操控表达式的位宽)。

当分支表达式不彻底掩盖操控表达式悉数分枝途径时,您老有偷闲没有写default的状况下,或许发生时序逻辑的锁存器的,这点和条件if句子相似。例4是一个比如,阐明晰default的重要性。可是,图1中的“ld”是锁存器现已是时序电路的元件了,逾越了本章的规模。

【例4】case句子条件掩盖不全发生会归纳出锁存器
代码1:组合逻辑电路写法
module case_full
(
input[7:0] number,
input[1:0] select,
output reg[7:0] result
);

//Load other module(s)

//Definition for Variables in the module

//Logical
always @(*)
begin
case (select)
2b00:
begin
result = number + 8b0000_0001;
end
2b01:
begin
result = number;
end
2b10:
begin
result = number – 8b0000_0001;
end
default:
begin
result = 8b0000_0000;
end
endcase
end
endmodule


图1例4归纳出的电路图(悉数为组合逻辑)

4. 多路挑选,一个比如
数据挑选器(也称为:多路复用器,英文:multiplexer,简写:MUX),是一种从多路输入信号中挑选一个信号作为输出的器材。电器符号如图2所示。


图2数据挑选器的电气符号

数据挑选器的的逻辑功用是:

留意,其间输入I0、I1和SEL以及输出O都是1比特位宽的信号。对应布尔逻辑表达式是

对应Verilog代码为:
1) 使用? :表达式
input SEL;
input I0;
input I1;
output O
assign O =(SEL) ? (I0) : (I1);
代码中要害的部分是? :表达式,其语法结构为 (逻辑表达式) ? (值0) : (值1);作用是

所以,以上代码满意了数字电路里边数据挑选器的功用。

2) 使用if要害词
If (SEL == 1’b0)
begin
O = I0;
end
else
begin
O = I1;
end
3) 使用case要害词
case (SEL)
1’b0:
begin
O = I0;
end
1’b1:
begin
O = I1;
end
endcase

在许多状况下,需求挑选的输入位宽大于1,这个时分只需两个待挑选的输入与输出的位宽共同,照样能够完结功用(以下依照8比特输入为例)。此刻Verilog代码除了模块的接口位宽,其他部分几乎没有改变:

input SEL;
input[7:0] I0;
input[7:0] I1;
output[7:0] O
assign O =(SEL) ? (I0) : (I1);

当然用if或许case句子也能够完结,信任读者触类旁通的才能,就不罗列了。
许多读者或许会感觉到笔者非常烦琐,实则否则,图3是多位输入的数据挑选器的电气原理图。


图3 多位数据挑选器的电路原理图

上图看起来是水到渠成的。这儿之所以笔者还诲人不倦的画出来,是为了叫读者看到多位与1比特完结上的差异。假如眼睛还没有贵恙的话,能够看出来多位数据挑选器便是若干1比特数据挑选器的并行摆放。考虑到前面内容介绍的时延问题,需求提示读者留意的是这个位数很高(当然不是比如里边的8比特)的时分,输入和输出信号的skew(线间时延)或许会给规划带来费事。

另一种常见的状况是输入不止有两个信号,或许说需求在不仅仅两个信号里边进行挑选,这个叫做高阶数据挑选器(一般吧SEL的比特数称为数据挑选器的阶数)。一般输入个数是2的幂,此刻挑选信号SEL也就不仅是1比特信号了,这个很简单了解。在理论上,能够经过打开布尔逻辑表达式的办法,完结高速的高阶数据挑选器。例如,2阶(也便是有4个输入信号,SEL为2比特变量)的随机挑选的布尔逻辑表达式为:

其间,I0、I1、I2和I3为器材的输入,S0和S1为SEL信号的低比特和高比特。
这个式子现已不简略了,假如是10阶神马的数据挑选器,那样的式子的长度不难想象。所以,在工程上,一般使用低阶数据挑选器的串联来完结高阶数据挑选器。图4是一个用3个1阶数据挑选器完结2阶数据挑选器的比如。


图4 使用低阶数据挑选器完结高阶数据挑选器

关于高阶数据挑选器的Verilog代码,一般主张使用case的办法。例如图3里边的2阶数据挑选器能够用以下代码完结:
case (SEL)
2’b00:
begin
O = I0;
end
2’b01:
begin
O = I1;
end
2’b01:
begin
O = I2;
end
2’b11:
begin
O = I3;
end

endcase
这正是:

组合逻辑大交融,要害语法有心得。不管理论数学河,电路优化靠归纳。
不才平话自有乐,撬行老僧沙弥哥。陈述收拾妒忌惹,大乘渡人笑呵呵。

与非网原创内容,谢绝转载!

系列汇总:

之一:温故而知新:从电路里来,到Verilog里去!

之二:Verilog编程无法一蹴即至,言语层次考究“名正则言顺”

之三:数字逻辑不容小窥,电路门一统江湖

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/199169.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部