当前位置:首页 > EDA > 电子设计自动化
[导读] 4.5.1 always块语言指导原则使用always块进行可综合的代码设计时需要注意以下几个问题。(1)每个always块只能有一个事件控制“@(event-expression)”,而且要紧跟在always关键字后面。(2)always块可以表示

 4.5.1 always块语言指导原则

使用always块进行可综合的代码设计时需要注意以下几个问题。

(1)每个always块只能有一个事件控制“@(event-expression)”,而且要紧跟在always关键字后面。

(2)always块可以表示时序逻辑或者组合逻辑,也可以用always块既表示电平敏感的透明锁存器又同时表示组合逻辑。但是不推荐使用这种描述方法,因为这容易产生错误和多余的电平敏感的透明锁存器。

(3) 带有posedge 或 negedge 关键字的事件表达式表示沿触发的时序逻辑;没有posedge 或negedge关键字的表示组合逻辑或电平敏感的锁存器,或者两种都表示。在表示时序和组合逻辑的事件控制表达式中如有多个沿和多个电平,其间必须用关键字“or” 连接 。

(4)每个表示时序逻辑的always块只能由一个时钟跳变沿触发,置位或复位最好也由该时钟跳变沿触发。

(5)每个在always块中赋值的信号都必需定义成reg型或整型。整型变量缺省为32bit,使用Verilog操作符可对其进行二进制求补的算术运算。综合器还支持整型量的范围说明,这样就允许产生不是32位的整型量,句法结构如下:

integer[:]

(6)always块中应该避免组合反馈回路。每次执行always块时,在生成组合逻辑的always块中赋值的所有信号必需都有明确的值;否则需要设计者在设计中加入电平敏感的锁存器来保持赋值前的最后一个值。

只有这样,综合器才能正常生成电路。如果不这样做,综合器会发出警告,提示设计中插入了锁存器。如果在设计中存在综合器认为不是电平敏感锁存器的组合回路时,综合器会发出错误信息(例如设计中有异步状态机时)。

用always块设计纯组合逻辑电路时,在生成组合逻辑的always块中,参与赋值的所有信号都必须有明确的值,即在赋值表达式右端参与赋值的信号都必需在always @(敏感电平列表)中列出。

如果在赋值表达式右端引用了敏感电平列表中没有列出的信号,那么在综合时,将会为该信号产生一个隐含的透明锁存器。这是因为该信号的变化不会立刻引起所赋值的变化,而必须等到敏感电平列表中某一个信号变化时,它的作用才显现出来。

也就是相当于存在着一个透明锁存器把该信号的变化暂存起来,待敏感电平列表中某一个信号变化时再起作用,纯组合逻辑电路不可能做到这一点。这样,综合后所得电路已经不是纯组合逻辑电路了。这时综合器会发出警告提示设计中插入了锁存器,如下所示:

input a,b,c;
reg e,d;
always @(a or b or c) begin
      e = d & a & b;       //因为d没有在敏感电平列表中,所以d变化时,e不能立刻变化,
                              //要等到a或b或c变化时才体现出来。这就是说实际上相当于存在
                              //一个电平敏感的透明锁存器在起作用, 把d信号的变化锁存其中
      d = e | c;
end

(7)对一个寄存器型(reg)或整型(integer)变量的赋值只允许在一个always块内进行,如果在另一always块也对其赋值,这是非法的。
(8)把某一信号值赋为'bx,综合器就把它解释成无关状态,因而综合器为其生成的硬件电路最简洁。


4.5.2  可综合风格的Verilog HDL模块实例
1.组合逻辑电路设计实例


例4.6:8位带进位端的加法器的设计实例(利用简单的算法描述)。

module adder_8(cout,sum,a,b,cin);               //模块声明
      output cout;
      output [7:0] sum;
      input cin;
      input[7:0] a,b;                             //端口声明
      assign {cout,sum} = a + b + cin;          //加法器算法
endmodule

 

例4.7:指令译码电路的设计实例(利用电平敏感的always块来设计组合逻辑)。

'define plus     3'd0                         //操作码的宏定义
'define minus    3'd1
'define band     3'd2
'define bor      3'd3'
'define unegate  3'd4

module alu(out,opcode,a,b);                 //模块声明
      output [7:0] out;
      input [2:0] opcode;
      input [7:0] a,b;                       //端口声明
      reg   [7:0] out;                      //寄存器声明

      always @(opcode or a or b) begin       //用电平敏感的always块描述组合逻辑
            case(opcode)
                  'plus: out = a + b;         //算术运算
                  'minus: out = a - b;
                  'band: out = a & b;          //位运算
                  'bor:  out = a | b;
                  'unegate: out = ~a;        //单目运算
                   default: out = 8'hx;
      endcase
      end
endmodule

 

例4.8:比较后重组信号的组合逻辑(利用task和电平敏感的always块设计)。

