1. BCD 코드란?
BCD(Binary Coded Decimal) 코드는 10진법 숫자를 2진법으로 표현하는 방식 중 하나이다. BCD 코드는 4비트(1자리수) 단위로 표현되며, 각 4비트는 0부터 9까지의 숫자를 나타낸다. 즉, 0000은 0, 0001은 1, 0010은 2, ..., 1001은 9를 나타낸다. 예를 들어, 105를 표현한다고 하면, 4비트씩 끊어서 2진수로 표현해야 한다.
105(dec) = 0001 0000 0101(bcd)
1 0 5
이렇게 된다는 것이다. 이쯤하고 다음 단계로 넘어가자.
2. 2진수를 BCD코드로 변환하는 Verilog 프로그램 코딩
2진수를 BCD코드로 구현하는 것이 매우 어려웠다. 이산수학이 필요한데, 일단 코드를 먼저 보고 왜 Always문에서 이러한 코드가 구현되었는지 사진으로 설명하겠다.
module bin_to_dec(
input [11:0] bin,
output reg [15:0] bcd
);
reg [3:0] i;
always @(bin)
begin
bcd = 0;
for(i = 0; i < 12; i = i+1) //베릴로그에는 증감 연산자가 없음
begin
bcd = {bcd[14:0], bin[11-i]}; // 결합연산자 {}
if(i < 11 && bcd[3:0] > 4) bcd[3:0] = bcd[3:0] + 3;
if(i < 11 && bcd[7:4] > 4) bcd[7:4] = bcd[7:4] + 3;
if(i < 11 && bcd[11:8] > 4) bcd[11:8] = bcd[11:8] + 3;
if(i < 11 && bcd[15:12] > 4) bcd[15:12] = bcd[15:12] + 3;
end
end
endmodule
먼저 이렇게 코드를 구현했다. 간단하게 설명하자면, 바꾸고 싶은 2진 비트의 길이만큼 루프를 돌려야한다.
우리는 binary 비트가 총 12자리이므로 12번의 루프를 거쳐야한다.
맨 처음 루프가 진행되면, 2진비트의 최상위 비트가 BCD의 최하위 비트로 온다.(이때 BCD는 아예 숫자가 없는 것으로 시작)
이렇게 루프를 한 번씩 거치면서 BCD코드의 숫자들을 추가한다. 여기서 가장 중요한 것은 숫자를 추가하면서 BCD 코드를 4비트씩 잘라 10진수로 4가 넘는지 안넘는지 판단해야한다. 4가 넘는 4비트가 있다면 그 네자리 비트는 0011을 더해주어야 한다. 그 다음 맨 마지막에 연산을 제외해야한다. 글을 읽고 이해하기에는 무리가 있다. 10진수로 105, 2진수로 0110 1001을 BCD코드로 변환하는 과정을 아래 사진에 첨부하겠다.
2진수 0110 1001(10진수로 105)을 BCD코드로 바꾸는 과정을 그려보았다. i가 0부터 7까지 총 8번의 shift과정을 거치게 되고, 중간에 4비트씩 잘라놓은 어떤 구간이던지간에 10진수로 4가 넘는다면, 무조건 0011을 더해주어야 한다. 그러나 기억해야할 것은 맨 마지막 shift과정에서는 4 이상일 때, 0011 덧셈 연산을 하지 않고 그대로 결과를 출력한다.
3. Basys3 2개로 구현해보기
첫 번째 디바이스는 10의 자리, 두 번째 디바이스는 1의 자리를 표현할 것이다. 지난번 사용했던 FND를 위한 7seg 디코더 모듈 사용하여 구현하겠다.
module BCD_FND_top(
input [3:0] in_bin, //switch
output [6:0] seg_7, //seg bits
output [3:0] com_an //anode on = 0
);
wire [15:0] w_bcd;
bin_to_dec BTD(
.bin({8'd0, in_bin}),
.bcd(w_bcd)
);
decoder_7_seg SEG( //모듈 가져와서 여기 있는 변수들 전달인자로 넣어주기
.hex_value(w_bcd[3:0]),
//.hex_value(w_bcd[7:4]),
.seg_7(seg_7),
.com_an(com_an)
);
endmodule
특별한 점이 있다면, SEG 인스턴스 내에 첫번째 모듈에서 10의 자리를 나타내기로 했으므로, .hex_value(w_bcd[7:4])를 코드에 작성하여 10의 자리를 출력하도록 설정했고, 두번째 모듈에서는 1의 자리를 나타내기로 했으므로, .hex_value(w_bcd[3:0])를 코드에 작성하여 10의 자리를 출력하도록 설정했다.
다음은 Basys3를 사용해야 하므로 xdc코드를 수정해야 한다.
슬라이드 스위치 역할을 하는 input을 각각 스위치에 매핑하였고, 지난번 FND를 사용했을 때처럼 FND를 ON시키기 위해 각각 포트를 매핑하였다.
아래의 결과 영상을 보자.
두 개의 Basys3의 슬라이드 스위치를 12가 되게끔 ON 했을 때, 10의 자리를 나타내는 왼쪽의 FND에서는 1이 출력되고, 오른쪽 FND에서는 2가 출력된다.
두번째는 7이 되었을 때, 0과 7이 각각 FND에 출력되는 것을 볼 수 있고, 마지막으로 15로 스위치를 맞췄을 때, 1과 5가 각각 FND에 출력됨을 알 수 있다.
'FPGA' 카테고리의 다른 글
[FPGA] 10. Basys3의 LED와 FND를 이용한 10진 카운터 실습 (0) | 2023.04.28 |
---|---|
[FPGA] 9. 래치(Latch)와 플립플롭(Flip-Flop) (0) | 2023.04.28 |
[FPGA] 7. 멀티플렉서와 디멀티플렉서 (0) | 2023.04.20 |
[FPGA] 6. Basys3 두 개로 Encoder <--> Decoder 구현 / 7-SEG Decoder 구현 (0) | 2023.04.18 |
[FPGA] 5. Basys3 사용해보기 (0) | 2023.04.18 |