目次
前
次
ROMエミュレータ作成
アセンブリ言語、C言語で作ったファームウエアを
ROMに焼き、動作テストするための時間が勿体なく
思えてきたので、ROMエミュレータを作成しました。
SRAMは、秋月電子で32kバイトのチップ5個で\300程度
なので、変換基板と合わせて入手してありました。
今回、このSRAMを利用することに。
ROMエミュレータの内容は、非常に簡単で、次のブロック図
に相当するレジスタを入れてあります。
2つのCPLDに、4ビットレジスタを複数用意しておき
アドレスデコーダを利用して、各レジスタに値を設定
します。CPLDを使うのは、手持ちのロジックICがない
のと、後で回路を変更しやすくするため。
8ビットのうち上位4ビットをアドレスに、下位4ビットを
データにして、4ビットレジスタにデータを格納します。
アドレスとレジスタの組合せは、以下。
- register8 control(low nibble) nHiZ
- register7 addressH(high nibble) A12-A15
- register6 addressH(low nibble) A8-A11
- register5 addressL(high nibble) A4-A7
- register4 addressL(low nibble) A0-A3
- register3 data(high nibble) D4-D7
- register2 data(low nibble) D0-D3
- register1 control(high nibble) nRESET
- register0 control(low nibble) nCS,nWR
nHiZは、CPLDの出力をハイインピーダンス状態にします。
nRESETは、CPUやMPUをリセット状態にし、アドレス、データ
制御バスをハイインピーダンス状態にします。
nCS,nWRは、SRAMにアドレス、データを指定してデータを
格納するために利用。
TTLロジックの回路図で示すと、次のようになります。
2つのCPLDに、ブロック図に相当するデジタル回路をVHDL言語
で記述して、入れました。VHDLコードは、以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity romemu is
port (
-- system
nRESET : in std_logic;
CLOCK : in std_logic;
-- input trigger
TRG : in std_logic ;
-- selector
SEL : in std_logic_vector(3 downto 0);
-- input data
NDAT : in std_logic_vector(3 downto 0);
-- output
ROUT1 : out std_logic_vector(7 downto 0);
ROUT0 : out std_logic_vector(7 downto 0)-- ;
);
end romemu;
architecture behavioral of romemu is
-- trigger
signal iTRG_SFT : std_logic_vector(2 downto 0);
signal iTRG : std_logic ;
-- internal registers
signal iREG0 : std_logic_vector(7 downto 0);
signal iREG1 : std_logic_vector(7 downto 0);
signal iREGX : std_logic ;
-- sequence
signal iSTATE : std_logic_vector(1 downto 0);
signal iSEL : integer range 0 to 15 ;
signal iNDAT : std_logic_vector(3 downto 0);
begin
-- input
iNDAT <= NDAT ;
-- output
ROUT1 <= iREG0 when ( iREGX = '1' ) else (others => 'Z') ;
ROUT0 <= iREG1 when ( iREGX = '1' ) else (others => 'Z') ;
-- trigger
process(nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iTRG_SFT <= "000" ;
elsif rising_edge( CLOCK ) then
iTRG_SFT <= iTRG_SFT(1 downto 0) & TRG ;
end if;
end process;
iTRG <= '1' when ( iTRG_SFT = "011" ) else '0' ;
-- master sequencer
process( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iREG0 <= (others => '0') ;
iREG1 <= (others => '0') ;
iREGX <= '0' ;
iSTATE <= "00" ;
iSEL <= 0 ;
elsif rising_edge( CLOCK ) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iTRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- latch data
when 1 => iSTATE <= "11" ;
iSEL <= conv_integer(SEL) ;
-- deliver
when 3 => iSTATE <= "10" ;
if ( iSEL = 0 ) then
iREG0(3 downto 0) <= iNDAT ;
end if ;
if ( iSEL = 1 ) then
iREG0(7 downto 4) <= iNDAT ;
end if ;
if ( iSEL = 2 ) then
iREG1(3 downto 0) <= iNDAT ;
end if ;
if ( iSEL = 3 ) then
iREG1(7 downto 4) <= iNDAT ;
end if ;
if ( iSEL > 7 ) then
iREGX <= iNDAT(0) ;
end if ;
-- return first state
when 2 => iSTATE <= "00" ;
-- default
when others =>
iSTATE <= "00" ;
end case ;
end if;
end process;
end behavioral;
内部に8ビットレジスタを2本、1ビットレジスタを
ひとつ用意します。STROBE信号は、シフトレジスタで
受け、内部のトリガーとします。
レジスタに確実にデータを格納するため
シーケンサを利用します。
ピンアサインは、以下。
NET "CLOCK" LOC = "P5";
NET "nRESET" LOC = "P39";
# control
NET "NDAT<0>" LOC = "P24";
NET "NDAT<1>" LOC = "P25";
NET "NDAT<2>" LOC = "P26";
NET "NDAT<3>" LOC = "P27";
NET "SEL<0>" LOC = "P28";
NET "SEL<1>" LOC = "P29";
NET "SEL<2>" LOC = "P33";
NET "SEL<3>" LOC = "P34";
# trigger
NET "TRG" LOC = "P36";
NET "TLED" LOC = "P35";
# data
NET "ROUT0<0>" LOC = "P1" ;
NET "ROUT0<1>" LOC = "P2" ;
NET "ROUT0<2>" LOC = "P3" ;
NET "ROUT0<3>" LOC = "P4" ;
NET "ROUT0<4>" LOC = "P6" ;
NET "ROUT0<5>" LOC = "P7" ;
NET "ROUT0<6>" LOC = "P8" ;
NET "ROUT0<7>" LOC = "P9" ;
# data
NET "ROUT1<0>" LOC = "P11";
NET "ROUT1<1>" LOC = "P12";
NET "ROUT1<2>" LOC = "P13";
NET "ROUT1<3>" LOC = "P14";
NET "ROUT1<4>" LOC = "P18";
NET "ROUT1<5>" LOC = "P19";
NET "ROUT1<6>" LOC = "P20";
NET "ROUT1<7>" LOC = "P22";
PersonalComputerのパラレルポートから、SRAMにデータを
転送することを想定して使います。パラレルポートを持つ
ノートPCを使って、SRAMにデータ転送します。
ノートPCは、Windows3.1かWindows98をOS
として載せているマシンを利用。
このマシンで、MS-DOSで動作するROMエミュレータ
用ソフトを作成し、梅澤無線電機のUECを基板上に
実装して使います。
ROMエミュレータを利用した、ファームウエア開発は
次のような開発環境になした。
SRAMのアドレス、データはZ80、CPLDどちらも出力し
nWEはCPLDのみ、nOEはZ80のみが出力します。
アドレス、データは、ハイインピーダンスになる
よう、制御して対応します。
ROMエミュレータが内蔵しているSRAM(32kバイト)に
プログラムを転送するには、LSICでアプリケーション
を作成して対応。
MS-DOSが動作していれば、パラレルポートは次の
どこかのI/Oアドレスに割当てられています。
0378h
0278h
03BCh
上の3ポートのアドレスは、データ入出力の8ビット
アドレスです。制御は、STORBE信号をON/OFFするので
上のI/Oアドレスに、オフセットの+2を加えた、制御
レジスタにパラメータを設定。
ROMエミュレータへ、1バイトデータを転送
するには、次のタイミングチャートを利用。
1バイトのデータを出力し、STROBE信号をON/OFFしますが
データのセットアップタイム、ホールタイムを満たすよう
にしなければなりません。PersonalComputerに使われている
チップにもよりますが、1usの単位で動くので、気にせずに
処理してよいでしょう。
パラレルポートのチェックをするために、次の基板を
利用しました。74HC574のD入力にPD0〜PD7に、CLOCKに
STROBEを接続しています。Q出力にLEDを接続しました。
データ出力のテストプログラムは、非常に簡単です。
LEDに0〜255に相当する点灯パターンを転送して
いるだけです。(このプログラムは、LSICで作成して
あります。)
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <io.h>
#define LPT1 0x378
#define LPT2 0x3bc
#define LPT3 0x278
int lpt_address ;
int set_address(int adr)
{
/* error check */
if ( adr < 0 || 255 < adr ) return -1 ;
/* address */
outp(lpt_address,adr);
/* strobe */
outp(lpt_address+2,0xc4);
outp(lpt_address+2,0xcc);
outp(lpt_address+2,0xcd);
outp(lpt_address+2,0xcc);
outp(lpt_address+2,0xc4);
/* result */
return 0 ;
}
int set_data(int adr,int dat)
{
/* error check */
if ( set_address(adr) == -1 ) return -1 ;
if ( dat < 0 || 255 < dat ) return -1 ;
/* data */
outp(lpt_address,dat);
/* strobe */
outp(lpt_address+2,0xc4);
outp(lpt_address+2,0xc6);
outp(lpt_address+2,0xc7);
outp(lpt_address+2,0xc6);
outp(lpt_address+2,0xc4);
/* result */
return 0 ;
}
void xwait(void)
{
unsigned short x,i ;
for ( i = 0 ; i < 200 ; i++ ) {
x = 0xffff ;
while ( x ) { x-- ; }
}
}
int main(int argc,char *argv[])
{
int i,address,lpt_num ;
/* usage */
if ( argc != 3 ) {
fprintf(stderr,"Usage:ledz lpt_num address\n");
exit(1);
}
/* judge */
address = atoi( &argv[2][0] ) ;
if ( address < 0 || 255 < address ) {
fprintf(stderr,"address range 0 <-> 255\n");
exit(1);
}
lpt_num = atoi( &argv[1][0] ) ;
if ( lpt_num < 1 || 3 < lpt_num ) {
fprintf(stderr,"lpt_number range 1 <-> 3\n");
exit(1);
}
lpt_address = LPT1 ;
if ( lpt_num == 2 ) { lpt_address = LPT2 ; }
if ( lpt_num == 3 ) { lpt_address = LPT3 ; }
/* endless loop */
i = 0 ;
while ( 1 ) {
/* get keyboard */
if ( kbhit() ) break ;
/* out data */
set_data(address,i);
xwait();
/* update */
i++ ;
i %= 256 ;
}
set_data(address,0x00);
return 0 ;
}
パラレルポートにデータを転送できることを
確認した後、次のプログラムを作成してROM
エミュレータ上のSRAMにデータ転送します。
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <io.h>
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
#define LPT1 0x378
#define LPT2 0x3bc
#define LPT3 0x278
#define MASKFF 0xff
#define MASK0F 0x0f
#define OFF 0
#define ON OFF+1
#define DISABLE_RESET 0
#define ENABLE_RESET 1
#define DISABLE_HIZ 0
#define ENABLE_HIZ 1
#define STB_OFF 0xcc
#define STB_ON 0xcd
#define CSOFF_WEOFF 0x03
#define CSON_WEOFF 0x01
#define CSON_WEON 0x00
#define CON_ADR0 0x00
#define CON_ADR1 0x10
#define DAT_LNIBBLE 0x20
#define DAT_HNIBBLE 0x30
#define ADRL_LNIBBLE 0x40
#define ADRL_HNIBBLE 0x50
#define ADRH_LNIBBLE 0x40
#define ADRH_HNIBBLE 0x50
#define CON_ADR0 0x00
#define CON_ADR1 0x10
UWORD lpt_address ;
void send_primitive(UBYTE x);
void send_write_pulse(void);
void send_reset(UBYTE x);
void send_hiz(UBYTE x);
void send_dat(UWORD ax,UBYTE dx);
void send_control(UBYTE dx);
UBYTE get_hex(UBYTE x);
int main(int argc,char *argv[])
{
FILE *fin ;
UWORD lpt_num ;
UWORD madr ;
UBYTE mdat ;
UBYTE mtype ;
UBYTE mcnt ;
UBYTE mindex ;
UBYTE loop ;
char mbuf[256] ;
/* usage */
if ( argc != 3 ) {
fprintf(stderr,"Usage:romemu lpt_num hex_file_name\n");
exit(1);
}
lpt_num = atoi( &argv[1][0] ) ;
if ( lpt_num < 1 || 3 < lpt_num ) {
fprintf(stderr,"lpt_number range 1 <-> 3\n");
exit(1);
}
lpt_address = LPT1 ;
if ( lpt_num == 2 ) { lpt_address = LPT2 ; }
if ( lpt_num == 3 ) { lpt_address = LPT3 ; }
fin = fopen(&argv[2][0],"r") ;
if ( fin == NULL ) {
fprintf(stderr,"file not exist !\n");
exit(1);
}
/* CPLD access SRAM */
send_reset(ENABLE_RESET);
send_hiz(DISABLE_HIZ);
/* store data to ROM emulator */
madr = 0 ;
mcnt = 0 ;
mtype = 0 ;
while ( !feof(fin) ) {
/* get 1 line */
fgets(mbuf,256,fin);
/* judge */
if ( *(mbuf+0) != ':' ) continue ;
/* fprintf(stdout,"%s",mbuf); */
/* counter */
mcnt = get_hex( *(mbuf+1) ); mcnt <<= 4 ;
mcnt += get_hex( *(mbuf+2) );
/* address */
madr = get_hex( *(mbuf+3) ); madr <<= 4 ;
madr += get_hex( *(mbuf+4) ); madr <<= 4 ;
madr += get_hex( *(mbuf+5) ); madr <<= 4 ;
madr += get_hex( *(mbuf+6) );
/* type */
mtype = get_hex( *(mbuf+7) ); mtype <<= 4 ;
mtype += get_hex( *(mbuf+8) );
/* judge */
if ( mtype != 0 ) continue ;
/* loop */
for ( loop = 0 ; loop < mcnt ; loop++ ) {
/* calcualte pointer */
mindex = 9 + loop * 2 ;
/* get data */
mdat = get_hex( *(mbuf+mindex) ) ; mdat <<= 4 ;
mdat += get_hex( *(mbuf+mindex+1) );
/* transfer */
send_dat(madr,mdat);
}
putchar('\n');
}
/* close file */
fclose( fin );
/* CPU access SRAM */
send_hiz(ENABLE_HIZ);
send_reset(DISABLE_RESET);
return 0 ;
}
void send_primitive(UBYTE x)
{
/* impress data */
outp(lpt_address,x);
/* strobe handling */
outp(lpt_address+2,STB_OFF);
outp(lpt_address+2,STB_ON );
outp(lpt_address+2,STB_OFF);
}
void send_write_pulse(void)
{
/* enable nCS */
send_primitive(CON_ADR0 | CSON_WEOFF);
/* enable nWR */
send_primitive(CON_ADR0 | CSON_WEON);
/* disable nWR */
send_primitive(CON_ADR0 | CSON_WEOFF);
/* disable nCS */
send_primitive(CON_ADR0 | CSOFF_WEOFF);
}
void send_reset(UBYTE x)
{
if ( x ) { send_primitive(CON_ADR1 | OFF); }
else { send_primitive(CON_ADR1 | ON ); }
}
void send_hiz(UBYTE x)
{
if ( x ) { send_primitive(0x80 | ON ); }
else { send_primitive(0x80 | OFF); }
}
void send_dat(UWORD ax,UBYTE dx)
{
UBYTE tmpx ;
/* get upper address and put */
tmpx = (ax >> 8) & MASKFF ;
send_primitive(ADRH_HNIBBLE | ((tmpx >> 4) & MASK0F));
send_primitive(ADRH_LNIBBLE | (tmpx & MASK0F));
/* get lower address and put */
tmpx = ax & MASKFF ;
send_primitive(ADRL_HNIBBLE | ((tmpx >> 4) & MASK0F));
send_primitive(ADRL_LNIBBLE | (tmpx & MASK0F));
/* get data and put */
tmpx = dx ;
send_primitive(DAT_HNIBBLE | ((tmpx >> 4) & MASK0F));
send_primitive(DAT_LNIBBLE | (tmpx & MASK0F));
/* store */
send_write_pulse();
}
void send_control(UBYTE dx)
{
send_primitive( dx );
}
UBYTE get_hex(UBYTE x)
{
UBYTE result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
やっていることは、非常に単純です。
パラレルポートのアドレスを1〜3のどれかで指定し
ROMに転送したいHEXファイルから、1バイトずつSRAM
にデータを送っているだけ。
パラレルポートのアドレスは、以下のように決めました。
使うときは、次のようにします。
romenu 1 test.hex{enter}
テスト用に作成したHEXファイルのソースコードは
PIOAから入力したデータを、PIOBに出力する処理
を使います。
CTC0 EQU 10h
CTC1 EQU 11h
CTC2 EQU 12h
CTC3 EQU 13h
SIOAD EQU 18h
SIOAC EQU 19h
SIOBD EQU 1ah
SIOBC EQU 1bh
PIOAD EQU 1ch
PIOAC EQU 1dh
PIOBD EQU 1eh
PIOBC EQU 1fh
org 0h
ld sp,0h
jp START
org 100h
START:
; initialize hardware
call INIT
;***********
; echo back
;***********
MAIN:
; get data from PIOA
in a,(PIOAD)
; put data tor PIOB
out (PIOBD),a
;
jr MAIN
;**********************
; initialize hardware
;**********************
INIT:
; initialize PIO
call INIT_PIO
;
ret
;****************
; initialize PIO
;****************
INIT_PIO:
;
push af
; PIOA (input mode)
ld a,4fh
out (PIOAC),a
; turn off all LEDs
ld a,00h
out (PIOBD),a
; PIOB (output mode)
ld a,0fh
out (PIOBC),a
;
pop af
ret
END
Z80を動かすには、Z80のnRESETを'L'から'H'にします。
nRESET='L'のとき、Z80はアドレス、データ線をハイ
インピーダンスにするので、ROMエミュレータにある
SRAMをCPLDがアクセスするなら、Z80からの制御信号
を切断して対応します。
Z80からは、ROMエミュレータ上のSRAMはリードさえ
出来ればよいので、上の回路でメモリリードだけが
可能となる仕掛けを作ります。
nRESET信号は、CPLDから出力します。
利用するCPLDに、空き容量があったので、上の
回路を入れました。
VHDLコードは、以下です。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity romemu is
port (
-- system
nRESET : in std_logic;
CLOCK : in std_logic;
-- input trigger
TRG : in std_logic ;
-- selector
SEL : in std_logic_vector(3 downto 0);
-- input data
NDAT : in std_logic_vector(3 downto 0);
-- input MREQ and RD
nMREQ : in std_logic ;
nRD : in std_logic ;
nXRESET : in std_logic ;
-- monitor output
TLED : out std_logic ;
--
nMRD : out std_logic ;
-- output
ROUT1 : out std_logic_vector(7 downto 0);
ROUT0 : out std_logic_vector(7 downto 0)-- ;
);
end romemu;
architecture behavioral of romemu is
-- trigger
signal iTRG_SFT : std_logic_vector(2 downto 0);
signal iTRG : std_logic ;
-- internal registers
signal iREG0 : std_logic_vector(7 downto 0);
signal iREG1 : std_logic_vector(7 downto 0);
signal iREGX : std_logic ;
-- sequence
signal iSTATE : std_logic_vector(1 downto 0);
signal iSEL : integer range 0 to 15;
signal iNDAT : std_logic_vector(3 downto 0);
--
signal iMRD : std_logic ;
begin
-- monitor output
TLED <= not iREGX ;
nMRD <= iMRD when ( nXRESET = '1' ) else 'Z' ;
-- input
iNDAT <= NDAT ;
-- output
ROUT1 <= iREG0 when ( iREGX = '1' ) else (others => 'Z') ;
ROUT0 <= iREG1 when ( iREGX = '1' ) else (others => 'Z') ;
iMRD <= nMREQ or nRD ;
-- trigger
process(nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iTRG_SFT <= "000" ;
elsif rising_edge( CLOCK ) then
iTRG_SFT <= iTRG_SFT(1 downto 0) & TRG ;
end if;
end process;
iTRG <= '1' when ( iTRG_SFT = "011" ) else '0' ;
-- master sequencer
process( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iREG0 <= (others => '0') ;
iREG1 <= (others => '0') ;
iREGX <= '0' ;
iSTATE <= "00" ;
iSEL <= 0 ;
elsif rising_edge( CLOCK ) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iTRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- latch data
when 1 => iSTATE <= "11" ;
iSEL <= conv_integer(SEL) ;
-- deliver
when 3 => iSTATE <= "10" ;
if ( iSEL = 0 ) then
iREG0(3 downto 0) <= iNDAT ;
end if ;
if ( iSEL = 1 ) then
iREG0(7 downto 4) <= iNDAT ;
end if ;
if ( iSEL = 2 ) then
iREG1(3 downto 0) <= iNDAT ;
end if ;
if ( iSEL = 3 ) then
iREG1(7 downto 4) <= iNDAT ;
end if ;
if ( iSEL > 7 ) then
iREGX <= iNDAT(0) ;
end if ;
-- return first state
when 2 => iSTATE <= "00" ;
-- default
when others =>
iSTATE <= "00" ;
end case ;
end if;
end process;
end behavioral;
ピン割当ては、次のようにしました。
NET "CLOCK" LOC = "P5";
NET "nRESET" LOC = "P39";
# control
NET "NDAT<0>" LOC = "P24";
NET "NDAT<1>" LOC = "P25";
NET "NDAT<2>" LOC = "P26";
NET "NDAT<3>" LOC = "P27";
NET "SEL<0>" LOC = "P28";
NET "SEL<1>" LOC = "P29";
NET "SEL<2>" LOC = "P33";
NET "SEL<3>" LOC = "P34";
# trigger
NET "TRG" LOC = "P36";
NET "TLED" LOC = "P35";
# data
NET "ROUT0<0>" LOC = "P1" ;
NET "ROUT0<1>" LOC = "P2" ;
NET "ROUT0<2>" LOC = "P3" ;
NET "ROUT0<3>" LOC = "P4" ;
NET "ROUT0<4>" LOC = "P6" ;
NET "ROUT0<5>" LOC = "P7" ;
NET "ROUT0<6>" LOC = "P8" ;
NET "ROUT0<7>" LOC = "P9" ;
# data
NET "ROUT1<0>" LOC = "P11";
NET "ROUT1<1>" LOC = "P12";
NET "ROUT1<2>" LOC = "P13";
NET "ROUT1<3>" LOC = "P14";
NET "ROUT1<4>" LOC = "P18";
NET "ROUT1<5>" LOC = "P19";
NET "ROUT1<6>" LOC = "P20";
NET "ROUT1<7>" LOC = "P22";
#
NET "nMRD" LOC = "P44" ;
NET "nMREQ" LOC = "P43" ;
NET "nRD" LOC = "P42" ;
NET "nXRESET" LOC = "P40" ;
ROMエミュレータは、基板に実装したので、UECかAKI80を
同じ基板に載せて、動かすようにします。今回は、梅澤
無線のUECを、同じ基板に載せます。
UECは、50ピンのコネクタを2つ利用するだけに対して
AKI80は、26ピン、20ピンを使うので、半田付けが面倒
だったことが理由です。
UECには、基板上のROM、RAMを殺して、外部のROM、RAMを
利用するための制御端子があるので、これを使えるのも
魅力でした。
ROMエミュレータの実体はSRAMなので、ROMを殺して
このSRAMをROMに見せるカラクリが用意されている
UECは、制御用としてAKI80にはない設計思想が見え
ます。
メモリ空間に関連する信号ピン割当ては、以下と
なっています。
1 RAMINH 2 ROMINH
3 nINT 4 nHALT
5 nMREQ 6 nIORQ
7 nRD 8 nWR
9 nBUSAK 10 nWAIT
11 nBUSRQ 12 nRESET
13 nM1 14 nRFSH
15 A1 16 A0
17 A3 18 A2
19 A5 20 A4
21 A7 22 A6
23 A9 24 A8
25 A11 26 A10
27 A13 28 A12
29 A15 30 A14
31 D0 32 D1
33 D2 34 D3
35 D4 36 D5
37 D6 38 D7
39 BACKUP 40 CLKOUT
41 nNMI 42 A7RF
43 IEO 44 IEI
45 nWDTOUT 46 nEXRESET
47 EV 48 GND
49 Vcc 50 Vcc
制御は、5、7、8に出ている信号を利用し
アドレスは15から30、データは31から38の
ピンとメモリを接続することに。
I/O処理も必要なので、どのような信号が出て
いるのかを確認します。
1 Vcc 2 GND
3 CLK/TRG0 4 CLK/TRG1
5 CLK/TRG2 6 CLK/TRG3
7 TC/TO3 8 TC/TO2
9 TC/TO1 10 TC/TO0
11 BRDY 12 nBSTB
13 PB7 14 PB6
15 PB5 16 PB4
17 PB3 18 PB2
19 PB1 20 PB0
21 nW/RDYB 22 nSYNCB
23 RxDB 24 nRxCB
25 nTxCB 26 nRSTB
27 nDTRB 28 TxDB
29 nCTSB 30 nDCDB
31 nDCDA 32 nCTSA
33 TxDA 34 nDTRA
35 nRTSA 36 TxCA
37 nRxCA 38 RxDA
39 nSYNCA 40 nW/RDYA
41 PA0 42 PA1
43 PA2 44 PA3
45 PA4 46 PA5
47 PA6 48 PA7
49 nASTB 50 ARDY
パラレルI/Oは、A、Bチャネルあるので
STBとRDYを直結し、単純I/Oとして使い
ます。
シリアルインタフェースは、3線式で
使うこととし、RTSとCTS、DTRとDCDを
直結します。
シリアルインタフェースには、クロックが
必要なので、TxC、RxCを直結します。
タイマーカウンタの出力をTxC、RxCに接続
して、外部クロックジェネレータを設けない
ことに。
TxD、RxDは、次のようにトランジスタを利用し
論理レベルと論理値を反転します。
(小信号トランジスタなら、何でもOK)
(under construction)
目次
前
次