Verilog9-Verilog_HDL数字集成电路设计与应用(chapter2,3)

Verilog_HDL数字集成电路设计与应用(chapter2,3)

//例2.3-2
module arith_tb;
    reg[3:0]a;
    reg[2:0]b;
    initial
        begin
            a = 4'b1111;
            b = 4'b011;
            $display("%b",a*b);		//结果为45的低四位
            $display("%b",a/b);
            $display("%b",a+b);
        end
endmodule

//例2.3-3
module rela_tb;
    reg[3:0]a,b,c,d;
    initial 
        begin
            a = 3;
            b = 6;
            c = 1;
            d = 4'hx;
            $display(a<b);		//结果为假(0)
            $display(d <= a);	//结果为不定值(x)
        end
endmodule

//例2.3-4
module equal_tb;
    reg[3:0]a,b,c,d;
    initial
        begin
            a = 4'b0xx1;
            b = 4'b0xx1;
            c = 4'b0011;
            d = 2'b11;
            $display(a==b);		//结果为不定值(x)
            $display(a===b);	//.....真(1)
            $display(c==d);		//.....真(1)
            $display(c===d);	//.....假(0)
        end
endmodule


2.3.4 逻辑运算符

  • 若操作数中存在不定态x,则逻辑运算的结果也是不定态

2.3.5 按位运算符

  • 五种类型位运算符
    • 按位取反(~),按位与(&)、按位或(|),按位异或(^),按位同或( ^~)
  • 两个不同长度的数据按位运算时,回自动将两个操作数按右对齐,高位补0
  • 运算结果的位宽与操作数中位宽较大者相同。

2.3.6 归约运算符

  • 归约运算符
    • 按位运算
    • 单目运算符
    • 结果:产生1位逻辑值 —— 缩位运算符
  • 缩位运算符
    • &、|、^、~ &、~ |、~ ^ 、^ ~
    • 归约运算符的操作数只有1个
  • 运算过程:设 a 是一个4位的寄存器型变量,分别是a[0],a[1],a[2],a[3]。当对a 进行缩位运算时,先对a[0] 和a[1] 进行缩位运算,产生1位结果,再将该结果与a[2]进行缩位运算,再是a[3],最后产生1位的操作结果
module cut_tb;
    reg[5:0]a;
    initial
        begin
            a = 6'b101011;
            $display("%b",&a);	//结果位1'b0
            $display("%b",|a);	//结果位 1'b1
            $display("%b",^a);	// 结果为1'b0
            
            //移位运算符
            b = a<<2;
            c = a>>3;
            $display("%b",b);
            $display("%b",c);
        end
endmodule

2.3.7 移位运算符

  • 左移运算符 <<
  • 右移运算符 >>
  • 用0 补位

2.3.8 条件运算符

  • < 条件表达式>?< 表达式1 >:< 表达式2 >
    • 结果:真(1),假(0),不定态(x)
    • 如果条件表达式的运算结果为不定态,则模拟器将按位对表达式1的值与表达式2的值进行比较,构成条件表达式的值。
//2.3-8 2选1数据选择器
module mux2(in1,in2,sel,out);
    input[3:0]in1,in2;
    input sel;
    output[3:0]out;
    wire[3:0]out;
    assign out = (!sel)?in1:in2;
endmodule

2.3.9 连接和复制运算符

  • 连接运算符({}) :将几个信号或数值连接成一个整体信号
    • 格式:{信号1的某几位,信号2的某几位,……,信号n的某几位}
  • 复制运算符({{}}):将一个表达式放入双重花括号中,复制因子放在第一层括号中。
module con_rep_tb;
    reg[2:0]a;
    reg[3:0]b;
    reg[7:0]c;
    reg[4:0]d;
    reg[5:0]e;
    initial 
        begin
            a = 3'b101;
            b = 4'b1110;
            c = {a,b};		//结果 8'b01011110
            d = {a[2:1],b[2:0]};
            e = {2{a}};		//复制操作,结果 6'b101101
        end
endmodule

3.1数据流建模

//3.1-1 显式连续赋值语句
module example1_assignment(a,b,m,n,c,y);
    input[3:0]a,b,m,n;
    output[3:0]c,y;
    wire[3:0]a,b,m,n,c,y;	//声明语句
    assign y = m|n;			//显式赋值语句
    assign #(3,2,4)c=a&b;	//显式连续赋值语句
endmodule

//3.1-2 隐式连续赋值语句
module example2_assignment(a,b,m,n,c,y,w);
    input[3:0]a,b,m,n;
    output[3:0]c,y,w;
    wire[3:0]a,b,m,n;	//声明语句
    wire[3:0]y = m|n;	//隐式赋值语句
    wire[3:0]#(3,2,4)c=a&b;		//隐式连续赋值语句
    wire(strong0,weak1)[3:0]#(2,1,3)w = (a^b)&(m^n); //隐式连续赋值语句
