조합회로
순서회로
플립플롭
f(A,B,C)=Σm(0,1,5,7)
입력 A,B,C 중에 출력 (0,1,5,7)이 1

베릴로그는 c언어의 연산자들을 대부분 쓸수있지만 증감 연산자는 쓸수없다
베릴로그로 만든 파일을 FPGA칩에 Generate Bitstream을 이용해서 보냄
if문같은 경우 {}대신 begin end로 묶는데 실행문이 1문장이면 생략가능하고, if-else문은 ';'은 두개 들어가지만 세트로 1문장으로 친다
if() //begin //begin end 생략 가능
if() ~~;
else ~~;
//end
https://www.slideserve.com/iliana-sharpe/counter


T플립플롭으로 사용
A는 클락 때마다 토글
B는 클락 때마다와 A가 1일때 토글
FPGA에는 lut과 D플립플롭만 있음
비바도에 있는 덧셈기 사용
회로도 대로 만들면 T플립플롭만들고 and게이트를 만들어야 하고 그에따른 lut도 따로 사용해야함
module up_counter_p(
input clk, reset_p, enable,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else if(enable)count = count +1;
end
endmodule
module up_counter_n(
input clk, reset_p, enable,
output reg [3:0] count);
always @(negedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else if(enable)count = count +1;
end
endmodule
리셋으로 초기화 하지 않으면 unkown 상태로, unkown상태에서 1을 더하든 뭘 하든 unkown상태이다
enable값은 1을 줘서 항상 동작할수있게 함
reset_p의 값에 1을 줘서 리셋 초기화

reset_p에 다시 0주고 (리셋 종료)

module down_counter_p(
input clk, reset_p, enable,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else if(enable)count = count - 1;
end
endmodule
module down_counter_p(
input clk, reset_p, enable,
output reg [3:0] count);
always @(negedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else if(enable)count = count - 1;
end
endmodule
리셋 한번 하고

리셋 다시0 주고 하강엣지에서 동작

2진화 10진수
10진수 각 자리수를 2진수로 표현(표현은 되지만 BCD코드로 계산은 하면 안됨)
enable입력을 만들지 않아도 회로에 자동으로 생성되고 기본 1값으로 설정
module bcd_upcounter_p(
input clk, reset_p,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else begin
if(count >= 9)count = 0;
else count = count +1;
end
end
endmodule
초기화 한번 한 후에

버전1
module bcd_downcounter_p(
input clk, reset_p,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else begin
if(count <= 0)count = 9;
else count = count -1;
end
end
endmodule
초기화 한번 한 후에

버전2
리셋값을 9로 설정
처음 시작을 9부터 시작해서 다운 카운트
module bcd_downcounter_p(
input clk, reset_p,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 9;
else begin
if(count <= 0)count = 9;
else count = count -1;
end
end
endmodule

module bcd_downcounter_p(
input clk, reset_p,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 9;
else begin
if(count >= 10 | count == 0)count = 9; //0보다 작을순없어서 '=='가능 하지만 4비트에서 10보다 큰 수가 나올수도있음(하드웨어적인 오류 등에있어서)
else count = count -1;
end
end
endmodule
module up_downcounter_p(
input clk, reset_p,
input up_down,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else begin
if(up_down)begin
count = count + 1;
end
else begin
count = count -1;
end
end
end
endmodule
동기식 BCD 업/다운 카운터
초기화 0으로 한번 한 뒤
up_down이 1이면 업 카운터로 동작, up_down이 0이면 다운 카운터로 동작
module bcd_up_downcounter_p(
input clk, reset_p,
input up_down,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p) count = 0;
else begin
if(up_down)begin
count = count + 1; //실행 순서 주의
if(count > 9) count = 0; //위아랫줄이 바뀌었으면 9나0에 1이 더해지고 출력되서 값이 건너 뛰어질 수 있음
end
else begin
count = count -1;
if(count == 0 | count >= 10) count = 9;
end
end
end
endmodule

베릴로그는 병렬적으로 동작한다 c언어처럼 순차적으로 동작하는 것을 구현할때 링 카운터 사용이 유용함
module ring_counter(
input clk, reset_p,
output reg [3:0] q);
always @(posedge clk, posedge reset_p)begin
if(reset_p) q=4'b0001;
else begin
case(q) //q의 변화가 감지 되었을 때 동작 //순차적으로 계속 변하게됨
4'b0001: q = 4'b0010; //q값이 0001이면 0010으로
4'b0010: q = 4'b0100; //q값이 0010이면 0100으로
4'b0100: q = 4'b1000; //q값이 0100이면 1000으로
4'b1000: q = 4'b0001; //q값이 1000이면 0001으로
default: q = 4'b0001; //q값이 그 외의 값이면 0001으로
endcase
end
end
endmodule

module ring_counter(
input clk, reset_p,
output reg [3:0] q);
always @(posedge clk or posedge reset_p)begin
if(reset_p)q=4'b0001;
else begin
if(q == 4'b1000)q=4'b0001;
else q=q<<1;
end
end
// always @(posedge clk, posedge reset_p)begin
// if(reset_p) q=4'b0001;
// else begin
// case(q)
// 4'b0001: q = 4'b0010;
// 4'b0010: q = 4'b0100;
// 4'b0100: q = 4'b1000;
// 4'b1000: q = 4'b0001;
// default: q = 4'b0001;
// endcase
// end
// end
endmodule


쉬프트 회로
쉬프트 연산 없이 배선만으로 만들기
{}결합 연산자를 통해 q=0001에서 001을 떼오고 1'b0을 맨 오른쪽에 붙여서 q=0010만듬, 클럭마다 반복
module ring_counter(
input clk, reset_p,
output reg [3:0] q);
always @(posedge clk or posedge reset_p)begin
if(reset_p)q=4'b0001;
else begin
if(q == 4'b1000)q=4'b0001;
else q[3:0] = {q[2:0], 1'b0}; //q가 4비트짜리라 else q = {q[2:0], 1'b0}도 가능
//else q=q<<1;
end
end
// always @(posedge clk, posedge reset_p)begin
// if(reset_p) q=4'b0001;
// else begin
// case(q)
// 4'b0001: q = 4'b0010;
// 4'b0010: q = 4'b0100;
// 4'b0100: q = 4'b1000;
// 4'b1000: q = 4'b0001;
// default: q = 4'b0001;
// endcase
// end
// end
endmodule

쉬프트 연산자 사라짐

출력값 0001일때 mux의 신호선과 입력선에들어가서 0010으로 다시 출력
시스템 클락의 1주기 동안만 High 되어있는 펄스 클락
always 감지 변수에 버튼 클럭 상승 엣지를 만들어서 안넣는 이유는 언제 버튼 상승엣지가 들어올지 몰라서 pdt계산, 타이밍 계산이 안되서 문법적으로는 가능하지만 안 넣어야 한다.


module edge_detector_p(
input clk, reset_p,
input cp,
output p_edge);
reg ff_cur, ff_old;
always @(posedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur=0;
ff_old=0;
end
else begin
ff_old = ff_cur; //어떤게 먼저 실행되느냐에 따라 다름 //순서대로 처리
ff_cur = cp; //병렬처리 사진
//ff_old = ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
endmodule
cp, ff_cur, ff_old의 잘못된 순서
module edge_detector_p(
input clk, reset_p,
input cp,
output p_edge);
reg ff_cur, ff_old;
always @(posedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur=0;
ff_old=0;
end
else begin
//ff_old = ff_cur; //어떤게 먼저 실행되느냐에 따라 다름 //순서대로 처리
ff_cur = cp; //병렬처리 사진
ff_old = ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
endmodule

바꾼 순서
module edge_detector_p(
input clk, reset_p,
input cp,
output p_edge);
reg ff_cur, ff_old;
always @(posedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur=0;
ff_old=0;
end
else begin
ff_old = ff_cur; //어떤게 먼저 실행되느냐에 따라 다름 //순서대로 처리
ff_cur = cp; //병렬처리 사진
//ff_old = ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
endmodule

always문과 assign문은 병렬적으로 처리되며 서로 즉시 영향을 주지만, 델타사이클에의해 대부분은 always문 내의 모든 문장이 처리되면 assign문에 영향을 준다고 생각하면된다.
병렬처리

순서대로 처리

(대입연산자)블럭킹문 (<=연산자)넌블럭킹문
always문에서는 순서대로 실행
module edge_detector_p(
input clk, reset_p,
input cp,
output p_edge);
reg ff_cur, ff_old;
always @(posedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur<=0;
ff_old<=0;
end
else begin
ff_cur <= cp;
ff_old <= ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
endmodule
결과

cp(버튼)의 신호가 들어왔을때 ff_cur, ff_old의 신호 차이에 의해 한 클락의 P_edge 발생
베릴로그는 기본적으로 병렬 처리 언어이다. 이는 하드웨어의 동시성을 모델링하기 위함.
하지만 예외가 있다