实验目的

  1. 熟练掌握文本输入设计、综合、仿真和下载的基本流程
  2. 掌握Verilog HDL模块的构成和基本逻辑模块的设计规范。
  3. 掌握测试代码的撰写和仿真测试方法。

预习要求

  1. 了解EDA数字系统设计的基本流程。
  2. 了解QuartusII或iverilog&gtkwave软件使用的基本规范和操作流程
  3. 了解测试代码撰写规范。

实验原理

  1. 待测模块test003
    1
    2
    3
    4
    5
    6
    7
    8
    9
    module test003(
    input[1:0] in1,
    input[1:0] in2,
    output cont,
    output[1:0] sum
    );
    assign {cont,sum}=in1+in2;
    endmodule

  2. 测试代码,可以通过quartus自动产生测试模板。通过控制送入待测模块的信号观测输出,分析输出与预期进行比较判断是否正确。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    `timescale 1 ns/ 1 ps  //时间标尺,确定时间单位和精度
    module test003_vlg_tst();//测试模块或测试平台代码,无参数列表
    reg [1:0] in1;//数据类型遵循always或initial中被赋值为variable类型的规则
    reg [1:0] in2;
    wire cont;
    wire [1:0] sum;

    reg clk;//该变量定义此处只为生成时钟演示,再test003模块中并不使用


    test003 i1 (//模块调用,待测模块
    .cont(cont),
    .in1(in1),
    .in2(in2),
    .sum(sum)
    );
    initial
    begin
    in1=0;in2=0;clk=0;
    #5 in1=1;in2=2;
    //$display("display:in1=%b",in1);可以使用display输出
    #5 in1=2;in2=2;
    //$display("display:in1=%b %t",in1,$realtime);
    #20 $stop;

    end
    always #5 clk=~clk;

    initial // 下面代码与上面always功能类似,产生连续时钟信号,实际电路测试可以选择其中某一种方式实现即可。
    begin
    forever #5 clk=~clk;
    repeat(200) #5 clk=~clk;
    end
    initial
    $monitor($realtime,,,"monitor: in1=%b",in1);//信号有变化,monitor输出一次

    endmodule

  3. 代码范例,下面提供了功能电路的各种实现方式,逻辑描述的不同风格,以供参考。
    (1)三裁判电路设计。a、b、c表示三位裁判,out表示输出,同意输出1,不同意输出0。参考代码如下。
    1
    2
    3
    4
    5
    6
    7
    8
    module lab001(a,b,c,out);//模块定义。
    input a,b,c;
    output out;
    wire[1:0] sum;//sum变量的用途传递计算和,注意和范围为0-3,所以设定为2位
    assign sum=a+b+c;//assign语句,再always模块外部,独立语句必须用assign
    assign out=sum[1]?1:0;//条件运算符,思考sum[1]代表的含义
    endmodule

    (2)三裁判电路的always设计。参考代码如下。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    module lab002(a,b,c,out);
    input a,b,c;
    output out;
    reg[1:0] sum;
    assign sum=a+b+c;
    always@(a,b,c)//always过程定义,注意上面assign和always过程块(begin-end之间)是并行结构,并行运行。注意always括号内信号列表的格式和含义
    begin
    if(sum>=2) out=1;//if语句对out进行赋值,注意此处不用assign
    else out=0;
    end
    endmodule

    (3)三裁判电路,采用模块调用设计。参考代码如下。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    module lab003(a,out);//主模块
    input[2:0] a;
    output out;
    wire[1:0] out1;
    lab0031 lab1(a,out1);//模块调用
    assign out=(out1>=2)?1:0;//assign语句、always过程块、模块调用,三种传值结构是完全并行,可以多次使用,但是不能够嵌套。Lab0031模块产生的输出值,通过中间变量out1传递到assign语句中,参与处理。
    endmodule
    module lab0031(a,out);//被调用子模块
    input[2:0] a;
    output[1:0] out;//注意此处为什么为2位。
    assign out=a[0]+a[1]+a[2];//注意此处为位选择方式,可以对多位变量a进行逐位访问。
    endmodule

    (4)2位加法器,ina,inb为两个2位的操作数,sum为相加的和,count为进位。2位加法器 四种不同的实现方法,注意对比.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    module add(ina,inb,sum,count);
    input[1:0] ina,inb;
    output[1:0] sum;
    output count;
    wire[2:0] sum_temp;
    assign sum_temp=ina+inb;
    assign sum=sum_temp[1:0];
    //或assign sum=ina+inb;
    assign count=sum_temp[2];
    endmodule

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    module add (ina,inb,sum,count);
    input[1:0] ina,inb;
    output reg[1:0] sum;//注意不同
    output reg count;//注意不同
    reg[2:0] sum_temp;//注意不同
    always@(ina,inb)//组合逻辑用ina、inb电平形式作为驱动信号
    begin
    sum_temp=ina+inb;
    sum=sum_temp[1:0];//或 sum=ina+inb;
    count=sum_temp[2];
    endmodule

    1
    2
    3
    4
    5
    6
    7
    8
    9
    module add (ina,inb,sum,count);
    input[1:0] ina,inb;
    output reg[1:0] sum;
    output reg count;
    always@(ina,inb)
    begin
    {count,sum}=ina+inb;
    endmodule

    1
    2
    3
    4
    5
    6
    7
    module add (ina,inb,sum,count);
    input[1:0] ina,inb;
    output[1:0] sum;
    output count;
    assign {count,sum}=ina+inb;//{ }为位拼接运算符,可以实现二进制数据、参量的拼接
    endmodule

    (5)带优先级8-3编码器和3-8译码器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 带优先级8-3编码器
    module code83(in8,out3);
    input[7:0] in8; output reg[2:0] out3;
    always@(in8)
    begin
    case(in8)
    if(in8[7]) out3=3'b111;
    else if(in8[6]) out3=3'b110;
    else if(in8[5]) out3=3'b101;
    else if(in8[4]) out3=3'b100;
    else if(in8[3]) out3=3'b011;
    else if(in8[2]) out3=3'b010;
    else if(in8[1]) out3=3'b001;
    else if(in8[0]) out3=3'b000;
    else out3=3'bxxx;
    endcase
    end
    endmodule

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 3-8译码器
    module decode38(in3,out8);
    input[2:0] in3; output[7:0] out8;
    always@(in3)
    begin
    case(in3)
    3'd0:out=8'b00000001;
    3'd1:out=8'b00000010;
    3'd2:out=8'b00000100;
    3'd3:out=8'b00001000;
    3'd4:out=8'b00010000;
    3'd5:out=8'b00100000;
    3'd6:out=8'b01000000;
    3'd7:out=8'b10000000;
    default:out=8'bxxxxxxxx;
    endcase
    end
    endmodule

实验内容

  1. 阅读实验原理参考代码,掌握不同代码风格的描述方式。
  2. 组合电路设计并测试,参照lab001、lab002、lab003三种不同的设计方式,设计一个实现10裁判电路设计,并设计测试文件进行测试,查看测试结果是否符合逻辑要求。每个裁判同意或不同意,裁判结果分为通过(同意人数多)、不通过(不同意人数多)、待定(同意与不同意相等)。建议使用quartus和Iverilog两种调试和测试工具,测试信号通过monitor或display文本显示。
  3. 时序电路设计并测试,设计一个模24的计数器。具有高电平的异步复位信号rst、同步置数信号load、上升沿触发时钟clk,置数数输入data,输出计数值sum和进位值cont。测试信号通过monitor或display文本显示。
  4. 按照要求2、3中的描述,设计模块代码和测试代码,利用quartus或iverilog进行综合和测试。在文件代码设计、综合、调试过程中,总结错误原因,掌握错误定位和改进的方法。

实验要求

  1. 按照上面的提示完善报告
  2. 将程序编译过程中出现的主要错误及解决方案进行总结
  3. 掌握和练习数字系统的分析步骤,并将一些核心步骤进行记录
  4. 将编写的程序与仿真结果进行记录