ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Verilog 문법, 특징 요약
    전공/논리회로실험 2020. 6. 9. 18:06

    * 모든 사진 파일은 부경대학교 한영선 교수님의 PPT에서 발췌했습니다. 주소 : http://hpcl.pknu.ac.kr

    Verilog HDL는 C와 유사한, 회로를 다루는 프로그래밍 언어이다.

    전력이 공급됨과 동시에 모든 코드가 병렬로 수행된다. 코드를 짤 때 가장 많이 실수하는 부분이라고 한다.

    모듈(module)

    하나의 반도체 칩을 정의하는 것이 하나의 모듈에서 정해진다고 보면 된다.

    모듈은 입출력 포트가 정의되어 있어야 하고 이들간의 논리적인 관계도 정의된다.

    모듈 중 메인이 되는 모듈을 TOP 모듈이라고 한다. C에서의 main() 함수와 유사하다고 보면 된다.

    [7:0]은 8비트 배열을 선언하는 것이다.

    나도 처음에는 [0:7]로 표현하는 게 더 올바르다 생각했는데 이렇게 프로그래밍 되어있다니까 뭐.

    여러 번 하니까 익숙해졌다.

    아래는 모듈 내에서 변수를 선언할 때의 규칙이다.

    <Direction><Data Type><Size><portName>

    Direction

    input : 입력값을 받는 변수. input의 데이터타입은 무조건 wire다. reg가 될 수 없다.

    output : 출력값을 내는 변수.

    inout : 입출력. 안써도 내 수준에서는 모든 회로 설계 가능

    Data Type

    wire : 실제로 회로를 물리적으로 연결하는 타입

    reg : 데이터 저장 가능한 타입

    Size

    n비트일 때는 [n-1:0] 형식으로 지정한다.

    1비트일 때는 생략하면 된다. ex) input 포트 지정시 : input wire op1;

    portName

    이건 그냥 변수 명이고.

    코드를 보고 회로를 구성하거나, 회로를 보고 코드를 구성할 줄 알아야 한다.

    Vivado 툴에서 코드를 시뮬레이션 하기 위해서는 "Run Simulation"을 누르면 된다.

    Logic Value

    진수변환

    9'h1A3 을 이진수로 변환

    9'h1A3은 9비트짜리 16진수(h)값이 1A3임을 인식

    16진수는 0~15까지의 범위를 표현하고, 총 4비트로 표현가능하므로 각 자리를 4비트짜리 이진수로 변환한다.

    1 => 0001

    A => 1010

    3 => 0011

    이어붙이면 0001 1010 0011 이 된다.

    9비트짜리 이진수로 변환하는 것이므로 9'b를 먼저 쓴다.

    그리고 위의 12비트를 이어붙인다. 그러면 9'b000110100011 이 된다.

    여기서 표현한 비트 수는 12개인데 9비트를 표현해야 하므로 맨앞의 0 3개를 버린다.

    따라서 9'b110100011이 된다.

    9'h1A3 을 8진수로 변환

    먼저 이진수로 변환을 한다. 우리는 이미 그 값(9'b110100011)을 구했다.

    8진수는 0~7의 값을 한 자리에 표현할 수 있고, 이는 총 3비트로 표현할 수 있다(2^3 = 8).

    따라서 3비트당 8진수 1자리로 변환한다. 착각하지 않기 위해 각 자리를 3개씩 나눈다.

    9'b 110 100 011

    110 => 6

    100 => 4

    011 => 3

    가장 앞에 9비트를 8진수로 표현한 값을 명시하기 위해 9'o 를 붙이고 643을 이어붙인다.

    따라서 9'o643 이라는 값을 구할 수 있다.

    14'h3BX6 을 이진수로 변환

    설명은 위에 했으니 과정만 나타낸다.

    3 => 0011

    B => 1011

    X => XXXX (값이 알려지지 않았으므로 4비트를 모두 X로 표현하면 된다)

    6 => 0110

    따라서 14'b111011XXXX0110

    14'h3BX6 을 8진수로 변환

    설명은 위에 했으니 과정만 나타낸다. 14'b111011XXXX0110 을 8진수로 변환한다.

    3자리씩 나눠야하는데 14자리이므로 2개짜리 비트가 나오는데, 이럴 땐 가장 앞에 0을 붙여 계산하면 된다.

    14'b 011 101 1XX XX0 110

    011 => 3

    101 => 5

    1XX => X (값을 모르는 비트가 하나 이상있으면 8진수로 변환하더라도 값은 모르니까 X로)

    XX0 => X

    110 => 6

    따라서 14o'35XX6 이 된다.

    할당(=대입)

    출력변수의 데이터 타입이 wire인지, reg인지에 따라 할당하는 표현 방식이 달라진다.

    reg는 플립플롭을 사용하는데, 클럭이 필요하고 wire은 클럭이 필요없기 때문에 reg와 wire를 따로 사용하는 것이다.

    C가 wire 출력변수일 때, assign C = A + B; 를 사용한다.

    C가 reg 출력변수일 때는 아래와 같이 always 구문으로 감싼다.

    always@(*)

    begin

    C = A + B; // blocking일 때

    C <= A + B; // nonBlocking일 때

    end

    always, initial 키워드는 클럭과 관련이 있는데 우리는 simulation만 할 것이기 때문에 always만 쓸 예정이다.

    initial은 simulation에서 쓰지 않는다고 한다.

    blocking vs non blocking

    blocking은 병렬이 아닌 한 줄당 딜레이가 생기게 된다.

    non blocking은 두 문장이 동시에 수행된다. 즉, 병렬 실행이 된다.

    always 구문

    always @ (posedge clk): clock의 rising edge에서 표현식이 실행된다. clk값이 선언되어 있어야 한다.

    always @ (negedge clk): clock의 falling edge에서 표현식이 실행된다. clk값이 선언되어 있어야 한다.

    always @ (posedge clk or negedge nrst): clock의 rising edge에서 또는 nrst의 falling edge에서 표현식이 실행된다. clk, nrst 값이 선언되어 있어야 한다.

    always @ (a or b or c): a, b, c의 값이 변할 때 표현식이 실행된다. a, b, c값이 선언되어 있어야 한다.

    always @ (*): 모든 입력값이 변할 때 표현식이 실행된다.

    reg타입 변수에는 하나의 always block에만 값을 assign해야 된다.

    즉 여러 블럭에 동일한 변수가 들어갈 수는 있지만 하나의 변숭에 대한 대입은 하나의 block에서만 해야된다.

    논리 연산자

    Verilog에서는 0은 거짓, 그 외의 값은 무조건 참이다.

    ex) 3'b000 && 4'b0101 = 0 // 3'b000은 거짓, 4'b0101은 참

    ex) 3'b000 || 4'b0101 = 1

    ex) !3'b000 = 1

    Bitwise 연산자(비트 연산자)

    비트연산자이므로 피연산자는 무조건 2진수로 변환해서 계산한다.

    Bit Reduction 연산자

    피연산자는 하나만 있으면 된다. 연산자의 위치는 피연산자의 앞부분이며, 2진수 변환을 해야 한다.

    shift 연산자

    비트의 자리 수를 증가 또는 감소(2^n배 증가 또는 감소) 하는 연산자이다.

    Relational 연산자

    자주 쓰는 연산자인데 명칭이 관계 연산자인줄은 몰랐다 ㅋㅋ

    if문

    여러 줄일 땐 begin - end 로 묶어야하고, 반드시 always 문 안에서 사용해야 한다.

    special 연산자

    concatenation 연산자

    여러 값을 합쳐 하나의 값으로 만든다.

    ex) {5'b10101, 2'b01, 1'b1} = 8'b1010_1011

    conditional 연산자

    이것도 C에서 자주 봤는데 연산자의 명칭은 처음 알았다.

    형태는 <조건문> ? <출력문1> : <출력문2> 이렇게 사용하며, always 문 상관없이 사용할 수 있다.

    ex) out = cond ? 1'b1 : 1'b0 // cond 값이 1일 경우 out에 1'b1 값 저장, 0일 경우에는 1'b0 저장

    case 연산자

    반드시 always 블럭 안에서 사용가능하다!

    case (expression)

    value1: 식1;

    value2: 식2;

    ...

    default: 식n;

    endcase

    '전공 > 논리회로실험' 카테고리의 다른 글

    조합회로와 순차회로  (0) 2020.06.10

    댓글

Designed by Tistory.