6-4. 실습: 시프트 레지스터 설계
1. 시프트 레지스터 소개
시프트 레지스터(Shift Register)는 디지털 회로 설계에서 매우 기본적인 구성 요소 중 하나입니다. 여러 개의 플립플롭(Flip-Flop)을 직렬로 연결하여 데이터를 저장하고, 클럭 신호에 따라 데이터를 한 비트씩 이동시키는 기능을 수행합니다. 이러한 특성 때문에 시프트 레지스터는 데이터 직렬화(serialization), 데이터 병렬화(parallelization), 데이터 지연(delay), 데이터 변환 등 다양한 응용 분야에서 핵심적인 역할을 합니다.
시프트 레지스터는 마치 기차와 같습니다. 각 플립플롭은 기차의 객차에 비유할 수 있으며, 데이터는 기차에 탑승한 승객에 해당합니다. 클럭 신호는 기차의 기관사이며, 클럭 펄스마다 승객(데이터)을 다음 객차(플립플롭)로 이동시킵니다.

위 그림은 4비트 시프트 레지스터의 기본적인 구조를 보여줍니다. 각 플립플롭은 데이터를 저장하고, 클럭 신호의 상승 또는 하강 에지에서 이전 플립플롭의 출력을 자신의 입력으로 받습니다. Serial In은 시프트 레지스터에 데이터를 입력하는 데 사용되며, Q0, Q1, Q2, Q3는 각 플립플롭의 출력을 나타냅니다.
2. 시프트 레지스터의 동작 원리
시프트 레지스터의 동작은 각 플립플롭의 동작과 클럭 신호에 의해 결정됩니다. 일반적으로 시프트 레지스터는 클럭 신호의 상승 또는 하강 에지에서 데이터를 이동시킵니다.
1) 직렬 입력, 직렬 출력 (SISO)
가장 기본적인 형태의 시프트 레지스터는 직렬 입력, 직렬 출력(Serial-In, Serial-Out, SISO)입니다. Serial In 핀을 통해 데이터를 입력하고, 마지막 플립플롭의 출력을 통해 데이터를 출력합니다.
- 클럭 펄스 1:
Serial In의 데이터가 첫 번째 플립플롭으로 이동합니다. - 클럭 펄스 2: 첫 번째 플립플롭의 데이터가 두 번째 플립플롭으로 이동하고,
Serial In의 새로운 데이터가 첫 번째 플립플롭으로 이동합니다. - 이러한 과정이 반복되면서 데이터는 시프트 레지스터를 통해 이동합니다.
2) 직렬 입력, 병렬 출력 (SIPO)
직렬 입력, 병렬 출력(Serial-In, Parallel-Out, SIPO) 시프트 레지스터는 Serial In을 통해 데이터를 입력하고, 각 플립플롭의 출력을 병렬로 출력합니다. 이를 통해 직렬 데이터를 병렬 데이터로 변환할 수 있습니다. 각 플립플롭의 출력을 개별적으로 접근할 수 있으므로, 시프트 레지스터에 저장된 데이터를 한 번에 읽을 수 있습니다.
3) 병렬 입력, 직렬 출력 (PISO)
병렬 입력, 직렬 출력(Parallel-In, Serial-Out, PISO) 시프트 레지스터는 병렬 데이터를 입력하고, 직렬로 데이터를 출력합니다. 병렬 입력 핀을 통해 데이터를 입력하고, 클럭 신호에 따라 마지막 플립플롭의 출력을 통해 데이터를 출력합니다. 이러한 구조는 병렬 데이터를 직렬 데이터로 변환하는 데 사용됩니다.
4) 병렬 입력, 병렬 출력 (PIPO)
병렬 입력, 병렬 출력(Parallel-In, Parallel-Out, PIPO) 시프트 레지스터는 병렬 데이터를 입력하고, 병렬로 데이터를 출력합니다. 이는 데이터를 단순히 저장하고, 필요에 따라 접근하는 데 사용됩니다.
3. Verilog를 이용한 시프트 레지스터 설계
Verilog는 하드웨어 기술 언어(HDL)로, 디지털 회로를 모델링하고 시뮬레이션하는 데 사용됩니다. 시프트 레지스터를 Verilog로 설계하는 것은 순차 논리 회로 설계를 이해하는 좋은 연습입니다.
1) SISO 시프트 레지스터 설계
SISO 시프트 레지스터는 가장 간단한 형태의 시프트 레지스터입니다. 다음은 4비트 SISO 시프트 레지스터의 Verilog 코드 예시입니다.
module shift_register_siso (
input logic clk,
input logic rst,
input logic serial_in,
output logic serial_out
);
parameter SIZE = 4; // 레지스터의 비트 수
logic [SIZE-1:0] shift_reg;
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
shift_reg <= 0;
end else begin
shift_reg <= {serial_in, shift_reg[SIZE-1:1]};
end
end
assign serial_out = shift_reg[0];
endmodule
module shift_register_siso: 모듈의 선언입니다.input logic clk, rst, serial_in: 클럭, 리셋, 직렬 입력 신호를 정의합니다.output logic serial_out: 직렬 출력 신호를 정의합니다.parameter SIZE = 4: 시프트 레지스터의 비트 수를 정의합니다. 이 값을 변경하여 레지스터의 크기를 쉽게 조절할 수 있습니다.logic [SIZE-1:0] shift_reg: 시프트 레지스터의 내부 레지스터를 정의합니다.always_ff @(posedge clk or posedge rst): 플립플롭의 동작을 정의하는always_ff블록입니다.posedge clk는 클럭의 상승 에지를,posedge rst는 리셋 신호의 상승 에지를 의미합니다.if (rst): 리셋 신호가 활성화되면shift_reg을 0으로 초기화합니다.shift_reg <= {serial_in, shift_reg[SIZE-1:1]}: 클럭의 상승 에지에서serial_in의 값을shift_reg의 최상위 비트로 이동시키고, 나머지 비트들은 한 비트씩 오른쪽으로 시프트합니다. 이 연산은concatenation연산자{}를 사용하여 구현됩니다.assign serial_out = shift_reg[0]:shift_reg의 최하위 비트를serial_out에 할당합니다.
2) SIPO 시프트 레지스터 설계
SIPO 시프트 레지스터는 직렬 데이터를 입력받아 병렬로 출력하는 역할을 합니다. 다음은 4비트 SIPO 시프트 레지스터의 Verilog 코드입니다.
module shift_register_sipo (
input logic clk,
input logic rst,
input logic serial_in,
output logic [3:0] parallel_out
);
logic [3:0] shift_reg;
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
shift_reg <= 0;
end else begin
shift_reg <= {serial_in, shift_reg[3:1]};
end
end
assign parallel_out = shift_reg;
endmodule
이 코드에서 parallel_out은 4비트의 출력을 나타내며, shift_reg의 각 비트가 병렬로 출력됩니다.
3) PISO 시프트 레지스터 설계
PISO 시프트 레지스터는 병렬 데이터를 입력받아 직렬로 출력합니다. 다음은 4비트 PISO 시프트 레지스터의 Verilog 코드입니다.
module shift_register_piso (
input logic clk,
input logic rst,
input logic [3:0] parallel_in,
output logic serial_out
);
logic [3:0] shift_reg;
logic internal_serial_out;
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
shift_reg <= 0;
end else begin
shift_reg <= parallel_in;
end
end
always_ff @(posedge clk) begin
internal_serial_out <= shift_reg[3];
shift_reg <= {shift_reg[2:0], 1'b0};
end
assign serial_out = internal_serial_out;
endmodule
이 코드에서 parallel_in은 4비트의 입력을 나타내며, serial_out은 직렬 출력을 나타냅니다. shift_reg에 parallel_in의 값이 로드되고, 클럭마다 shift_reg의 내용이 오른쪽으로 시프트됩니다.
4) PIPO 시프트 레지스터 설계
PIPO 시프트 레지스터는 병렬 데이터를 입력받아 병렬로 출력합니다. 다음은 4비트 PIPO 시프트 레지스터의 Verilog 코드입니다.
module shift_register_pipo (
input logic clk,
input logic rst,
input logic [3:0] parallel_in,
output logic [3:0] parallel_out
);
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
parallel_out <= 0;
end else begin
parallel_out <= parallel_in;
end
end
endmodule
이 코드에서는 입력된 병렬 데이터(parallel_in)를 클럭 또는 리셋 신호에 따라 parallel_out으로 바로 전달합니다.
4. 시프트 레지스터의 응용
시프트 레지스터는 다양한 응용 분야에서 활용됩니다.
1) 데이터 직렬화 및 병렬화
SIPO 시프트 레지스터는 병렬 데이터를 직렬 데이터로 변환하는 데 사용됩니다. 이는 데이터를 전송하거나 저장할 때 데이터 전송 라인의 수를 줄여 효율성을 높이는 데 유용합니다. PISO 시프트 레지스터는 반대로 직렬 데이터를 병렬 데이터로 변환하는 데 사용됩니다.
2) 데이터 지연
시프트 레지스터는 데이터를 특정 시간 동안 지연시키는 데 사용될 수 있습니다. 각 플립플롭이 데이터를 한 클럭 사이클만큼 지연시키기 때문에, 시프트 레지스터의 비트 수에 따라 전체 지연 시간을 조절할 수 있습니다.
3) 주파수 분주기
시프트 레지스터는 클럭 신호의 주파수를 분주하는 데 사용될 수 있습니다. 특정 비트의 출력을 클럭 신호로 사용함으로써, 원래 클럭 신호의 주파수를 분주할 수 있습니다.
4) 메모리
시프트 레지스터는 간단한 형태의 메모리로 사용될 수 있습니다. 데이터를 저장하고, 필요에 따라 읽을 수 있습니다.
5. 설계 시 고려 사항 및 트러블슈팅
1) 클럭 도메인
시프트 레지스터 설계 시, 클럭 도메인 문제를 고려해야 합니다. 여러 개의 클럭 도메인을 사용하는 경우, 데이터 전송 시 동기화 문제를 해결해야 합니다.
2) 레이스 컨디션
레이스 컨디션(Race condition)은 여러 신호가 동시에 변경될 때 발생할 수 있는 문제로, 시뮬레이션 결과와 실제 동작의 차이를 발생시킬 수 있습니다. Verilog 코드에서 플립플롭의 동작을 정확하게 모델링하고, 레이스 컨디션을 피하기 위해 신중하게 코드를 작성해야 합니다.
3) 타이밍 분석
시프트 레지스터의 타이밍은 설계의 중요한 부분입니다. 클럭 주파수, 플립플롭의 설정 시간(setup time) 및 홀드 시간(hold time)을 고려하여 설계해야 합니다. 타이밍 분석 도구를 사용하여 타이밍 문제를 확인하고 해결할 수 있습니다.
4) 테스트벤치
시프트 레지스터를 설계한 후에는 반드시 테스트벤치를 사용하여 기능을 검증해야 합니다. 테스트벤치는 입력 신호를 생성하고, 출력 신호를 예상 값과 비교하여 올바르게 동작하는지 확인합니다.
6. 결론
시프트 레지스터는 디지털 회로 설계의 기본이며, 다양한 응용 분야에서 중요한 역할을 합니다. Verilog를 사용하여 시프트 레지스터를 설계하고 시뮬레이션하는 실습을 통해 순차 논리 회로 설계에 대한 이해를 높일 수 있습니다. 본 문서에서 제시된 SISO, SIPO, PISO, PIPO 시프트 레지스터 설계 예시를 참고하여, 실제 프로젝트에 적용해 보시기 바랍니다.
비슷한 글 추천
1-2. 디지털 시스템 설계 과정
Verilog를 이용한 디지털 시스템 설계의 전반적인 과정을 설명합니다. 설계, 시뮬레이션, 합성, 검증 단계를 소개합니다.
7-1. Verilog의 유한 상태 기계(FSM) 설계
유한 상태 기계의 개념과 Verilog를 이용한 FSM 설계 방법을 설명합니다. Moore 및 Mealy 머신을 다룹니다.
7-2. FSM 설계 예제: 시퀀스 감지기
시퀀스 감지기를 설계하는 예제를 통해 FSM 설계 과정을 실습합니다. 상태 다이어그램 및 Verilog 코드를 작성합니다.
3-1. Verilog의 구문 (Statement) - if-else 구문
Verilog의 제어 흐름 구문인 if-else 문을 설명하고, 조건에 따른 동작 제어 방법을 익힙니다. 예제와 함께 실습합니다.
Comments (0)
No comments yet. Be the first to comment!
Please to write a comment.