module sort4(ra,rb,rc,rd,a,b,c,d);         //模块声明
      output [t:0] ra, rb, rc, rd;
      input [t:0] a, b, c, d;               //端口声明
      reg [t:0] ra, rb, rc, rd;
      reg [t:0] va, vb, vc, vd;             //寄存器声明
      parameter t=3;                            //参数声明

      always @(a or b or c or d) begin       //用电平敏感的always块描述组合逻辑
           {va,vb,vc,vd}={a,b,c,d};
           sort2(va,vc);                        //信号重组
           sort2(vb,vd);
           sort2(va,vb);
           sort2(vc,vd);
           sort2(vb,vc);
           {ra,rb,rc,rd}={va,vb,vc,vd};
      end

      task sort2;                             //x与y互换任务
            inout [t:0] x,y;
            reg [t:0] tmp;
            if(x > y) begin
                 tmp = x;               //使用临时变量tmp保存x的值
                 x = y;
                 y = tmp;
      end
      endtask
endmodule

 

例4.9:比较器的设计实例(利用赋值语句设计组合逻辑)。

module compare(equal,a,b);              //模块声明
      output equal;
      input [size-1:0] a,b;            //端口声明
      parameter size=1;                  //参数声明
      assign  equal =(a==b)? 1 : 0;  //比较器
endmodule

 

例4.10:3-8译码器设计实例(利用赋值语句设计组合逻辑)。

module decoder(out,in);             //模块声明
      output [7:0] out;
      input [2:0] in;                 //端口声明
      assign  out = 1'b1<<in;       //把最低位的1左移 in(根据从in口输入的值)位
                                          //将移位结果赋予out
endmodule

 

例4.11:3-8编码器的设计实例。
编码器设计方案一。

module encoder1(none_on,out,in);            //模块声明
      output none_on;
      output [2:0] out;
      input [7:0] in;                         //端口声明
      reg [2:0] out;
      reg none_on;                              //寄存器声明
      always @(in) begin: local                //in有变化时,触发
            integer  i;                           //变量声明
            out = 0;
            none_on = 1;                         //初始化
            for( i=0; i<8; i=i+1 ) begin      //for循环语句
                 if( in[i] ) begin         //将in中值为1的位编码
                      out = i;
                      none_on = 0;
                 end
            end
      end
endmodule

 

编码器设计方案二。

module encoder2 ( none_on,out2,out1,out0,h,g,f,e,d,c,b,a);     //模块声明
      input h,g,f,e,d,c,b,a;
      output none_on,out2,out1,out0;         //端口声明
      wire [3:0] outvec;                      //向量声明
      assign outvec =                           //使用assign语句实现输出向量赋值
            h ? 4'b0111 : g ? 4'b0110 : f ? 4'b0101:
            e ? 4'b0100 : d ? 4'b0011 : c ? 4'b0010 :
            b ? 4'b0001 : a ? 4'b0000 : 4'b1000;
      assign none_on = outvec[3];            //使用assign语句进行编码
      assign    out2 = outvec[2];
      assign    out1 = outvec[1];
      assign    out0 = outvec[0];
endmodule

 

编码器设计方案三。

module encoder3 ( none_on,out2,out1,out0,h,g,f,e,d,c,b,a);     //模块声明
      input h,g,f,e,d,c,b,a;
      output none_on,out2,out1,out0;      //端口声明
      wire [3:0] outvec;                    //向量声明
      assign {none_on,out2,out1,out0} = outvec;   //与上例的编码方式一致
      always @( a or b or c or d or e or f or g or h) begin
            if(h)       outvec=4'b0111;     //使用if_else语句实现向量赋值
            else if(g) outvec=4'b0110; //共9个分支,其中向量的低3位有8种编码方式
            else if(f) outvec=4'b0101;
            else if(e) outvec=4'b0100;
            else if(d) outvec=4'b0011;
            else if(c) outvec=4'b0010;
            else if(b) outvec=4'b0001;
            else if(a) outvec=4'b0000;
            else         outvec=4'b1000;
      end
endmodule

例4.12:多路器的设计实例。


使用assign赋值语句、case语句或if-else语句可以生成多路器电路。如果条件语句(case或if-else)中分支条件是互斥的话,综合器能自动地生成并行的多路器。
多路器设计方案一。

modul emux1(out,a,b,sel);                //模块声明
     output out;
     input a,b,sel;                         //端口声明
                                               //使用assign语句检查输入信号sel的值
     assign out = sel ? a : b;            //当sel为1时,out为a;否则为b
endmodule

 

多路器设计方案二。

module  mux2( out,a,b,sel);          //模块声明
      output out;
      input a,b,sel;                    //端口声明
      reg out;
      always @(a or b or sel) begin //用电平触发的always块来设计多路器的组合逻辑
            case( sel )                 //使用case语句检查输入信号sel的值
                1'b1: out = a;         //如果为1,输出out为a
                1'b0: out = b;         //如果为0,输出out为b
                default: out = 'bx;   //默认状态
            endcase
      end
endmodule

 

多路器设计方案三。

