Verilog always 블록으로 순차 논리 구현: JK 플립플롭, 카운터, 시프트 레지스터
always 블록은 순차 논리(메모리 요소 포함) 구현의 주력 도구입니다. 클럭 에지 기반 상태 업데이트 패턴을 마스터하세요.
JK 플립플롭
진리표: J=K=0 유지, J=0/K=1 리셋(0), J=1/K=0 세트(1), J=K=1 토글.
module jk_ff (input j, k, rstn, clk, output reg q);
always @(posedge clk or negedge rstn) begin
if (!rstn) q <= 0;
else q <= (j & ~q) | (~k & q); // JK 특성 방정식
end
endmodule
- 비동기 리셋:
negedge rstn 포함
- 비블로킹 할당(
<=) 필수
- 다음 상태 계산은 현재 상태
q 기반 (올바른 순차 동작)
테스트벤치 패턴
module tb;
reg j, k, rstn, clk; wire q;
always #10 clk = ~clk; // 클럭 생성
jk_ff u0 (.j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
initial begin
{j,k,rstn,clk} = 0; #10 rstn = 1;
repeat (10) begin
#($random) j = $random; #($random) k = $random;
end
#20 $finish;
end
endmodule
모듈로-10 카운터 (MOD-10 Counter)
0~9 카운트 후 롤오버. 4비트 레지스터 필요 (log2(10) ≈ 4).
module mod10_counter (input clk, rstn, output reg [3:0] out);
always @(posedge clk) begin
if (!rstn) out <= 0;
else if (out == 4'd9) out <= 0; // 9 다음 0
else out <= out + 1;
end
endmodule
파라미터화로 MOD-N 확장 가능: parameter N = 10; localparam W = $clog2(N);
4비트 좌측 시프트 레지스터
입력 d가 LSB로 들어오고 기존 비트들이 좌측 시프트.
module lshift_4b_reg (input d, clk, rstn, output reg [3:0] out);
always @(posedge clk) begin
if (!rstn) out <= 0;
else out <= {out[2:0], d}; // 결합으로 시프트 구현
end
endmodule
초기값 0011, d=0 입력 시: 0011 → 0110 → 1100 → 1000 → 0000 ...
순차 논리 설계 핵심 패턴
| 패턴 | 템플릿 |
| 동기 리셋 | always @(posedge clk) if (rst) q<=0; else q<=next; |
| 비동기 리셋 | always @(posedge clk or negedge rstn) if (!rstn) q<=0; else q<=next; |
| 동기 세트/리셋 | always @(posedge clk) if (rst) q<=0; else if (set) q<=1; else q<=next; |
| 이네이블 포함 | always @(posedge clk) if (en) q<=next; |
| 상태 머신 | always @(posedge clk) state <= next_state; always @(*) next_state = f(state, in); |
흔한 실수와 회피
- 블로킹 할당(
=) 사용: 순차 블록에서 비블로킹(<=) 필수
- 민감도 리스트에 클럭만: 비동기 리셋 시
negedge rstn 추가
- 조합/순차 혼용: 별도
always 블록으로 분리
- 리셋 미포함: 시뮬레이션 초기값
x 방지 위해 리셋 필수