Verilog和数字电路

HDL、EDA和FPGA

  • HDL(Hardware Description Language,硬件描述语言)
    • 描述数字电路,比如Verilog
  • EDA(Electronic Design Automation,电子设计自动化)
    • 将HDL编译为数字电路的门级网表,比如Intel Quartus Prime Lite Edition
  • FPGA(Field Programmable Gate Array,现场可编程门阵列)
    • 数字电路的门级网表的物理实现,比如Intel DE10-Lite
  • Intel DE10-Lite的物理资源
    • 下方 –> 6个七段数码管、10个开关、10个LED
    • 右侧 –> 2个按钮
    • 我们需要使用有限的物理资源,实现数字电路的功能

Intel DE10-Lite

七段数码管显示十六进制数

  • Verilog和物理资源
    • HEX[7:0]
      • 8位二进制数 –> 1个七段数码管、1个小数点
      • HEX0~HEX5 –> 6个七段数码管、6个小数点
    • SW[9:0]
      • 10位二进制数 –> 10个开关
    • LEDR[9:0]
      • 10位二进制数 –> 10个LED
    • KEY[1:0]
      • 2位二进制数 –> 2个按钮
  • 七段数码管
    • 0~5 –> 从上方的短横开始,顺时针旋转
    • 6 –> 中间的短横
    • 7 –> 小数点
    • 置1不显示,置0显示
 _      0
|_|    561
|_|.   432 7
  • 七段数码管显示十六进制数
    • Verilog的模块
      • module、endmodule之间
      • input –> 输入为10个开关(SW)
      • output –> 输出为10个LED(LEDR)、1个七段数码管(HEX0)
    • Verilog的函数
      • function、endfunction之间
      • num[3:0] –> 输入为4位二进制数
      • digit[7:0] –> 输出为十六进制数的七段数码管表示
      • 它类似于编程语言的宏,而不是函数
    • Verilog的assign语句
      • 右边的端口,连接到左边的端口
      • 我们只使用了4个开关,即可表示1个十六进制数
// ----- Seven-Segment Display, Hexadecimal -----

// (SW) -> (LEDR, HEX0)
module TopLevel(SW, LEDR, HEX0);
    input [9:0] SW;
    output [9:0] LEDR;
    output [7:0] HEX0;

    // (num) -> (digit)
    function automatic [7:0] digit;
        input [3:0] num;

        case (num)
            0: digit = 8'b11000000;  // Display 0
            1: digit = 8'b11111001;  // Display 1
            2: digit = 8'b10100100;  // Display 2
            3: digit = 8'b10110000;  // Display 3
            4: digit = 8'b10011001;  // Display 4
            5: digit = 8'b10010010;  // Display 5
            6: digit = 8'b10000010;  // Display 6
            7: digit = 8'b11111000;  // Display 7
            8: digit = 8'b10000000;  // Display 8
            9: digit = 8'b10010000;  // Display 9
            10: digit = 8'b10001000;  // Display A
            11: digit = 8'b10000011;  // Display b
            12: digit = 8'b11000110;  // Display C
            13: digit = 8'b10100001;  // Display d
            14: digit = 8'b10000110;  // Display E
            15: digit = 8'b10001110;  // Display F
        endcase
    endfunction

    assign LEDR = SW;
    assign HEX0 = digit(SW[3:0]);
endmodule

Verilog的三种层级

  • 全加器,3个二进制数相加,求出和(Sum)、进位(Carry)
    • 门级
      • 指定逻辑门,比如and、or、xor
    • 数据流级
      • 指定逻辑运算,比如与(&)、或(|)、异或(^)
    • 行为级
      • 指定行为,比如加(+)、位联结({})
      • always @(…)语句
        • 括号中为敏感列表,比如星号(*)表示任意信号的改变
        • 当敏感列表中的事件发生时,执行语句块中的行为
    • wire变量类似于编程语言的局部变量,always语句的赋值变量必须为reg变量
// ----- Gate -----

// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
    input [9:0] SW;
    output [9:0] LEDR;

    wire AB, AC, BC;

    // Sum
    xor SumSig (LEDR[0], SW[0], SW[1], SW[2]);

    // Carry
    and (AB, SW[0], SW[1]);
    and (AC, SW[0], SW[2]);
    and (BC, SW[1], SW[2]);
    or CarrySig (LEDR[1], AB, AC, BC);
endmodule



// ----- Dataflow -----

// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
    input [9:0] SW;
    output [9:0] LEDR;

    // Sum 
    assign LEDR[0] = SW[0] ^ SW[1] ^ SW[2];

    // Carry
    assign LEDR[1] = SW[0] & SW[1] | SW[0] & SW[2] | SW[1] & SW[2];
endmodule



// ----- Behavior -----

// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
    input [9:0] SW;
    output [9:0] LEDR;

    reg sum, carry;

    // Sum
    assign LEDR[0] = sum;

    // Carry
    assign LEDR[1] = carry;

    always @(*)
        {carry, sum} = SW[0] + SW[1] + SW[2];
endmodule