module mux3( out,a,b sel);                 //模块声明
      output out;
      input a, b, sel;                       //端口声明
      reg out;
      always @( a or b or sel ) begin
           if( sel )                          //使用if_else语句检查输入信号sel的值
                out = a;                      //如果为1,输出out为a
           else
                out = b;                      //如果为0,输出out为b
      end
endmodule

 

例4.13:奇偶校验位生成器设计实例。

module parity( even_numbits,odd_numbits,input_bus);  //模块声明
      output even_numbits, odd_numbits;
      input [7:0] input_bus;                  //端口声明
      assign odd_numbits = ^input_bus; //当input_bus中1的个数为奇数时,输出为1
      assign even_numbits = ~odd_numbits;  //此时输出even_numbits为0
endmodule

 

例4.14:三态输出驱动器设计实例(用连续赋值语句建立三态门模型)。
三态输出驱动器设计方案一。

module trist1( out,in,enable);            //模块声明
      output out;
      input in, enable;                     //端口声明
      assign  out = enable? in: 'bz;      //使用assign语句判断enable的值
endmodule

 

三态输出驱动器设计方案二。

module trist2( out,in,enable );    //模块声明
      output out;
      input in,enable;                //端口声明
      bufif1 mybuf1(out, in, enable); //bufif1是一个 Verilog门级原语(primitive)
                                         //通过实例化该原语,实现三态门的调用
endmodule

 

例4.15:三态双向驱动器设计实例。

module bidir(tri_inout,out,in,en,b);         //模块声明
      inout tri_inout;
      output out;
      input in,en,b;                             //端口声明
      assign tri_inout = en? in : 'bz;       //三态门的输入为in
      assign out = tri_inout ^ b;             //三态门的输出为b
endmodule


2.时序逻辑电路设计实例
例4.16:触发器设计实例。

module dff( q,data,clk);                  //模块声明
      output q;
      input data,clk;                       //端口声明
      reg q;
      always @( posedge clk ) begin      //边缘检测
            q = data;                        //通过always语句,实现触发器
      end
endmodule

 

例4.17:电平敏感型锁存器设计实例一(assign语句)。

module latch1( q,data,clk);                //模块声明
      output q;
      input data,clk;                        //端口声明
      assign q = clk ? data : q;           //通过assign语句,实现的是一个锁存器
endmodule

 

例4.18:带置位和复位端的电平敏感型锁存器设计实例二(assign语句)。

module latch2( q,data,clk,set,reset);   //模块声明
      output q;
      input data,clk,set,reset;           //端口声明
      assign q= reset ? 0 : ( set? 1:(clk? data : q ) );
                                               //通过assign语句,实现的是一个锁存器
                                               //其中,set为置位端,reset为复位端
                                               //在clk为高电平时,锁存data,否则保持q值
endmodule

 

例4.19:电平敏感型锁存器设计实例三(always块)。

module latch3( q, data, clk);           //模块声明
      output q;
      input data,clk;                      //端口声明
      reg q;
      always @(clk or data) begin       //电平检测
            if(clk)                         //clk为高电平时,q锁存data值
                  q = data;
      end
endmodule

 

  注意 有的综合器会产生一个警告信息,提示将产生了一个电平敏感型锁存器。因为此例中设计的就是一个电平敏感型锁存器,所以这个警告信息是没有问题的。

 

例4.20:移位寄存器设计实例。

module shifter( din,clk,clr,dout);         //模块声明
      input din,clk,clr;
      output [7:0] dout;                     //端口声明
      reg [7:0] dout;
      always @(posedge clk) begin
            if(clr)                             //清零
                   dout = 8'b0;
            else begin
                   dout = dout<<1;             //左移一位
                   dout[0] = din;             //把输入信号放入寄存器的最低位
            end
      end
endmodule


例4.21:8位计数器设计实例一。

module counter1( out, cout, data, load, cin, clk);     //模块声明
      output [7:0] out;
      output cout;
      input [7:0] data;
      input load, cin, clk;                //端口声明
      reg [7:0] out;
      always @(posedge clk) begin         //边缘检测
            if( load )                        //加载信号检测
                 out = data;
            else
                 out = out + cin;
            end
      assign cout= & out & cin;           //只有当out[7:0]的所有各位都为1
                                               //并且进位cin也为1时才能产生进位cout
endmodule

 

例4.22:8位计数器设计实例二。

module counter2( out, cout, data, load, cin, clk);     //模块声明
      output [7:0] out;
      output cout;
      input [7:0] data;
      input load, cin, clk;                     //端口声明
      reg [7:0] out;
      reg cout;
      reg [7:0] preout;                         //寄存器声明
      always @(posedge clk) begin              //边缘检测
            out = preout;                         //触发器
            end
      //计算计数器和进位的下一个状态,为提高性能,load不应影响进位
      always @( out or data or load or cin ) begin
            {cout, preout} = out + cin;        //进位操作
            if(load) preout = data;             //判断加载信号
            end
endmodule

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