1. 멀티플렉서(Multiplexer)
멀티플렉서란 다수의 입력신호중 하나를 선택해서 보내주는 기능을 가지고 있다. 예를 들어, 핸드폰에 8개의 전화번호가 저장되어 있고, 각각을 1부터 8까지 순서대로 저장했다고 가정하자. 만약 숫자 버튼 1을 꾹 누르면 첫 번째로 저장된 곳 전화가 걸릴 것이고,숫자 버튼 2를 꾹 누르면 두 번째로 저장된 곳 전화가 걸릴 것이다. 결국 n개의 입력 신호 중 하나의 입력 신호를 선택하면 하나의 신호로 출력이 될 수 있게 해주는 것을 멀티플렉서라고 한다.
위 사진은 멀티플렉서를 그림으로 나타낸 사진이다. 보낼 각 주소의 데이터와 신호선 두 가닥을 이용하여 8개의 데이터 중 하나를 선택하여 보낼 수 있다. 이를 Verilog로 구현하면 다음과 같다
module mux_8_1_1(
input [2:0] S,
input [7:0] D,
output F
);
wire [2:0] Sbar;
wire [7:0] WD;
not(Sbar[0], S[0]);
not(Sbar[1], S[1]);
not(Sbar[2], S[2]);
and (WD[0], D[0], Sbar[2], Sbar[1], Sbar[0]);
and (WD[1], D[1], Sbar[2], Sbar[1], S[0]);
and (WD[2], D[2], Sbar[2], S[1], Sbar[0]);
and (WD[3], D[3], Sbar[2], S[1], S[0]);
and (WD[4], D[4], S[2], Sbar[1], Sbar[0]);
and (WD[5], D[5], S[2], Sbar[1], S[0]);
and (WD[6], D[6], S[2], S[1], Sbar[0]);
and (WD[7], D[7], S[2], S[1], S[0]);
or (F, WD[0], WD[1], WD[2], WD[3], WD[4], WD[5], WD[6], WD[7]);
endmodule
Verilog에서 게이트 레벨 모델링으로 구현한 8x1 멀티플렉서이다. input에 주소 값 역할을 할 8비트짜리 D와 신호선 역할을 할 2비트짜리 S을 선언하였고, 주소 값을 저장 할 output 1비트 F를 선언하였다.
또한 위 8x1 멀티플렉서의 신호선 단에서 not게이트와 and게이트 사이의 선을 처리해야하므로 wire형으로 1비트짜리 Sbar 3개와 and게이트 이후부터 하나로 모이는 or게이트 사이의 선을 처리해야하므로 wire형으로 1비트짜리 WD 8개를 선언해주었다.
그 이후, 각 and게이트를 호출하여 output과 input을 회로도에 맞게 적절하게 넣어주었다.
파형에 대한 시뮬레이션을 보았을 때, S가 4인 구간에서 D[4]의 파형이 F에서 그대로 출력되는 것을 볼 수 있고, S가 2인 구간에서 D[2]의 파형이 F에서 그대로 출력되는 것을 볼 수 있다.
2. 디멀티플렉서(DeMultiplexer)
디멀티플렉서란 멀티플렉서의 반대라고 생각하면 된다. 하나의 신호를 여러 곳 중 한 곳으로 보낼 때 쓰인다.
위 사진은 디멀티플렉서를 그림으로 나타낸 사진이다. 보낼 데이터의 값과 신호선 두 가닥을 이용하여 4개의 주소 중 한 곳으로 보낼 수 있다. 이를 Verilog로 구현하면 다음과 같다.
module demux_1_4(
input [1:0] S,
input D,
output [3:0] F
);
wire [1:0] Sbar;
not(Sbar[0], S[0]);
not(Sbar[1], S[1]);
and(F[0], D ,Sbar[1], Sbar[0]);
and(F[1], D ,Sbar[1], S[0]);
and(F[2], D ,S[1], Sbar[0]);
and(F[3], D ,S[1], S[0]);
endmodule
Verilog에서 게이트 레벨 모델링으로 구현한 1x4 디멀티플렉서이다. input에 데이터 역할을 할 1비트짜리 D와 신호선 역할을 할 2비트짜리 S를 선언하였고, 주소 값을 저장 할 output 레지스터 F를 선언하였다.
D는 1로 상수값을 주었을 때, S의 값에 따라 각각의 F에서 D가 출력되는 것을 볼 수 있다.
3. 8x1 멀티플렉서와 1x4 디멀티플렉서를 결합하고, 신호 선택선을 이용하여 8개의 입력신호를 4개의 출력신호로 분배해보기
위 8x1 멀티플렉서를 Input으로 놓고, 신호를 입력받아 멀티플렉서로 나온 신호를 디멀티플렉서로 전달하여 출력하는 모듈을 만들어보자. 아래 그림과 같다.
위와 같이 S_mux와 S_demux의 신호 선택선으로 보낼 데이터와 보낼 주소를 정할 것이다. 7비트 D에 각각의 데이터가 들어오면 신호 선택선에 따라 하나의 데이터가 한 곳으로 가게 될 것이다.
위 사진을 코딩으로 구현해보자. 탑 모듈을 먼저 선언하여 멀티플렉서와 디멀티플렉서 각각을 호출하여 인스턴스를 붙여준다.
module mux_test_top(
input [7:0] D,
input [3:0] S_mux,
input [2:0] S_demux,
output [3:0] F
);
wire w;
mux_8_1_1 mux(
.D(D),
.S(S_mux),
.F(w)
);
demux_1_4 demux(
.S(S_demux),
.D(w),
.F(F)
);
endmodule
.MUX와 DEMUX 사이를 연결해줄 wire 타입의 w를 선언하였고, 신호선들을 각각 연결해주었다.
또한 simulation을 하기 위해 테스트벤치를 만들 것이다.
`timescale 1ns / 1ps
module mux_test_top_tb();
reg clk_100MHz, clk_50MHz, clk_25MHz, clk_12500kHz, clk_6250kHz, clk_3125kHz, clk_1562kHz, clk_781kHz;
reg [2:0] S_mux;
reg [1:0] S_demux;
wire [3:0] F;
mux_test_top DUT(.D({clk_100MHz, clk_50MHz, clk_25MHz, clk_12500kHz, clk_6250kHz, clk_3125kHz, clk_1562kHz, clk_781kHz}),
.S_mux(S_mux),
.S_demux(S_demux),
.F(F)
);
initial begin //이니셜문은 한번만 실행
//아래 클럭을 주기전에 한번은 초기화를 해야함 아니면 임피던스임.
clk_100MHz = 0;
clk_50MHz = 0;
clk_25MHz = 0;
clk_12500kHz = 0;
clk_6250kHz = 0;
clk_3125kHz = 0;
clk_1562kHz = 0;
clk_781kHz = 0;
S_mux = 0;
S_demux = 0;
end
always #5 clk_100MHz = ~clk_100MHz; //상승 5ns + 하강 5ns = 10ns 라서 1주기를 나타내기위해 #5로 delay한 것
//1과 0으로 자꾸 바꿔서 클럭을 인위적으로 생성
always #10 clk_50MHz = ~clk_50MHz;
always #20 clk_25MHz = ~clk_25MHz;
always #40 clk_12500kHz = ~clk_12500kHz;
always #80 clk_6250kHz = ~clk_6250kHz;
always #160 clk_3125kHz = ~clk_3125kHz;
always #320 clk_1562kHz = ~clk_1562kHz;
always #640 clk_781kHz = ~clk_781kHz;
initial begin //이니셜문은 한번만 실행
//아래 클럭을 주기전에 한번은 초기화를 해야함 아니면 임피던스임.
#10000;
S_mux = 3'b011;
S_demux = 2'b01;
#10000;
S_mux = 3'b100;
S_demux = 2'b11;
$finish; //총 20000ns뒤에 아예 시뮬레이션 자체를 종료
end
endmodule
전체 모듈 왼쪽 단 MUX의 D에 들어가는 각각의 Input 값을 클락으로 만들 것이다. 시뮬레이션에서 정상적으로 출력되는지 보기 위해서 각각의 클럭을 다른 크기로 만들어주었다. 그리고 먼저 모든 파형과 신호 선택선을 0으로 초기화 시키고, always문에서 무한루프로 클럭을 발생시켰다.이렇게 만든 클럭은 왼쪽 MUX D에 들어갈 것이다. 마지막에 신호 선택선(S_mux와 S_demux)에 시뮬레이션을 위해 각각 값을 넣어주었다. 시뮬레이션을 확인해보자.
.
시뮬레이션을 분석해보자. S_mux(mux에 입력되는 선택선)에 3이 입력됐다. 3번째에 입력되는 6250kHz의 클락이 출력되어야 한다. S_demux(demux에 입력되는 선택선)에는 1이 입력되었으므로 F[1]의 위치에서 출력되어야 한다. 따라서 6250kHz의 클락이 F[1]에 출력되면 된다. 왼쪽 빨간 선에서 그대로 출력되는 것을 볼 수 있다.
왼쪽에는 S_mux(mux에 입력되는 선택선)에 4가 입력됐다. 4번째에 입력되는 12500kHz의 클락이 출력되어야 한다. S_demux(demux에 입력되는 선택선)에는 3이 입력되었으므로 F[3]의 위치에서 출력되어야 한다. 따라서 12500kHz의 클락이 F[3]에 출력되면 된다. 오른쪽 파란 선에서 그대로 출력되는 것을 볼 수 있다.
'FPGA' 카테고리의 다른 글
[FPGA] 9. 래치(Latch)와 플립플롭(Flip-Flop) (0) | 2023.04.28 |
---|---|
[FPGA] 8. 2진수를 BCD코드로 변환 프로그램을 Basys3에서 구현하기 (0) | 2023.04.20 |
[FPGA] 6. Basys3 두 개로 Encoder <--> Decoder 구현 / 7-SEG Decoder 구현 (0) | 2023.04.18 |
[FPGA] 5. Basys3 사용해보기 (0) | 2023.04.18 |
[FPGA] 4. 대표적인 모델링 방법 (Data Flow/Gate Level/Behavioral Modeling) (0) | 2023.04.18 |