FPGA에서의 LFSR – VHDL & Verilog 코드 선형 피드백 시프트 레지스터가 FPGA 내부에서 작동하는 원리 LFSR은 Linear Feedback Shift Register(선형 피드백 시프트 레지스터)의 약자로, FPGA 내부에서 유용한 설계입니다. LFSR은 합성하기 간단하여 상대적으로 적은 리소스를 사용하며 FPGA 내부에서 매우 높은 클럭 속도로 실행할 수 있습니다. LFSR 사용으로 이득을 보는 애플리케이션은 많습니다: 카운터(Counters) 테스트 패턴 생성기(Test Pattern Generators)
설계 module single_port_sync_ram #( parameter ADDR_WIDTH = 4, parameter DATA_WIDTH = 32, parameter DEPTH = 16 )( input clk, input [ADDR_WIDTH-1:0] addr, inout [DATA_WIDTH-1:0] data, input cs, input we, input oe ); reg [DATA_WIDTH-1:0] tmp_data; reg [DATA_WIDTH-1:0] mem [DEPTH];
가산기는 두 숫자의 덧셈을 수행하는 디지털 구성요소입니다. 프로세서의 ALU 내부 주요 구성요소이며 주소 증가, 테이블 인덱스, 버퍼 포인터 등 덧셈이 필요한 많은 곳에서 사용됩니다. 풀 가산기는 다른 입력 이진수들과 함께 캐리 입력을 더해 합(sum)과 캐리 출력(carry output)을 생성합니다. 진리표 A B Cin Cout Sum 00000 00101 01001 01110 10001 10110 11010 11111 설계 아래는 두 이진수를
멀티플렉서(mux)란? 멀티플렉서 또는 줄여서 mux는 선택 신호에 따라 N개의 입력 중 하나의 데이터를 출력으로 전달하는 디지털 소자입니다. 아래 사례는 N이 4인 경우입니다. 예를 들어 4비트 멀티플렉서는 각각 4비트인 N개의 입력을 가지며, 선택 신호를 사용하여 각 입력을 출력 핀 out으로 보낼 수 있습니다. sel은 2비트 입력으로 네 가지 값을 가질 수 있습니다. 선택 라인의 각 값은 입력 중 하나가 출력 핀 out으로 전송되도록 허용합니다. sel a b c d out 0 3 7 1 9 3 1 3 7 1
설계 module pr_en ( input [7:0] a, input [7:0] b, input [7:0] c, input [7:0] d, input [1:0] sel, output reg [7:0] out ); always @ (a or b or c or d or sel) begin if (sel == 2b00) out <= a; else if (sel == 2b01) out <= b; else if (sel == 2b10) out <= c; else out <= d; en
디지털 전자공학에서 시프트 레지스터는 한 플롭의 출력 핀 q가 다음 플롭의 데이터 입력 핀(d)에 연결된 플립플롭의 캐스케이드입니다. 모든 플롭이 같은 클럭으로 동작하므로 시프트 레지스터에 저장된 비트 배열이 한 위치씩 시프트됩니다. 예를 들어, 초기값이 10110인 5비트 우측 시프트 레지스터의 입력이 0으로 연결되면 다음 패턴은 01011, 그 다음은 00101이 됩니다. 설계 이 시프트 레지스터 설계는 다섯 개의 입력과 하나의 n비트 출력을 가지며, parameter MSB를 사용하여 시프트 레지스터의 폭을 나타냅니다.
설계 module gray_ctr #( parameter N = 4 ) ( input clk, input rstn, output reg [N-1:0] out ); reg [N-1:0] q; always @ (posedge clk) begin if (!rstn) begin q <= 0; out <= 0; end else begin q <= q + 1; `ifdef FOR_LOOP for (int i = 0; i < N-1; i = i +
설계 module modN_ctr #( parameter N = 10, parameter WIDTH = 4 ) ( input clk, input rstn, output reg[WIDTH-1:0] out ); always @ (posedge clk) begin if (!rstn) begin out <= 0; end else begin if (out == N-1) out <= 0; else out <= out + 1; end end endmodule 테스트
설계 module johnson_ctr #(parameter WIDTH=4) ( input clk, input rstn, output reg [WIDTH-1:0] out ); always @ (posedge clk) begin if (!rstn) out <= 1; else begin out[WIDTH-1] <= ~out[0]; for (int i = 0; i < WIDTH-1; i = i + 1) begin out[i] <= out[i+1]; end
설계 module ring_ctr #(parameter WIDTH=4) ( input clk, input rstn, output reg [WIDTH-1:0] out ); always @ (posedge clk) begin if (!rstn) out <= 1; else begin out[WIDTH-1] <= out[0]; for (int i = 0; i < WIDTH-1; i = i + 1) begin out[i] <= out[i+1]; end en
리플 카운터는 첫 번째를 제외한 모든 플롭이 앞선 플롭의 출력으로 클럭되는 비동기 카운터입니다. 설계 module dff ( input d, input clk, input rstn, output reg q, output qn ); always @ (posedge clk or negedge rstn) if (!rstn) q <= 0; else q <= d; assign qn = ~q; endmodule module ripple ( input clk, input rstn, out
4비트 카운터는 4b0000에서 4h1111까지 증가하다가 다시 4b0000으로 롤오버합니다. 실행 중인 클럭이 제공되고 리셋이 하이 상태로 유지되는 한 계속 카운트합니다. 롤오버는 최종 덧셈의 최상위 비트(MSB)가 버려질 때 발생합니다. 카운터가 최대값 4b1111에 있을 때 카운트 요청을 한 번 더 받으면 5b10000에 도달하려 하지만 4비트만 지원하므로 MSB가 버려져 0이 됩니다. 0000 0001 0010 ... 1110 1111 rolls over 0000 0001 ... 설계에는 클럭용 입력 하나와 액티브
플립플롭은 클럭의 양성 또는 음성 에지에서 입력 데이터를 캡처합니다. 중요한 점은 클럭 에지 이후 다음 클럭 에지까지 데이터에 무슨 일이 일어나든 출력에 반영되지 않는다는 것입니다. 반면 래치는 클럭 에지에서 캡처하지 않고, 인에이블 핀이 어서트되는 동안 출력이 입력을 따릅니다. 설계 이 예제에서는 세 개의 입력과 한 개의 출력을 가진 래치를 만듭니다. 입력 d는 0 또는 1이 될 수 있는 데이터를 나타내고, rstn은 액티브 로우 리셋, en은 입력 데이터가 출력으로 래치되도록 하는 인에이블입니다. 액티브 로우 리셋은 이 입력이
설계 module tff ( input clk, input rstn, input t, output reg q ); always @ (posedge clk) begin if (!rstn) q <= 0; else if (t) q <= ~q; else q <= q; end endmodule 테스트벤치 module tb; reg clk; reg rstn; reg t; tff u0 ( .clk(clk), .rstn(rstn), .t(t), .q(q)
D 플립플롭은 클럭의 주어진 에지에서 입력 핀 d를 따르는 순차 소자입니다. 설계 #1: 비동기 액티브 로우 리셋 module dff ( input d, input rstn, input clk, output reg q ); always @ (posedge clk or negedge rstn) if (!rstn) q <= 0; else q <= d; endmodule 하드웨어 회로도 테스트벤치 module tb_dff; reg clk; reg d; reg rstn; reg [2:0
설계 module jk_ff ( input j, input k, input clk, output q ); reg q; always @ (posedge clk) case ({j,k}) 2b00 : q <= q; 2b01 : q <= 0; 2b10 : q <= 1; 2b11 : q <= ~q; endcase endmodule 하드웨어 회로도 테스트벤치 module tb_jk; reg j; reg k; reg clk; always
가장 간단한 예제로 시작하는 것이 가장 좋으며, Hello World!만큼 좋은 예제는 없습니다. // 한 줄 주석은 //로 시작 // Verilog 코드는 항상 모듈 안에 작성되며, 각 모듈은 특정 기능을 가진 디지털 블록을 나타냄 module tb; // initial 블록은 시뮬레이션을 위해 신호 넷과 변수를 초기화하는 데 주로 사용되는 구조 initial // Verilog는 설계자가 회로의 문제를 디버깅할 수 있도록 신호 값을 화면에 표시하는 기능 지원 // 여기서는 단순히 Hello World 출력
Verilog는 파일을 열고, 파일에 값을 출력하고, 파일에서 값을 읽어 변수에 저장하고, 파일을 닫는 시스템 태스크와 함수를 제공합니다. 파일 열기와 닫기 module tb; // 파일 핸들러를 저장할 변수 선언 integer fd; initial begin // my_file.txt라는 새 파일을 쓰기 권한으로 열고 // 파일 핸들러 포인터를 변수 fd에 저장 fd = $fopen(my_file.txt, w); // fd가 가리키는 파일 핸들 닫기 $fclose(fd
기본 타임스케일 (Default Timescale) Verilog 모듈은 모듈 전에 timescale이 정의되어 있을 것으로 예상되지만, 시뮬레이터는 기본 timescale을 삽입할 수 있습니다. Verilog 엘리보레이트된 계층 구조에서 어떤 범위든 적용되는 실제 timescale은 $printtimescale 시스템 태스크로 출력할 수 있으며, 이는 범위를 인자로 받습니다. module tb; initial begin // 이 모듈의 timescale 출력 $printtimescale(tb); // $
Verilog timescale 지시자는 시뮬레이션의 시간 단위와 정밀도를 지정합니다. Verilog $timeformat 시스템 함수는 $display와 $strobe 같은 디스플레이 문장에서 %t 포맷 지정자의 보고 스타일을 지정합니다. 문법 $timeformat(<unit_number>, <precision>, <suffix_string>, <minimum field width>); unit_number는 소스 코드에서 사용된 모든 `timescale 지시자 중 가장 작은
verilog