endmodule

3.2 行为级建模

3.2.1 过程语句

  • initial过程语句
    • 用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值
  • 在过程语句(initial,always)中,被赋值信号必须定义为“reg"类型

3.2.2 语句块

//串行语句块:begin...end
module wave_tb1;
    reg wave;
    parameter T=10;
    initial
        begin	//当块内有变量时,必须有块名,即 begin:块名
            wave=0;
            #T wave=1;
            #T wave=0;
            #T wave=1;
            #T wave=0;
        end
endmodule
//并行语句块:fork...join
module wave_tb2;
    reg wave;
    parameter T=10;
    initial
        fork
            wave=0;
            #T 		wave=1;
            #(2*T) 	wave=0;
            #(3*T) 	wave=1;
            #(4*T) 	wave=0;
        join
endmodule

3.2.3 过程赋值语句

  • 阻塞赋值语句:= ,直接赋值
  • 非阻塞赋值语句:<=相当于触发器,有延迟
// 3.2-8
//程序1
module block3(a,b,c,clk,sel,out);
    input a,b,c,clk,sel;
    output out;
    reg out,temp;
    always@(posedge clk)
        begin
            temp=a&b;
            if(sel)out=temple;
            else out=c;
        end
endmodule
//程序2
module block4(a,b,c,clk,sel,out);
    input a,b,c,clk,sel;
    output out;
    reg out,temp;
    always@(posedge clk)
        begin
            temp<=a&b;
            if(sel)out<=temp;
            else out<=c;		//非阻塞式赋值,产生两级流水线
        end
endmodule

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7zTlijvK-1602333855033)(D:\BCRC\documents\work\digital\assets\image-20200314143447257.png)]

  • 为什么有out~0门,干啥用?

3.2.4 过程连续赋值语句

  • 赋值语句与重新赋值语句:assign……deassign
  • 强制语句与释放语句:force…… release
//3.2-9 使用assign,deassign设计异步清零D触发器
module assign_dff(d,clr,clk,q);
    input d,clr,clk;
    output q;
    reg q;
    always@(clr)
        begin
            if(!clr)
                assign q=0;
            else
                deassign q;
        end
    always@(negedge clk) q=d;
endmodule
//3.2-10
module force_release(a,b,out);
    input a,b;
    output out;
    wire out;
    and(out,a,b);
    initial
        begin
            force out=a|b;
            #5;
            release out;
        end
endmodule

module release_tb;
    reg a,b;
    wire out;
    force_relesse_tb U1(a,b,out);
    initial begin
        a=1,b=0;
    end
endmodule

3.3结构化建模

3.3.1 模块级建模

//3.3-7 使用defparam语句修改参数值
module halfadder(a,b,s,c);
    input a,b;
    output c,s;
    parameter xor_delay=2,and_delay=3;
    assign #xor_delay s=a^b;
    assign #and_delay c=a&b;
endmodule

module fulladder(p,q,ci,co,sum);
    input p,q,ci;
    output co,sim;
    parameter or_delay=1;
    wire w1,w2,w3;
    halfadder		U1(p,q,w1,w2);
    halfadder		U2(ci,w1,sum,w3);
    or #or_delay	U3(co,w2,w3);
endmodule

module top1(top1a,top1b,top1s,top1c);	//修改半加器参数
    input top1a,top1b;
    output top1s,top1c;
    	defparam U1.xor_delay=4,U1.and_delay=5;
    halfadder U1(top1a,top1b,top1s,top1c);
endmodule
module top2(top2a,top2b,top2ci,top2co,top2sum);	//修改全加器参数
    input top2a,top2b,top2ci;
    output top2co,top2sum;
    	defparam	U2.U1.xor_delay=6,
    				U2.U1.and_delay=7;
    	U2.or_delay=5;
    fulladder U2(top2a,top2b,top2ci,top2co,top2sum);
endmodule
//3.3-10 cmos开关级2输入与非门示例
module nnand2(a,b,y);
    input a,b;
    output y;
    supply0 Gnd;
    supply1 Vdd;	//supply0,supply1为内部参量,分别表示低电平和高电平
    wire im1;
    	pmos g1(y,Vdd,a);
    	pmos g2(y,Vss,b);
    	nmos g3(y,im1,a);
    	nmos g4(im1,Gnd,b);
endmodule

课后习题

