豊四季タイニーベーシック
前回から随分と間が空いてしまいましたが...
豊四季タイニーベーシックを移植しました。
起動時の表示
フロー制御を設定していない場合は、内部コードへの変換に時間がかかる場合に、文字を読み飛ばしてしまう場合がある。
フロー制御を指定
フロー制御を指定すると正常に受信できる。
9600bpsを超える設定でも問題ありません。
実行結果
処理は最適化の余地があるので追々最適化をします。
※コマンドの追加も考えています。
VGA出力
文字サイズ:8x8ドットフォントの下に2ドットの空白で8x10ドット
表示色:文字色8色、背景色8色(VRAM的にはそれぞれ16色に拡張する余裕あり)
カーソル表示:0.8Hzのブリンク表示
画像の真ん中右側の「1」がカーソル位置
5V⇒3.3V変換のための74AC541Pを注文していますので、届いたらユニバーサル基板で拡張ボード化する予定です。
CFボード
CFボードでIdentifyDriveコマンドを実行するプログラムと結果です。
ASSIST09と組み合わせて使用します。
実行結果
SanDiskの512MB CompactFlashです。
CapabilitiesからLBA/DMAに対応していることがわかります。
ソース
1バイト読み込む毎にDRQをチェックするのが正しいようですが、
CPUが遅いためかDRQのチェックを行うと、読み飛ばしが発生するようで、
DRQのチェックを行わずに読み込みを行っています。
-----------------------
CF_PORT EQU $FFB0
CF_DATA EQU (CF_PORT+0) ;DATA
CF_ERR EQU (CF_PORT+1) ;READ:Error Register
CF_FEATURE EQU (CF_PORT+1) ;WRITE:Features
CF_SECT_CNT EQU (CF_PORT+2) ;WRITE:Sector count
CF_LBA0 EQU (CF_PORT+3) ;
CF_LBA1 EQU (CF_PORT+4)
CF_LBA2 EQU (CF_PORT+5)
CF_LBA3 EQU (CF_PORT+6)
CF_STAT EQU (CF_PORT+7) ;READ:status
CF_CMD EQU (CF_PORT+7) ;WRITE:command
ST_ERR EQU $1
ST_DRQ EQU $8
ST_DF EQU $20
ST_RDY EQU $40
ST_BSY EQU $80
ST_DRQ EQU $8
ST_DF EQU $20
ST_RDY EQU $40
ST_BSY EQU $80
DATA_BUF EQU $1000
ORG ROM2OF
CF_TEST ;LDMD #1
LEAX MSG1,PCR
SWI
FCB PDATA1
JSR CF_INIT
LDA #$EC ;EC:Identify Drive
JSR CF_RD_CMD
;General configuration bit-significant information:
LEAX H_INFO,PCR
SWI
FCB PDATA1
LDX #DATA_BUF
SWI
FCB OUT4HS
JSR PRCRLF
;Serial Number
LEAX H_SN,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(10*2))
LDB #20
JSR PUTS
JSR PRCRLF
;Firmware revision
LEAX H_FIRM,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(23*2))
LDB #8
JSR PUTS
JSR PRCRLF
CF_TEST ;LDMD #1
LEAX MSG1,PCR
SWI
FCB PDATA1
JSR CF_INIT
LDA #$EC ;EC:Identify Drive
JSR CF_RD_CMD
;General configuration bit-significant information:
LEAX H_INFO,PCR
SWI
FCB PDATA1
LDX #DATA_BUF
SWI
FCB OUT4HS
JSR PRCRLF
;Serial Number
LEAX H_SN,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(10*2))
LDB #20
JSR PUTS
JSR PRCRLF
;Firmware revision
LEAX H_FIRM,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(23*2))
LDB #8
JSR PUTS
JSR PRCRLF
;Model Number
LEAX H_MODEL,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(27*2))
LDB #40
JSR PUTS
JSR PRCRLF
;Capabilities
LEAX H_CAPA,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(49*2))
SWI
FCB OUT4HS
JSR PRCRLF
;TOTAL SECTORS
LEAX H_SECS,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(60*2))
SWI
FCB OUT4HS
LDX #(DATA_BUF+(61*2))
SWI
FCB OUT4HS
JSR PRCRLF
LEAX H_MODEL,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(27*2))
LDB #40
JSR PUTS
JSR PRCRLF
;Capabilities
LEAX H_CAPA,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(49*2))
SWI
FCB OUT4HS
JSR PRCRLF
;TOTAL SECTORS
LEAX H_SECS,PCR
SWI
FCB PDATA1
LDX #(DATA_BUF+(60*2))
SWI
FCB OUT4HS
LDX #(DATA_BUF+(61*2))
SWI
FCB OUT4HS
JSR PRCRLF
RTS
H_INFO FCC /INFORMATION:/
FCB EOT
H_SN FCC /SERIAL NUMBER:/
FCB EOT
H_FIRM FCC /FIRMWARE VERSION:/
FCB EOT
H_MODEL FCC /MODEL NUMBER:/
FCB EOT
H_CAPA FCC /Capabilities:/
FCB EOT
H_SECS FCC /LBA Total Sectors:/
FCB EOT
H_INFO FCC /INFORMATION:/
FCB EOT
H_SN FCC /SERIAL NUMBER:/
FCB EOT
H_FIRM FCC /FIRMWARE VERSION:/
FCB EOT
H_MODEL FCC /MODEL NUMBER:/
FCB EOT
H_CAPA FCC /Capabilities:/
FCB EOT
H_SECS FCC /LBA Total Sectors:/
FCB EOT
;***************************************************************************
;CF INITIALIZE
;***************************************************************************
CF_INIT JSR CF_WT_BSY
LDA #$E0
STA >CF_LBA3
JSR CF_WT_BSY
LDA #$01
STA >CF_FEATURE
JSR CF_WT_BSY
LDA #$EF ;SET FEATURES
STA >CF_CMD
JSR CF_WT_BSY
RTS
;CF INITIALIZE
;***************************************************************************
CF_INIT JSR CF_WT_BSY
LDA #$E0
STA >CF_LBA3
JSR CF_WT_BSY
LDA #$01
STA >CF_FEATURE
JSR CF_WT_BSY
LDA #$EF ;SET FEATURES
STA >CF_CMD
JSR CF_WT_BSY
RTS
;***************************************************************************
;CF_RD_CMD
;Function: Gets a sector (512 bytes) into RAM buffer.
;***************************************************************************
CF_RD_CMD JSR CF_WT_RDY
STA >CF_CMD
;JSR CF_WT_DRQ
JSR CF_WT_BSY
LDA >CF_STAT
ANDA #ST_ERR
BNE CF_RD_CMD
LDX #DATA_BUF
LDB #0
1 PSHS B
;2 JSR CF_WT_DRQ
;2 JSR CF_WT_BSY
; ANDA #ST_ERR
; BNE 3F
LDA >CF_DATA
LDB >CF_DATA
STB ,X+
STA ,X+
PULS B
DECB
BNE 1B
RTS
;CF_RD_CMD
;Function: Gets a sector (512 bytes) into RAM buffer.
;***************************************************************************
CF_RD_CMD JSR CF_WT_RDY
STA >CF_CMD
;JSR CF_WT_DRQ
JSR CF_WT_BSY
LDA >CF_STAT
ANDA #ST_ERR
BNE CF_RD_CMD
LDX #DATA_BUF
LDB #0
1 PSHS B
;2 JSR CF_WT_DRQ
;2 JSR CF_WT_BSY
; ANDA #ST_ERR
; BNE 3F
LDA >CF_DATA
LDB >CF_DATA
STB ,X+
STA ,X+
PULS B
DECB
BNE 1B
RTS
;WAIT BUSY=0,RDY=1
CF_WT_RDY PSHS A
1 LDA >CF_STAT
ANDA #(ST_BSY+ST_RDY)
EORA #ST_RDY
BNE 1B
PULS A
RTS
CF_WT_RDY PSHS A
1 LDA >CF_STAT
ANDA #(ST_BSY+ST_RDY)
EORA #ST_RDY
BNE 1B
PULS A
RTS
CFボード
仕事が忙しくなかなか時間が取れません。
CFボードを作成しました。
まずはセクタ読み出しのプログラム作成予定。
メモリテスト2
前回のメモリチェックに、アドレス線のチェックと(ほぼ)全領域のチェックを追加してみました。
・アドレス線のチェック
特開平6-110723を参考に作成
・全領域のチェック
$1000~$1FFFに対し順に$55書込・ビットの反転・コンペアを行います。
これを、$8Dを除く、$80~$FFページのすべてに行います。
;CHECK MAPPING
LBSR INITMAP
LEAX CHK1MSG,PCR
SWI
FCB PDATA1
LDA #$80
LOOP1 STA >MAPTABLE
STA >$0000
INCA
BNE LOOP1
LDA #$80
LOOP2 STA >(MAPTABLE+1)
CMPA >$1000
LBNE PERRMSG
INCA
BNE LOOP2
JSR POKMSG
LBSR INITMAP
;CHECK TASK
LEAX CHK2MSG,PCR
SWI
FCB PDATA1
LDB #$0
LDA #$80
LOOP3 STB >UPDTASK
STB >MAPTASK
STA >MAPTABLE
STA >$0000
INCB
INCA
CMPB #8
BCS LOOP3
LDB #0
STB >UPDTASK
LDA #$80
LOOP4 STB >MAPTASK
CMPA >$0000
LBNE PERRMSG
INCB
INCA
CMPB #8
BCS LOOP4
LBSR INITMAP
JSR POKMSG
;CHECK RAM ADDRESS LINE
;特開平6-110723を参考に作成
LEAX CHK3MSG,PCR
SWI
FCB PDATA
;ADDRESS LINE 00001-00800
LDA #0
STA >$0
LDY >$ffe0
LDA #$80
STA ,Y
LDX #$0001
LOOP5 LDA #$ff
STA ,X
LDB >$0
LBNE PERRMSG
TFR X,D
LSLB
ROLA
TFR D,X
CMPD #$1000
BNE LOOP5
;ADDRESS LINE 01000-40000
LDA #$81
LDY #$ffe1
LDX #$1000
LOOP6 STA ,Y
LDB #$ff
STB ,X
LDB >$0
BNE PERRMSG
LSLA
ORA #$80
CMPA #$80
BNE LOOP6
BSR INITMAP
JSR POKMSG
;RAM CHECK
;ALL AREA(without 0D000-0DFFF)
LEAX CHK4MSG,PCR
SWI
FCB PDATA1
LDA #$80
RCLOOP PSHS A
LEAX ,S
SWI
FCB OUT2HS
PULS A
CMPA #$8D
BEQ RCSKIP
;check
STA >(MAPTABLE+1)
LDX #$1000
RCCHKLOOP
BSR CHK1BYT
LBNE PRAMERR
LEAX 1,X
CMPX #$2000
BNE RCCHKLOOP
;OK
PSHS A
LEAX RAMOK,PCR
SWI
FCB PDATA1
PULS A
BRA RCNEXT
RCSKIP PSHS A
LEAX RAMSKIP,PCR
SWI
FCB PDATA1
PULS A
RCNEXT INCA
BNE RCLOOP
BSR INITMAP
LEAX RAMALOK,PCR
SWI
FCB PDATA1
RTS
INITMAP ;reinitialize map
LDA #$0
STA >MAPTASK
STA >UPDTASK
LDA #$80
LDX #$FFE0
IMLOOP STA ,X+
INCA
CMPA #$8E
BNE IMLOOP
RTS
POKMSG LEAX COKMSG,PCR
SWI
FCB PDATA1
RTS
PERRMSG BSR INITMAP
LEAX CERRMSG,PCR
SWI
FCB PDATA1
RTS
PRAMERR BSR INITMAP
LEAX RAMNG,PCR
SWI
FCB PDATA1
RTS
PRCRLF SWI
FCB PCRLF
RTS
CHK1BYT LDB #$55
STB ,X
COM ,X
COMB
CMPB ,X
BNE C1BRTS
LDB #$AA
STB ,X
CMPB ,X
C1BRTS RTS
CHK1MSG FCC /CHECK MAPPING.../
FCB EOT
CHK2MSG FCC /CHECK TASK.../
FCB EOT
CHK3MSG FCC /CHECK ADDRESS LINE.../
FCB EOT
CHK4MSG FCC /CHECK ALL RAM(Without 0D000-0DFFF).../
FCB EOT
COKMSG FCC /OK/
FCB CR,LF
FCB EOT
CERRMSG FCC /ERROR/
FCB CR,LF
FCB EOT
RAMOK FCC /OK /
FCB EOT
RAMNG FCC /NG/
FCB CR,LF
FCB EOT
RAMSKIP FCC /SKIP/
FCB CR,LF
FCB EOT
RAMALOK FCB CR,LF
FCC /RAM ALL OK/
FCB EOT
LBSR INITMAP
;CHECK TASK
LEAX CHK2MSG,PCR
SWI
FCB PDATA1
LDB #$0
LDA #$80
LOOP3 STB >UPDTASK
STB >MAPTASK
STA >MAPTABLE
STA >$0000
INCB
INCA
CMPB #8
BCS LOOP3
LDB #0
STB >UPDTASK
LDA #$80
LOOP4 STB >MAPTASK
CMPA >$0000
LBNE PERRMSG
INCB
INCA
CMPB #8
BCS LOOP4
LBSR INITMAP
JSR POKMSG
;CHECK RAM ADDRESS LINE
;特開平6-110723を参考に作成
LEAX CHK3MSG,PCR
SWI
FCB PDATA
;ADDRESS LINE 00001-00800
LDA #0
STA >$0
LDY >$ffe0
LDA #$80
STA ,Y
LDX #$0001
LOOP5 LDA #$ff
STA ,X
LDB >$0
LBNE PERRMSG
TFR X,D
LSLB
ROLA
TFR D,X
CMPD #$1000
BNE LOOP5
;ADDRESS LINE 01000-40000
LDA #$81
LDY #$ffe1
LDX #$1000
LOOP6 STA ,Y
LDB #$ff
STB ,X
LDB >$0
BNE PERRMSG
LSLA
ORA #$80
CMPA #$80
BNE LOOP6
BSR INITMAP
JSR POKMSG
;RAM CHECK
;ALL AREA(without 0D000-0DFFF)
LEAX CHK4MSG,PCR
SWI
FCB PDATA1
LDA #$80
RCLOOP PSHS A
LEAX ,S
SWI
FCB OUT2HS
PULS A
CMPA #$8D
BEQ RCSKIP
;check
STA >(MAPTABLE+1)
LDX #$1000
RCCHKLOOP
BSR CHK1BYT
LBNE PRAMERR
LEAX 1,X
CMPX #$2000
BNE RCCHKLOOP
;OK
PSHS A
LEAX RAMOK,PCR
SWI
FCB PDATA1
PULS A
BRA RCNEXT
RCSKIP PSHS A
LEAX RAMSKIP,PCR
SWI
FCB PDATA1
PULS A
RCNEXT INCA
BNE RCLOOP
BSR INITMAP
LEAX RAMALOK,PCR
SWI
FCB PDATA1
RTS
INITMAP ;reinitialize map
LDA #$0
STA >MAPTASK
STA >UPDTASK
LDA #$80
LDX #$FFE0
IMLOOP STA ,X+
INCA
CMPA #$8E
BNE IMLOOP
RTS
POKMSG LEAX COKMSG,PCR
SWI
FCB PDATA1
RTS
PERRMSG BSR INITMAP
LEAX CERRMSG,PCR
SWI
FCB PDATA1
RTS
PRAMERR BSR INITMAP
LEAX RAMNG,PCR
SWI
FCB PDATA1
RTS
PRCRLF SWI
FCB PCRLF
RTS
CHK1BYT LDB #$55
STB ,X
COM ,X
COMB
CMPB ,X
BNE C1BRTS
LDB #$AA
STB ,X
CMPB ,X
C1BRTS RTS
CHK1MSG FCC /CHECK MAPPING.../
FCB EOT
CHK2MSG FCC /CHECK TASK.../
FCB EOT
CHK3MSG FCC /CHECK ADDRESS LINE.../
FCB EOT
CHK4MSG FCC /CHECK ALL RAM(Without 0D000-0DFFF).../
FCB EOT
COKMSG FCC /OK/
FCB CR,LF
FCB EOT
CERRMSG FCC /ERROR/
FCB CR,LF
FCB EOT
RAMOK FCC /OK /
FCB EOT
RAMNG FCC /NG/
FCB CR,LF
FCB EOT
RAMSKIP FCC /SKIP/
FCB CR,LF
FCB EOT
RAMALOK FCB CR,LF
FCC /RAM ALL OK/
FCB EOT
メモリテスト
6809アセンブリ言語の勉強と合わせて、
1.メモリマッピング機能のテスト
・0000-0FFFに128ページ分のRAMを順番に割付し、個別の値($80~$FF)を書き込む。
・2000-2FFFに128ページ分のRAMを順番に割付し、書き込んだ値が読み出せることを確認する。
2.8タスク分のマッピングのテスト
・0~7のタスクに対し個別のページを0000-0FFFに割付し、個別の値を書き込む。
・0~7のタスクを選択し、個別に書き込んだ値が読み出せることを確認する。
簡単なプログラムを作成してみました。
ASSIST09から実行します。
LDA #$80
LOOP1 STA >MAPTABLE
STA >$0000
INCA
BNE LOOP1
LDA #$80
LOOP2 STA >(MAPTABLE+1)
CMPA >$1000
BNE PERRMSG
INCA
BNE LOOP2
LDA #$0
JSR POKMSG
LOOP1 STA >MAPTABLE
STA >$0000
INCA
BNE LOOP1
LDA #$80
LOOP2 STA >(MAPTABLE+1)
CMPA >$1000
BNE PERRMSG
INCA
BNE LOOP2
LDA #$0
JSR POKMSG
;CHECK TASK
LEAX CHK2MSG,PCR
SWI
FCB PDATA
LDB #$0
LDA #$80
LOOP3 STB >UPDTASK
STB >MAPTASK
STA >MAPTABLE
STA >$0000
INCB
INCA
CMPB #8
BCS LOOP3
LDB #0
STB >UPDTASK
LDA #$80
LOOP4 STB >MAPTASK
CMPA >$0000
BNE PERRMSG
INCB
INCA
CMPB #8
BCS LOOP4
JSR POKMSG
RTS
POKMSG LEAX COKMSG,PCR
SWI
FCB PDATA
RTS
PERRMSG LEAX CERRMSG,PCR
SWI
FCB PDATA
RTS
LEAX CHK2MSG,PCR
SWI
FCB PDATA
LDB #$0
LDA #$80
LOOP3 STB >UPDTASK
STB >MAPTASK
STA >MAPTABLE
STA >$0000
INCB
INCA
CMPB #8
BCS LOOP3
LDB #0
STB >UPDTASK
LDA #$80
LOOP4 STB >MAPTASK
CMPA >$0000
BNE PERRMSG
INCB
INCA
CMPB #8
BCS LOOP4
JSR POKMSG
RTS
POKMSG LEAX COKMSG,PCR
SWI
FCB PDATA
RTS
PERRMSG LEAX CERRMSG,PCR
SWI
FCB PDATA
RTS
CHK1MSG FCC /CHECK MAPPING.../
FCB EOT
CHK2MSG FCC /CHECK TASK.../
FCB EOT
COKMSG FCC /OK/
FCB CR,LF
FCB EOT
CERRMSG FCC /ERROR/
FCB CR,LF
FCB EOT
FCB EOT
CHK2MSG FCC /CHECK TASK.../
FCB EOT
COKMSG FCC /OK/
FCB CR,LF
FCB EOT
CERRMSG FCC /ERROR/
FCB CR,LF
FCB EOT
--------------------------
簡単なMMU実装完了
マッピングの実装ができました。
簡単なプログラムで簡単な動作確認もできました。
1.機能
・4kb単位でマッピング
・8タスク分のマップ情報を保持(LUT数の限界)
・FFD0:マッピング対象のタスク番号(0~7)
・FFD1:マッピング情報更新対象のタスク番号
・FFE0~FFEF:マッピング情報
00~7F:ROM(SBC6809は8KBが最大なので00~01)
80~FF:RAM(512KBまで可能)
2.動作確認用のBASICソース
8000~8FFFのマッピングを変更しています。
1000 POKE &HFFD0,0
1010 POKE &HFFD1,0
1020 PRINT "&H88"
1030 GOSUB 1160
1040 PRINT "&H90"
1050 POKE &HFFE8,&H90
1060 POKE &H8000,&HAA
1070 GOSUB 1160
1080 POKE &HFFE8,&H88
1090 PRINT "&H88"
1100 GOSUB 1160
1110 POKE &HFFE8,&H90
1120 PRINT "&H90"
1130 GOSUB 1160
1140 POKE &HFFE8,&H88
1150 END
1160 A=&H8000
1170 FOR J=0 TO 3
1180 PRINT RIGHT$("000"+HEX$(A),4);" ";
1190 FOR I=0 TO 15
1200 C=PEEK(A)
1210 PRINT RIGHT$("0"+HEX$(C),2);" ";
1220 A=A+1
1230 NEXT I
1240 PRINT
1250 NEXT J
1260 RETURN
1010 POKE &HFFD1,0
1020 PRINT "&H88"
1030 GOSUB 1160
1040 PRINT "&H90"
1050 POKE &HFFE8,&H90
1060 POKE &H8000,&HAA
1070 GOSUB 1160
1080 POKE &HFFE8,&H88
1090 PRINT "&H88"
1100 GOSUB 1160
1110 POKE &HFFE8,&H90
1120 PRINT "&H90"
1130 GOSUB 1160
1140 POKE &HFFE8,&H88
1150 END
1160 A=&H8000
1170 FOR J=0 TO 3
1180 PRINT RIGHT$("000"+HEX$(A),4);" ";
1190 FOR I=0 TO 15
1200 C=PEEK(A)
1210 PRINT RIGHT$("0"+HEX$(C),2);" ";
1220 A=A+1
1230 NEXT I
1240 PRINT
1250 NEXT J
1260 RETURN
3.動作画面
①初期状態の8000~803Fのメモリダンプを表示
②8000~8FFFのマップを変更後、8000を書き換えし、メモリダンプを表示
③マップを初期状態に戻し、メモリダンプを表示
④再度、マップを変更し、メモリダンプを表示
4.FPGAソース
module MMU(a_in, d_in, e_in, rw_in, rd_in, wr_in, a_out, ce_out);
input wire [15:0] a_in;
input wire [7:0] d_in;
input wire e_in;
input wire rw_in;
input wire rd_in;
input wire wr_in;
//A12-A19を返す
output wire [7:0] a_out;
//CEを返す
//[0]:ROM
//[1]:RAM
//[2]:ACIA-1
//[3]:ACIA-2
//[4]:PTM
//[5]:PIA
//[6]:V9958
output wire [7:0] ce_out;
//FF80-FF8F:PTM
//FF90-FF9F:ACIA-1(6850)
//FFA0-FFAF:PIA
//FFB0-FFBF:ACIA-2(6850)
//FFC0-FFCF:V9958(予定)
//FFD0:マッピング対象タスク(0-31)
//FFD1:マッピングテーブル更新対象タスク(0-31)
//FFE0-FFEF:マッピングテーブル(WriteOnly)
reg [7:0] map [0:127];
reg [2:0] sel_task;//現在選択しているタスク
reg [2:0] upd_task;//マップテーブルを更新するタスク
reg [7:0] a_out_r;
reg [7:0] ce_out_r;
reg [9:0] i;
reg [6:0] index;
initial begin
sel_task = 0;
upd_task = 0;
for (i=0; i<128; i=i+16) begin
//初期メモリ設定
map[i+0] = 8'h80;//0000:RAM
map[i+1] = 8'h81;//1000:RAM
map[i+2] = 8'h82;//2000:RAM
map[i+3] = 8'h83;//3000:RAM
map[i+4] = 8'h84;//4000:RAM
map[i+5] = 8'h85;//5000:RAM
map[i+6] = 8'h86;//6000:RAM
map[i+7] = 8'h87;//7000:RAM
map[i+8] = 8'h88;//8000:RAM
map[i+9] = 8'h89;//9000:RAM
map[i+10] = 8'h8a;//a000:RAM
map[i+11] = 8'h8b;//b000:RAM
map[i+12] = 8'h8c;//c000:RAM
map[i+13] = 8'h8d;//d000:RAM
map[i+14] = 8'h00;//e000:ROM
map[i+15] = 8'h01;//f000:ROM
end
end
function [7:0] CE(
input [15:0] in_address,
input [7:0] out_address
);
case (in_address[15:4])
12'hff8:
//FF80-FF8F:PTM
CE = 8'b11101111;
12'hff9:
//FF90-FF9F:ACIA-1(6850)
CE = 8'b11111011;
12'hffa:
//FFA0-FFAF:PIA
CE = 8'b11011111;
12'hffb:
//FFB0-FFBF:ACIA-2(6850)
CE = 8'b11110111;
12'hffc:
//FFC0-FFCF:V9958
CE = 8'b10111111;
12'hffd:
//FFD0-FFDF:MMU:CEはすべてHIGH
CE = 8'b11111111;
12'hffe:
//FFE0-FFEF:MMU:CEはすべてHIGH
CE = 8'b11111111;
12'hfff:
//FFF0-FFFF:ROM
CE = 8'b11111110;
default:
begin
//最上位bitが0の場合はROM
if (out_address[7] == 1'b0)
CE = 8'b11111110;
else
CE = 8'b11111101;
end
endcase
endfunction
//アドレス変換、および、CE出力
always @(a_in) begin
a_out_r <= map[{sel_task,a_in[15:12]}];
ce_out_r <= CE(a_in, map[{sel_task,a_in[15:12]}]);
end
//FFD0-FFEF:MMU用のI/O
always @(posedge e_in) begin
//eの立下りで取り込む
if(rw_in == 1'b0) begin
if(a_in[15:0] == 16'hffd0) begin
//FF80:マッピング対象タスク選択
sel_task <= d_in[2:0];
end else if(a_in[15:0] == 16'hffd1) begin
//FF81:マッピングテーブル更新対象タスク選択
upd_task <= d_in[2:0];
end else if(a_in[15:4] == 12'hffe) begin
//FF90-FF9Fマッピングテーブル更新
map[{upd_task,a_in[3:0]}] <= d_in;
end
end
end
assign ce_out = ce_out_r;
assign a_out = a_out_r;
endmodule
input wire [15:0] a_in;
input wire [7:0] d_in;
input wire e_in;
input wire rw_in;
input wire rd_in;
input wire wr_in;
//A12-A19を返す
output wire [7:0] a_out;
//CEを返す
//[0]:ROM
//[1]:RAM
//[2]:ACIA-1
//[3]:ACIA-2
//[4]:PTM
//[5]:PIA
//[6]:V9958
output wire [7:0] ce_out;
//FF80-FF8F:PTM
//FF90-FF9F:ACIA-1(6850)
//FFA0-FFAF:PIA
//FFB0-FFBF:ACIA-2(6850)
//FFC0-FFCF:V9958(予定)
//FFD0:マッピング対象タスク(0-31)
//FFD1:マッピングテーブル更新対象タスク(0-31)
//FFE0-FFEF:マッピングテーブル(WriteOnly)
reg [7:0] map [0:127];
reg [2:0] sel_task;//現在選択しているタスク
reg [2:0] upd_task;//マップテーブルを更新するタスク
reg [7:0] a_out_r;
reg [7:0] ce_out_r;
reg [9:0] i;
reg [6:0] index;
initial begin
sel_task = 0;
upd_task = 0;
for (i=0; i<128; i=i+16) begin
//初期メモリ設定
map[i+0] = 8'h80;//0000:RAM
map[i+1] = 8'h81;//1000:RAM
map[i+2] = 8'h82;//2000:RAM
map[i+3] = 8'h83;//3000:RAM
map[i+4] = 8'h84;//4000:RAM
map[i+5] = 8'h85;//5000:RAM
map[i+6] = 8'h86;//6000:RAM
map[i+7] = 8'h87;//7000:RAM
map[i+8] = 8'h88;//8000:RAM
map[i+9] = 8'h89;//9000:RAM
map[i+10] = 8'h8a;//a000:RAM
map[i+11] = 8'h8b;//b000:RAM
map[i+12] = 8'h8c;//c000:RAM
map[i+13] = 8'h8d;//d000:RAM
map[i+14] = 8'h00;//e000:ROM
map[i+15] = 8'h01;//f000:ROM
end
end
function [7:0] CE(
input [15:0] in_address,
input [7:0] out_address
);
case (in_address[15:4])
12'hff8:
//FF80-FF8F:PTM
CE = 8'b11101111;
12'hff9:
//FF90-FF9F:ACIA-1(6850)
CE = 8'b11111011;
12'hffa:
//FFA0-FFAF:PIA
CE = 8'b11011111;
12'hffb:
//FFB0-FFBF:ACIA-2(6850)
CE = 8'b11110111;
12'hffc:
//FFC0-FFCF:V9958
CE = 8'b10111111;
12'hffd:
//FFD0-FFDF:MMU:CEはすべてHIGH
CE = 8'b11111111;
12'hffe:
//FFE0-FFEF:MMU:CEはすべてHIGH
CE = 8'b11111111;
12'hfff:
//FFF0-FFFF:ROM
CE = 8'b11111110;
default:
begin
//最上位bitが0の場合はROM
if (out_address[7] == 1'b0)
CE = 8'b11111110;
else
CE = 8'b11111101;
end
endcase
endfunction
//アドレス変換、および、CE出力
always @(a_in) begin
a_out_r <= map[{sel_task,a_in[15:12]}];
ce_out_r <= CE(a_in, map[{sel_task,a_in[15:12]}]);
end
//FFD0-FFEF:MMU用のI/O
always @(posedge e_in) begin
//eの立下りで取り込む
if(rw_in == 1'b0) begin
if(a_in[15:0] == 16'hffd0) begin
//FF80:マッピング対象タスク選択
sel_task <= d_in[2:0];
end else if(a_in[15:0] == 16'hffd1) begin
//FF81:マッピングテーブル更新対象タスク選択
upd_task <= d_in[2:0];
end else if(a_in[15:4] == 12'hffe) begin
//FF90-FF9Fマッピングテーブル更新
map[{upd_task,a_in[3:0]}] <= d_in;
end
end
end
assign ce_out = ce_out_r;
assign a_out = a_out_r;
endmodule