지난 3편에서는 입력/출력/입출력 핀의 사용법에 대해서 알아보았다.
이번에는 이핀들을 실제로 제어하기 위하여 PLD와 CPU의 연결방법에 대하여 알아본다.
이번글의 최종 목표는 C언어상에서
특정 어드레스에 DATA를 Write하면 해당 Data가 PLD의 외부출력핀으로 나가고,
특정 어드레스에 DATA를 READ하면 PLD의 입력핀의 값이 읽을수 있게 하는것이다.
CPU와 PLD를 연결하는 이유는 서로의 데이터 교환을 위해서이다.
데이터의 종류와 데이터의 전송속도에 따라서 다양한 연결방법이 존재한다.
하지만 가장 기본이 되는 연결방법은 PLD가 SRAM과 같이 동작하도록 연결하는 방법이다.
여기서는 이 방법에 대해서 집중적으로 살펴본다.
CPU와 PLD의 연결구성은 대략 다음 그림과 같다.
[그림1] CPU-PLD연결
거의 모든 CPU가외부 ADDRESS BUS와 DATA BUS가지고 있으며,
이들 버스의 용도는 외부메모리 ACCESS이다.
외부 메모리 ACCESS중에서도 SRAM의 ACCESS는 CPU의 가장 기본적인
기능이면서, ACCESS 방법(Protocol)이 통일되어 있는 방법이다.
모든 CPU제조업체와SRAM제조업체는 아래설명하는 통일된 방법으로
자신들의 IC가 동작하도록 제조한다.
모든 CPU Datasheet에는 외부 메모리의 READ CYCLE Timing과 WRITE CYCLE Timing이
도면으로 그려져 있다.
이 timing그림은 거의 모든 CPU가 동일한 그림이다.
또한 모든 SRAM Datasheet에는 CPU Datasheet에 그려져 있는것과 동일한 timing도면이
있다.
CPU와 PLD를 연결하기 위해서는 PLD를 SRAM처럼 동작시키면 되고,
PLD를 SRAM처럼 동작시키기 위해서는 CPU나 SRAM에 있는 timing도면대로
PLD내부를 구성하면 된다.
따라서 PLD로직을 작성하기 위해서는 SRAM timing에 대해서 완벽하게 마스터해야한다.
[그림2] SRAM READ Timing(출처 :삼성 KM62256D datasheet)
[그림3] SRAMWRITE Timing(출처 :삼성 KM62256D datasheet)
위 그림들이 SRAM의 ACCESS timing이다.
[그림1]의 구성으로 PLD를 작성한 예제가 바로 다음 PDF화일이다.
IDE_io_144.pdf이 PDF파일을 별도의 창에 열어놓고 아래를 보기 바란다.
(참고로 이 PDF파일은 필자가 만든 ARMCPLD보드에서 직접 가져온 pdf파일이다.)
먼저 SW입력과 LED출력은 3장의 입출력을 참고한다.
pdf파일을 보면 CPU쪽 인터페이스는 MA(7:6),MD(7:0),MNCS,MNWE,MNOE signal이 있다.
nRESET와 CPU_CLK,Timer_CLK는 메모리 엑세스와 직접적인 연관은 없다.
먼저 CPU가 led_out(7:0)에 write하는 과정을 살펴보자.
CPU의 DATABUS MD(7:0)은 입력버퍼 IBUF8을 통해 MDI(7:0)으로 항상연결되어 있다.
MDI(7:0)은 FD8CE를 통해서 led_out(7:0)으로 연결된다.
따라서 CPU databus의 값은 항상 FD8CE의 입력단까지 전달된다.
이제 MNWE신호가 0에서 1로 바뀌는 순간에 databus의 값이 led_out(7:0)으로 전달될 것이다.
하지만 CPU의 모든 메모리 write신호에 이 FD8CE가 반응하면 안된다.
FD8CE는 어드레스버스에 특정 값(해당 어드레스)가 set되었을때의 MNWE에만 동작해야 한다.
MSEL2가 바로 이 신호이다.
인스턴스 D2_4E가 MSEL2를 생성해내는 어드레스 디코더이다.
인스턴스 D2_4E는 Add7번과 Addr6번의 상태를 감지해서 MSEL2/MSEL3를 선택한다.
물론 MCS가 1일때만 동작한다.
이제 이 D2_4E와 FD8CE의 동작을 [그림 3]의 write cycle과 연계해서 살펴보자.
CPU는 먼저 자신이 write하려는 번지의 address 버스와 databus를 먼저 set한다.(twc의 왼쪽 화살표부분)
([그림 3]은 SRAM의 datasheet이기 때문에 SRAM의 입장에서 입력데이터의 유효구간-data valid만
표시되어 있다. 하지만 사실은 CPU의 입장에서는 address bus와 data bus를 동시에 set한다).
그다음에 CPU는 nCS를 0으로 만든다.
PLD내부에서는 MNCS가 0이 되면(CPU가 nCS를 0으로 만들면) inv를 거쳐서 MCS가 1이된다.
MCS가 1이 되면 그때의 MA(7:6)의 상태에 따라서 MSEL2나 MSEL3가 1이된다.
만일 MSEL2가 선택되었다면(MA(7:6)=10)이라면 FD8CE가 enable된다.
그리고 CPU는 MNWE를 0으로 만들지만 이때는 아무 변화가 없다.
CPU가 MNWE를 1로 만들면 MDI(7:0)의 값이 led_out(7:0)에 set된다.
그다음에nCS도 1로 올라간다.
이렇게 해서 메모리 write cycle은 끝났다.
이 cycle에서 가장중요한 순간이 MNWE가 0에서 1로 올라가는 순간이다.
MNWE가 1로되는 순간의 데이터버스 값이 FD8CE의 출력값이 된다.
이 순간에 data bus가 안정적이지 못하거나,
CPU의 출력핀에서부터FD8CE의 CLK핀까지 변화하는데 지연시간이 발생하거나,
MNWE signal에 노이즈가 발생한다면 data가 정상적으로 write되지 못한다.
이제 실제 C언어에서는 다음과 같이사용하면 led_out(7:0)에 write할수 있다.
#define cpld_led_write (*(volatile U16 *)0x06000080)
cpld_led_write = 0xff;
위와 같은 형태로 write하면 0xff가 led_out(7:0)에 set된다.
어드레스의 MA(7:6)=10인 형태가 0x06000080의 8로서 나타났다.
이와 같이 CPU의 write가 이루어진다.
CPU의 write는 read에 비해서 상당히 쉬운편이다.
이제 CPU가 sw_in(7:0)을 읽는과정을 살펴보자.
CPU의 데이터버스는 입출력버스이고, CPU가 제어권한을 가지고 있다.
3장에서 설명한것처럼 데이터버스에 아무 IC나 마구 data를 출력해서는 안된다.
PLD도 마찬가지로 CPU의 제어(명령)에 절대적으로 복종해야 하고,
CPU가 출력하라고 할때만 data를 출력해야 한다.
바로 CPU의 제어컨트롤을 담당하는 부분이 OBUFT8이다.
OBUFT8의 T가 0이면 MDO(7:0)이 MD(7:0)으로 출력된다.
T가 1이면 OBUFT8의 출력측과 MD(7:0)은 연결이 끊어진것처럼 OBUFT8은 동작한다.
이렇게 끊어진 상태처럼 보이는것이 Tri-State혹으 Hi-Z이다.
이제 그림2의 read cycle을 참조하며 CPU의 read과정을 살펴보자.
먼저 CPU는 address를 셋트하고, ncs를 0으로 만든다.
PLD내부에서는 D2_4E에 의해 address가 선택된다.
MA(7:0)=11이라면 MSEL3가 1이된다.
CPU가 nCS를0으로 만드는것만으로도 sw_in(7:0)은 BUFE8을 거쳐 MDO(7:0)을 거쳐서
OBUFT8의 입력단까지도달하게 된다.
CPU가 nOE를 0으로 만들면 OBUFT8의 T에 연결된 NAND2B1의 출력값은 0이된다.
따라서 MDO(7:0)의 값이 MD(7:0)으로 출력된다.
그리고 CPU는 nOE가 1로되는 순간의 MD(7:0)의 값을 읽어들인다.
nOE가 0에서 1로 되는 순간에 CPU내부에있는 flip-flop이 set된다.
따라서 nOE가 nWE와동일하게 flip-flop을set하는역할을 한다.
nOE가 1로 되는 순간 OBUFT8은 tri-state가 된다.
이부분은 아주 미묘한 문제를 발생시킨다.
CPU가 tri-state상태 이전의 값을 가져갈지, tri-state상태 이후의 값을 가져갈지에 따라서
정상값 혹은 쓰레기 값을 가져가게 된다.
실제로는 CPU내부에서 먼저 nOE가 1로 set되고, CPU핀을 통해, PCB거친후에
PLD를 거치고, nand2b1을 거친후에 OBUFT8까지 도달한다.
이때의 지연시간때문에 별다른 문제를 발생시키지는 않는다.
하여튼 위와 같은 과정을 거쳐서 read과정이 이루어진다.
이제 실제 C언어에서는 다음과 같이사용하면 sw_in(7:0)을 read할수 있다.
#define cpld_sw_read (*(volatile U16 *)0x060000c0)
indata=cpld_sw_read;
어드레스의 c가 MA(7:6)='11'을 의미한다.
이상과 같이 3장에서 제기했던 누가, 언제, 어떻게 data를 read/write하는지 알아보았다.
여기서 문제가 되는 부분이 있다.
이 PLD는 본인이 직접 만든 SRAM의 일종이라고 할수 있다.
모든 반도체 메이커가 자신이 만든 반도체에 timing chart를 datasheet에 공개하는것처럼,
위에서만든 PLD의 access속도가 얼마인지를 PLD로직을 만든 사람은 반드시 알고있어야 한다.
즉 그림2와 그림3에서 나온 각각의 timing값들을 계산할수 있어야만
실전에서 CPU와 인터페이스 할수 있다.
Xilinx ISE에서는 합성된PLD의 timing과 관련한 report를 만들어준다.
하지만 ISE가 만드는 timing REPORT는 PLD칩 내부의 동작 timing이지,
PLD칩 외부의 동작 timing을 만들지는 않는다.
따라서 PLD Logic 작성자는 PLD칩내부의 timing report를 바탕으로
PLD칩외부의 timing report를 직접 작성할수 있어야한다.
그래야만 내가 만든 PLD로직이 8051과 붙일수 있는지, ARM CPU와
붙일수 있는지 파악할수 있고,
고성능 CPU과 연결할 경우에 CPU의 RAM(이경우는 PLD) ACCESS CYCLE을 결정할수 있기 때문이다.
이 report를 만드는 일은 본 강좌에서는 언급하지 않는다.
이부분은 여러분들의 숙제이다.
이번에는 이핀들을 실제로 제어하기 위하여 PLD와 CPU의 연결방법에 대하여 알아본다.
이번글의 최종 목표는 C언어상에서
특정 어드레스에 DATA를 Write하면 해당 Data가 PLD의 외부출력핀으로 나가고,
특정 어드레스에 DATA를 READ하면 PLD의 입력핀의 값이 읽을수 있게 하는것이다.
CPU와 PLD를 연결하는 이유는 서로의 데이터 교환을 위해서이다.
데이터의 종류와 데이터의 전송속도에 따라서 다양한 연결방법이 존재한다.
하지만 가장 기본이 되는 연결방법은 PLD가 SRAM과 같이 동작하도록 연결하는 방법이다.
여기서는 이 방법에 대해서 집중적으로 살펴본다.
CPU와 PLD의 연결구성은 대략 다음 그림과 같다.
[그림1] CPU-PLD연결
거의 모든 CPU가외부 ADDRESS BUS와 DATA BUS가지고 있으며,
이들 버스의 용도는 외부메모리 ACCESS이다.
외부 메모리 ACCESS중에서도 SRAM의 ACCESS는 CPU의 가장 기본적인
기능이면서, ACCESS 방법(Protocol)이 통일되어 있는 방법이다.
모든 CPU제조업체와SRAM제조업체는 아래설명하는 통일된 방법으로
자신들의 IC가 동작하도록 제조한다.
모든 CPU Datasheet에는 외부 메모리의 READ CYCLE Timing과 WRITE CYCLE Timing이
도면으로 그려져 있다.
이 timing그림은 거의 모든 CPU가 동일한 그림이다.
또한 모든 SRAM Datasheet에는 CPU Datasheet에 그려져 있는것과 동일한 timing도면이
있다.
CPU와 PLD를 연결하기 위해서는 PLD를 SRAM처럼 동작시키면 되고,
PLD를 SRAM처럼 동작시키기 위해서는 CPU나 SRAM에 있는 timing도면대로
PLD내부를 구성하면 된다.
따라서 PLD로직을 작성하기 위해서는 SRAM timing에 대해서 완벽하게 마스터해야한다.
[그림2] SRAM READ Timing(출처 :삼성 KM62256D datasheet)
[그림3] SRAMWRITE Timing(출처 :삼성 KM62256D datasheet)
위 그림들이 SRAM의 ACCESS timing이다.
[그림1]의 구성으로 PLD를 작성한 예제가 바로 다음 PDF화일이다.
IDE_io_144.pdf이 PDF파일을 별도의 창에 열어놓고 아래를 보기 바란다.
(참고로 이 PDF파일은 필자가 만든 ARMCPLD보드에서 직접 가져온 pdf파일이다.)
먼저 SW입력과 LED출력은 3장의 입출력을 참고한다.
pdf파일을 보면 CPU쪽 인터페이스는 MA(7:6),MD(7:0),MNCS,MNWE,MNOE signal이 있다.
nRESET와 CPU_CLK,Timer_CLK는 메모리 엑세스와 직접적인 연관은 없다.
먼저 CPU가 led_out(7:0)에 write하는 과정을 살펴보자.
CPU의 DATABUS MD(7:0)은 입력버퍼 IBUF8을 통해 MDI(7:0)으로 항상연결되어 있다.
MDI(7:0)은 FD8CE를 통해서 led_out(7:0)으로 연결된다.
따라서 CPU databus의 값은 항상 FD8CE의 입력단까지 전달된다.
이제 MNWE신호가 0에서 1로 바뀌는 순간에 databus의 값이 led_out(7:0)으로 전달될 것이다.
하지만 CPU의 모든 메모리 write신호에 이 FD8CE가 반응하면 안된다.
FD8CE는 어드레스버스에 특정 값(해당 어드레스)가 set되었을때의 MNWE에만 동작해야 한다.
MSEL2가 바로 이 신호이다.
인스턴스 D2_4E가 MSEL2를 생성해내는 어드레스 디코더이다.
인스턴스 D2_4E는 Add7번과 Addr6번의 상태를 감지해서 MSEL2/MSEL3를 선택한다.
물론 MCS가 1일때만 동작한다.
이제 이 D2_4E와 FD8CE의 동작을 [그림 3]의 write cycle과 연계해서 살펴보자.
CPU는 먼저 자신이 write하려는 번지의 address 버스와 databus를 먼저 set한다.(twc의 왼쪽 화살표부분)
([그림 3]은 SRAM의 datasheet이기 때문에 SRAM의 입장에서 입력데이터의 유효구간-data valid만
표시되어 있다. 하지만 사실은 CPU의 입장에서는 address bus와 data bus를 동시에 set한다).
그다음에 CPU는 nCS를 0으로 만든다.
PLD내부에서는 MNCS가 0이 되면(CPU가 nCS를 0으로 만들면) inv를 거쳐서 MCS가 1이된다.
MCS가 1이 되면 그때의 MA(7:6)의 상태에 따라서 MSEL2나 MSEL3가 1이된다.
만일 MSEL2가 선택되었다면(MA(7:6)=10)이라면 FD8CE가 enable된다.
그리고 CPU는 MNWE를 0으로 만들지만 이때는 아무 변화가 없다.
CPU가 MNWE를 1로 만들면 MDI(7:0)의 값이 led_out(7:0)에 set된다.
그다음에nCS도 1로 올라간다.
이렇게 해서 메모리 write cycle은 끝났다.
이 cycle에서 가장중요한 순간이 MNWE가 0에서 1로 올라가는 순간이다.
MNWE가 1로되는 순간의 데이터버스 값이 FD8CE의 출력값이 된다.
이 순간에 data bus가 안정적이지 못하거나,
CPU의 출력핀에서부터FD8CE의 CLK핀까지 변화하는데 지연시간이 발생하거나,
MNWE signal에 노이즈가 발생한다면 data가 정상적으로 write되지 못한다.
이제 실제 C언어에서는 다음과 같이사용하면 led_out(7:0)에 write할수 있다.
#define cpld_led_write (*(volatile U16 *)0x06000080)
cpld_led_write = 0xff;
위와 같은 형태로 write하면 0xff가 led_out(7:0)에 set된다.
어드레스의 MA(7:6)=10인 형태가 0x06000080의 8로서 나타났다.
이와 같이 CPU의 write가 이루어진다.
CPU의 write는 read에 비해서 상당히 쉬운편이다.
이제 CPU가 sw_in(7:0)을 읽는과정을 살펴보자.
CPU의 데이터버스는 입출력버스이고, CPU가 제어권한을 가지고 있다.
3장에서 설명한것처럼 데이터버스에 아무 IC나 마구 data를 출력해서는 안된다.
PLD도 마찬가지로 CPU의 제어(명령)에 절대적으로 복종해야 하고,
CPU가 출력하라고 할때만 data를 출력해야 한다.
바로 CPU의 제어컨트롤을 담당하는 부분이 OBUFT8이다.
OBUFT8의 T가 0이면 MDO(7:0)이 MD(7:0)으로 출력된다.
T가 1이면 OBUFT8의 출력측과 MD(7:0)은 연결이 끊어진것처럼 OBUFT8은 동작한다.
이렇게 끊어진 상태처럼 보이는것이 Tri-State혹으 Hi-Z이다.
이제 그림2의 read cycle을 참조하며 CPU의 read과정을 살펴보자.
먼저 CPU는 address를 셋트하고, ncs를 0으로 만든다.
PLD내부에서는 D2_4E에 의해 address가 선택된다.
MA(7:0)=11이라면 MSEL3가 1이된다.
CPU가 nCS를0으로 만드는것만으로도 sw_in(7:0)은 BUFE8을 거쳐 MDO(7:0)을 거쳐서
OBUFT8의 입력단까지도달하게 된다.
CPU가 nOE를 0으로 만들면 OBUFT8의 T에 연결된 NAND2B1의 출력값은 0이된다.
따라서 MDO(7:0)의 값이 MD(7:0)으로 출력된다.
그리고 CPU는 nOE가 1로되는 순간의 MD(7:0)의 값을 읽어들인다.
nOE가 0에서 1로 되는 순간에 CPU내부에있는 flip-flop이 set된다.
따라서 nOE가 nWE와동일하게 flip-flop을set하는역할을 한다.
nOE가 1로 되는 순간 OBUFT8은 tri-state가 된다.
이부분은 아주 미묘한 문제를 발생시킨다.
CPU가 tri-state상태 이전의 값을 가져갈지, tri-state상태 이후의 값을 가져갈지에 따라서
정상값 혹은 쓰레기 값을 가져가게 된다.
실제로는 CPU내부에서 먼저 nOE가 1로 set되고, CPU핀을 통해, PCB거친후에
PLD를 거치고, nand2b1을 거친후에 OBUFT8까지 도달한다.
이때의 지연시간때문에 별다른 문제를 발생시키지는 않는다.
하여튼 위와 같은 과정을 거쳐서 read과정이 이루어진다.
이제 실제 C언어에서는 다음과 같이사용하면 sw_in(7:0)을 read할수 있다.
#define cpld_sw_read (*(volatile U16 *)0x060000c0)
indata=cpld_sw_read;
어드레스의 c가 MA(7:6)='11'을 의미한다.
이상과 같이 3장에서 제기했던 누가, 언제, 어떻게 data를 read/write하는지 알아보았다.
여기서 문제가 되는 부분이 있다.
이 PLD는 본인이 직접 만든 SRAM의 일종이라고 할수 있다.
모든 반도체 메이커가 자신이 만든 반도체에 timing chart를 datasheet에 공개하는것처럼,
위에서만든 PLD의 access속도가 얼마인지를 PLD로직을 만든 사람은 반드시 알고있어야 한다.
즉 그림2와 그림3에서 나온 각각의 timing값들을 계산할수 있어야만
실전에서 CPU와 인터페이스 할수 있다.
Xilinx ISE에서는 합성된PLD의 timing과 관련한 report를 만들어준다.
하지만 ISE가 만드는 timing REPORT는 PLD칩 내부의 동작 timing이지,
PLD칩 외부의 동작 timing을 만들지는 않는다.
따라서 PLD Logic 작성자는 PLD칩내부의 timing report를 바탕으로
PLD칩외부의 timing report를 직접 작성할수 있어야한다.
그래야만 내가 만든 PLD로직이 8051과 붙일수 있는지, ARM CPU와
붙일수 있는지 파악할수 있고,
고성능 CPU과 연결할 경우에 CPU의 RAM(이경우는 PLD) ACCESS CYCLE을 결정할수 있기 때문이다.
이 report를 만드는 일은 본 강좌에서는 언급하지 않는다.
이부분은 여러분들의 숙제이다.
댓글 없음:
댓글 쓰기