3.1 连续赋值语句 与 过程赋值语句

  • 连续赋值
    • 语法上:**关键词“assign”**标识
    • 被赋值的数据类型必须是线网型(wire)
    • 连续赋值语句不能出现在过程块(initial,always中)
    • 连续赋值语句主要对数据流行为建模组合逻辑进行建模,对线网wire型数据,进行描述
    • 右端操作数的值发生变化时便执行赋值(上电便一直执行)
  • 过程赋值
    • 语法上:只能在initial,always语句(过程块)内的赋值,无assign
    • 只能对寄存器(reg)型变量赋值
    • 类别:使用 = 或 <=
      • 阻塞赋值语句:
        • 符号 =,各阻塞赋值语句顺序执行
        • 执行顺序:计算右侧表达式,立即赋给左边变量
      • 非阻塞赋值语句:
        • 符号: <=,各非阻塞赋值语句并行执行
        • 执行顺序:计算右侧表达式,等待延迟时间结束,再将结果赋给左边变量
    • 过程性赋值语句主要描述顺序行为建模时序逻辑电路,用于驱动寄存器
    • initial块只执行一次,若有多个initial块,则在程序开始时并行执行;always块只要满足敏感列表条件就执行一次
  • 过程性连续赋值语句
    • 两组过程性连续赋值语句可以实现连续赋值
      • assign - deassign:只能对寄存器(reg)型变量的连续赋值操作
        • 使用assign给寄存器赋值之后,这个值将一直保持在这个寄存器上,直到遇到 deassign 为止
      • force - release:可以对线网型(wire)或寄存器型(reg)型操作,force语句的优先级高于assign
        • force语句用于寄存器时,会将寄存器当前值覆盖,release之后寄存器值不变,直到被重新赋值。

3.2 连续赋值语句描述4选1数据选择器

module mux(out,in0,in1,in2,in3,add);
    output out;
    input in0,in1,in2,in3;
    input[1:0] add;
    wire out;
    assign out=((~add[0])&(~add[1])&in0)||((~add[0])&(add[1])&in1)||((add[0])&(~add[1])&in2)||((add[0])&(add[1])&in3);
endmodule

3.3

  • Verilog 常用复位:同步复位,异步复位
  • 同步复位和异步复位
    • 同步复位:时钟敏感,复位信号随时钟边沿触发有效
    • 异步复位:电平敏感,复位信号与时钟无关
  • 同步电路和异步电路
    • 同步电路:统一时钟源,经过PLL分频后的时钟驱动模块也是同步电路。
    • 异步电路:没有统一时钟源
  • 同步逻辑、异步逻辑
    • 同步逻辑:时钟之间有固定的因果关系
    • 异步逻辑:………… 没有……………………

3.4

  • always:

    • 敏感信号列表中信号值发生变化就执行

    • 敏感信号可以是:边沿敏感型 或 电平敏感型

      reg[3:0] a;
      reg[1:0] b;
      always@(posedge clk)
          a=4'b1011;
      	b<=2'b10;
      
  • initial

    • 只执行一次

    • 多个initial过程块时,从时间0开始并行执行

    • initial块内的多条行为语句可以是顺序执行,也可以是并行执行

    • 用途:仿真模块中对激励向量的描述,给寄存器型变量赋初值

      initial
          begin
              a=2'b11;
              b=3'o463;
          end
      

3.5

  • begin-end:其中语句串行执行
  • fork - join:其中语句并行执行
module begin_exam;
    reg A;
    reg B;
    initial
        begin
            A=0,B=1;
            #10 A=1,B=0;
            #10 A=1,B=1;
            #10 A=0,B=1;
            #10 A=0,B=0;
            #10 A=1,B=1;
        end
endmodule

module fork_exam;
    reg A;
    reg B;
    initial
        fork
            A=0,B=1;
            #10 A=1,B=0;
            #20 A=1,B=1;
            #30 A=0,B=1;
            #40 A=0,B=0;
            #50 A=1,B=1;
        join
endmodule

3.8

  • 阻塞赋值语句
    • =,顺序执行,前面的未执行完后面无法执行
  • 非阻塞赋值语句
    • <=,并行执行,前面的是否执行完不影响后面
//阻塞赋值
module register1(out,din,clk);
    output[3:0] out;
    input din,clk;
    reg[3:0] out;
    always@(posedge clk)
        out[3]=out[2];
    	out[2]=out[1];
   		out[1]=out[0];
    	out[0]=din;
endmodule

//非阻塞赋值
module register2(out,din,clk);
    output[3:0] out;
    input din,clk
    reg[3:0] out;
    always@(posedge clk)
        out[0]<=din;
    	out[1]<=out[0];
    	out[2]<=out[1];
    	out[3]<=out[2];
endmodule

3.10 case,casex,casez

3.14

module exam_14(Z,D,S);
    output Z;
    input[3:0] D;
    input S1,S2;
    wire S2not,S1not;
    reg[3:0] T;
    reg Z;
    and3 U1(T[3],D[3],S1,S2);
    and3 U2(T[2],D[2],S1,S2not);
    and3 U3(T[1],D[1],S1not,S2);
    and3 U4(T[0],D[0],S1not,S2not)
    not U5(S1not,S1);
    not U6(S2not,S2);
    or4 U7(Z,T[0],T[1],T[2],T[3]);
endmodule

module and3(out,in1,in2,in3);
    output out;
    input in1,in2,in3;
    reg out;
    out=in1&in2&in3;
endmodule

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值