├── doc
├── .gitignore
├── system_design_spec.pdf
└── papiGB_design_document.md
├── sim
├── generated_frames
│ └── .gitignore
├── signals
│ ├── mmu_cpu_gpu_sel
│ ├── dzcpu_states
│ ├── gpu_dst
│ ├── gpu_uop
│ ├── timer_states
│ ├── dzcpu_reg_select
│ ├── gpu_src
│ ├── flow_ids
│ ├── dzcpu_uop_cmd
│ └── tb_simple_dzcpu.gtkw
├── .gitignore
├── Makefile
├── resources
│ ├── tetris_oam_fe00_fe9f.dump
│ └── zelda_game_scene_1_oam_fe00_fe9f.dump
└── reference
│ └── bios_vram_9800_9bff.dump
├── tests
└── asm
│ ├── .gitignore
│ ├── test_PUSHDE.asm
│ ├── test_ANDn2.asm
│ ├── test_SUBn.asm
│ ├── test_CPn.asm
│ ├── test_SUBr_a.asm
│ ├── test_ADDn.asm
│ ├── test_LDHLmr_h.asm
│ ├── test_LDHLmr_l.asm
│ ├── test_XORan.asm
│ ├── test_DECBC.asm
│ ├── test_DECDE.asm
│ ├── test_DECHL.asm
│ ├── test_INCBC.asm
│ ├── test_INCDE.asm
│ ├── test_INCHL.asm
│ ├── test_INCSP.asm
│ ├── test_SUBAn.asm
│ ├── test_JRNCn2.asm
│ ├── test_LDHLDA.asm
│ ├── test_LDIOnA.asm
│ ├── test_RLCA.asm
│ ├── test_RRA.asm
│ ├── test_RRc.asm
│ ├── test_push-pop_bc.asm
│ ├── test_CB_SHL_b_2.asm
│ ├── test_ADDr_a.asm
│ ├── test_DECSP.asm
│ ├── test_ORr_a.asm
│ ├── test_XORr_a.asm
│ ├── test_LDHLmr_a.asm
│ ├── test_LDHLmr_b.asm
│ ├── test_LDHLmr_c.asm
│ ├── test_LDHLmr_d.asm
│ ├── test_LDHLmr_e.asm
│ ├── test_LDSPHL.asm
│ ├── test_PUSHHL_POPHL.asm
│ ├── test_ANDn.asm
│ ├── test_ANDr_a.asm
│ ├── test_CB_SHL_b.asm
│ ├── test_PUSHDE_POPDE.asm
│ ├── test_SBCr_a.asm
│ ├── test_LDrr_aa.asm
│ ├── test_LDrr_ha.asm
│ ├── test_LDrr_hb.asm
│ ├── test_LDrr_hc.asm
│ ├── test_LDrr_hd.asm
│ ├── test_LDrr_he.asm
│ ├── test_LDrr_hh.asm
│ ├── test_LDrr_hl.asm
│ ├── test_PUSHAF.asm
│ ├── test_ADCr_a.asm
│ ├── test_ADDr_h.asm
│ ├── test_JPCnn.asm
│ ├── test_JRNCn.asm
│ ├── test_ORr_b.asm
│ ├── test_ORr_c.asm
│ ├── test_ORr_d.asm
│ ├── test_ORr_h.asm
│ ├── test_ORr_l.asm
│ ├── test_SUBr_b.asm
│ ├── test_SUBr_c.asm
│ ├── test_ADDr_e.asm
│ ├── test_ADDr_l.asm
│ ├── test_LDIOCA.asm
│ ├── test_ORr_e.asm
│ ├── test_SUBr_d.asm
│ ├── test_SUBr_h.asm
│ ├── test_XORr_b.asm
│ ├── test_XORr_c.asm
│ ├── test_XORr_d.asm
│ ├── test_XORr_e.asm
│ ├── test_XORr_h.asm
│ ├── test_XORr_l.asm
│ ├── test_ADDr_b.asm
│ ├── test_ADDr_c.asm
│ ├── test_JPHL.asm
│ ├── test_JPNZnn.asm
│ ├── test_SUBr_l.asm
│ ├── test_ADDr_d.asm
│ ├── test_ADDr_d_2.asm
│ ├── test_ANDr_b.asm
│ ├── test_ANDr_c.asm
│ ├── test_ANDr_d.asm
│ ├── test_ANDr_e.asm
│ ├── test_ANDr_h.asm
│ ├── test_ANDr_l.asm
│ ├── test_INCr_b.asm
│ ├── test_JPZnn.asm
│ ├── test_LDrr_ab.asm
│ ├── test_LDrr_ac.asm
│ ├── test_LDrr_ad.asm
│ ├── test_LDrr_ae.asm
│ ├── test_LDrr_ah.asm
│ ├── test_LDrr_al.asm
│ ├── test_LDrr_da.asm
│ ├── test_LDrr_la.asm
│ ├── test_LDrr_lh.asm
│ ├── test_LDrr_ll.asm
│ ├── test_ORn.asm
│ ├── test_LDrr_ba.asm
│ ├── test_LDrr_bb.asm
│ ├── test_LDrr_bc.asm
│ ├── test_LDrr_ca.asm
│ ├── test_LDrr_cb.asm
│ ├── test_LDrr_cc.asm
│ ├── test_SBCn.asm
│ ├── test_DECr_a.asm
│ ├── test_INCr_a.asm
│ ├── test_DECr_b.asm
│ ├── test_SUBr_e.asm
│ ├── test_INCr_c.asm
│ ├── test_LDrr_db.asm
│ ├── test_LDrr_dc.asm
│ ├── test_LDrr_dd.asm
│ ├── test_LDrr_de.asm
│ ├── test_LDrr_dh.asm
│ ├── test_LDrr_dl.asm
│ ├── test_LDrr_eb.asm
│ ├── test_LDrr_ec.asm
│ ├── test_LDrr_ed.asm
│ ├── test_LDrr_eh.asm
│ ├── test_LDrr_el.asm
│ ├── test_LDrr_lb.asm
│ ├── test_LDrr_lc.asm
│ ├── test_LDrr_ld.asm
│ ├── test_LDrr_le.asm
│ ├── test_RETI.asm
│ ├── test_ADDHLSP.asm
│ ├── test_DECr_d.asm
│ ├── test_DECr_h.asm
│ ├── test_INCr_d.asm
│ ├── test_INCr_h.asm
│ ├── test_LDrr_ea.asm
│ ├── test_LDrr_ee.asm
│ ├── test_DECr_c.asm
│ ├── test_DECr_e.asm
│ ├── test_DECr_l.asm
│ ├── test_INCr_b_flags.asm
│ ├── test_INCr_e.asm
│ ├── test_INCr_l.asm
│ ├── test_LDrr_bd.asm
│ ├── test_LDrr_be.asm
│ ├── test_LDrr_bh.asm
│ ├── test_LDrr_bl.asm
│ ├── test_LDrr_cd.asm
│ ├── test_LDrr_ce.asm
│ ├── test_LDrr_ch.asm
│ ├── test_LDrr_cl.asm
│ ├── test_JRCn.asm
│ ├── test_SBCr_b.asm
│ ├── test_SBCr_c.asm
│ ├── test_SBCr_d.asm
│ ├── test_SBCr_e.asm
│ ├── test_SBCr_h.asm
│ ├── test_SBCr_l.asm
│ ├── test_ORHL.asm
│ ├── test_ADCr_b.asm
│ ├── test_ADCr_c.asm
│ ├── test_ADCr_d.asm
│ ├── test_ADCr_e.asm
│ ├── test_ADCr_h.asm
│ ├── test_ADCr_l.asm
│ ├── test_INCr_c_flags.asm
│ ├── test_RETC.asm
│ ├── test_JRn.asm
│ ├── test_INCHLm.asm
│ ├── test_CALLNZnn.asm
│ ├── test_LDrHLm_b.asm
│ ├── test_LDrHLm_c.asm
│ ├── test_LDrHLm_d.asm
│ ├── test_LDrHLm_e.asm
│ ├── test_LDrHLm_h.asm
│ ├── test_LDrHLm_l.asm
│ ├── test_LDABCm.asm
│ ├── test_LDADEm.asm
│ ├── test_LDrHLm_a.asm
│ └── README
├── script
├── create_gb_from_asm.sh
├── run_gearboysim.sh
├── create_dump_from_hex.pl
└── check_bios_log.py
├── .travis.yml
├── ucf
├── pgb_vga.ucf
└── pgb_lcd.ucf
├── rtl
├── sound_controller_modules
│ ├── tb_simple_mx.v
│ ├── SoundControllerOSC2.v
│ ├── SoundControllerOSC1.v
│ ├── tb_simple_channel2.v
│ ├── tb_simple_channel4.v
│ ├── tb_simple_channel3.v
│ ├── tb_simple_channel1.v
│ ├── SoundControllerMX.v
│ ├── SoundControllerChannel2.v
│ ├── SoundControllerChannel1.v
│ ├── SoundControllerChannel3.v
│ └── SoundControllerChannel4.v
├── aDefinitions.v
├── interrupts.v
├── io.v
├── gpu_definitions.v
├── VgaController.v
├── pGB.v
├── bios.v
└── gpu_ucode_rom.v
├── tb
└── tb_simple_io.v
├── cad
└── papiGB.scad
└── README.md
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | *.docx
2 |
--------------------------------------------------------------------------------
/sim/generated_frames/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sim/signals/mmu_cpu_gpu_sel:
--------------------------------------------------------------------------------
1 | 0 bus_owner_cpu
2 | 1 bus_owner_gpu
3 |
--------------------------------------------------------------------------------
/tests/asm/.gitignore:
--------------------------------------------------------------------------------
1 | *.dump
2 | *.gb
3 | *.hex
4 | *.map
5 | *.obj
6 | *.sym
7 |
--------------------------------------------------------------------------------
/sim/signals/dzcpu_states:
--------------------------------------------------------------------------------
1 | 0 AFTER_RESET
2 | 1 START_FLOW
3 | 2 RUN_FLOW
4 | 3 END_FLOW
5 |
--------------------------------------------------------------------------------
/doc/system_design_spec.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegovalverde/papiGB/HEAD/doc/system_design_spec.pdf
--------------------------------------------------------------------------------
/sim/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.vcd
3 | *.dump
4 | *.ppm
5 | *.swp
6 | *.swap
7 | ise/
8 | tb_simple_dzcpu
9 |
--------------------------------------------------------------------------------
/sim/signals/gpu_dst:
--------------------------------------------------------------------------------
1 | 12 vmem_addr
2 | 13 wBh
3 | 14 wBl
4 | 15 bg_buffer_block_sel
5 | 16 state
6 | 17 r0
7 | 18 r1
8 | 19 r2
9 |
--------------------------------------------------------------------------------
/sim/signals/gpu_uop:
--------------------------------------------------------------------------------
1 | 0 nop
2 | 1 wrl
3 | 2 wrr
4 | 3 add
5 | 4 sub
6 | 5 addl
7 | 6 jnz
8 | 7 wbg
9 | 8 subl
10 | 9 rvmem
11 | 10 shl
12 |
--------------------------------------------------------------------------------
/script/create_gb_from_asm.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | rgbasm -o ${1}.obj ../tests/asm/${1}.asm
4 | rgblink -m ${1}.map -n ${1}.sym -o ${1}.gb ${1}.obj
5 |
--------------------------------------------------------------------------------
/sim/signals/timer_states:
--------------------------------------------------------------------------------
1 | 0 AFTER_RESET
2 | 1 WAIT_FOR_TICK
3 | 2 INC
4 | 3 INC_BTAKEN
5 | 4 INC_BTAKEN_NOT_EOF
6 | 5 WAIT_EOF
7 |
8 |
--------------------------------------------------------------------------------
/tests/asm/test_PUSHDE.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | ld d, 10
4 | ld e, 25
5 | push de
6 | ;the expected value in the stack is 1025
7 |
--------------------------------------------------------------------------------
/sim/signals/dzcpu_reg_select:
--------------------------------------------------------------------------------
1 | 0 b
2 | 1 c
3 | 2 d
4 | 3 e
5 | 4 h
6 | 5 l
7 | 6 hl
8 | 7 a
9 | 8 pc
10 | 9 sp
11 | 10 spl
12 | 11 sph
13 | 12 x8
14 | 13 x16
15 | 14 io_c
16 | 15 de
--------------------------------------------------------------------------------
/tests/asm/test_ANDn2.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $1
7 | and a, $10
8 | ;af=$00a0
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $df
7 | sub a, $5
8 | ;af=$da40
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_CPn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | cp a, $90
8 | ;the value af=$0050
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, 20
7 | sub a
8 | ; A=0, flags Z=1, H=1, C=1
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $f8
7 | add $8
8 | ;the value expected is 00b0
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld [hl],h
7 | dec hl
8 | ld [hl],h
9 | ;the value expected is $FFFF
10 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld [hl],l
7 | dec hl
8 | ld [hl],l
9 | ;the value expected is $FDFC
10 |
--------------------------------------------------------------------------------
/tests/asm/test_XORan.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $7F
7 | xor a, $ED
8 | ;the value expected is af=$9200
9 | push af
10 |
--------------------------------------------------------------------------------
/tests/asm/test_DECBC.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld bc, $cafe
7 | dec bc
8 | ;the value expected is $cafd not flags affected
9 | push bc
10 |
--------------------------------------------------------------------------------
/tests/asm/test_DECDE.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld de, $cafe
7 | dec de
8 | ;the value expected is $cafd not flags affected
9 | push de
10 |
--------------------------------------------------------------------------------
/tests/asm/test_DECHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, $cafe
7 | dec hl
8 | ;the value expected is $cafd not flags affected
9 | push hl
10 |
--------------------------------------------------------------------------------
/tests/asm/test_INCBC.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld bc, $cafd
7 | inc bc
8 | ;the value expected is $cafe not flags affected
9 | push bc
10 |
--------------------------------------------------------------------------------
/tests/asm/test_INCDE.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld de, $ffff
7 | inc de
8 | ;the value expected is $0000 not flags affected
9 | push de
10 |
--------------------------------------------------------------------------------
/tests/asm/test_INCHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, $00ff
7 | inc hl
8 | ;the value expected is $0100 not flags affected
9 | push hl
10 |
--------------------------------------------------------------------------------
/tests/asm/test_INCSP.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFD
6 | ld hl, $ffff
7 | inc sp
8 | ;the value expected is $ffff not flags affected
9 | push hl
10 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBAn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0
7 | sub a, $88
8 |
9 | ;the value expected is bc=$7870
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_JRNCn2.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ;af = $da40
6 | jr nc, end
7 |
8 | ld a, $80
9 | ;the value expected is af=$8040
10 | end:
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLDA.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld a, $15
7 |
8 | ldd [hl],a
9 | ldd [hl],a
10 | ;the value expected is $1515
11 |
--------------------------------------------------------------------------------
/tests/asm/test_LDIOnA.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 |
6 | ld a, $35
7 | ld [$FF00+$FD],a
8 | dec a
9 | ld [$FF00+$FC],a
10 | ;the value expected is $3534
11 |
--------------------------------------------------------------------------------
/tests/asm/test_RLCA.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ;f = 70
6 | ld a, $88
7 | ld sp, $FFFE
8 | rlca
9 | ;the value expected is af=$1110
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_RRA.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ;f = 70
6 | ld a, $fe
7 | ld sp, $FFFE
8 | rr a
9 | ;the value expected is af=$ff40
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_RRc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld c, $ff
7 | rr c
8 | ld a, c
9 | ;the value expected is bc=$ff10
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_push-pop_bc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | ld b, 8
4 | ld c, 7
5 | push bc
6 | ld b, 6
7 | nop
8 | pop bc
9 | ;the value expected is b=8 and c=7
10 | nop
11 |
--------------------------------------------------------------------------------
/tests/asm/test_CB_SHL_b_2.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld b, $FF
7 | srl b
8 | ld a, b
9 | ;the value expected is bc=$7f10
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $02
7 | or a,a
8 | nop
9 | add a, a
10 | ;the value expected is 4
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_DECSP.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFF
6 | dec sp
7 | ld hl, $cafa
8 | dec hl
9 | ;the value expected is $caf9 not flags affected
10 | push hl
11 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | or a, a
8 | ;the value expected is $20 with flasgs Z=0
9 | ;af=$8000
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | xor a, a
8 | ;the value expected is $00 with flasgs Z=1
9 | ;af=$0080
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld a, $95
7 | ld [hl],a
8 | dec hl
9 | dec a
10 | ld [hl],a
11 | ;the value expected is $9594
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld b, $50
7 | ld [hl],b
8 | dec hl
9 | dec b
10 | ld [hl],b
11 | ;the value expected is $504f
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld c, $f2
7 | ld [hl],c
8 | dec hl
9 | dec c
10 | ld [hl],c
11 | ;the value expected is $f2f1
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld d, $11
7 | ld [hl],d
8 | dec hl
9 | dec d
10 | ld [hl],d
11 | ;the value expected is $1110
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDHLmr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld e, $23
7 | ld [hl],e
8 | dec hl
9 | dec e
10 | ld [hl],e
11 | ;the value expected is $2322
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDSPHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFE
6 |
7 | ld a, 1
8 | or a,a
9 |
10 | ld sp,hl
11 |
12 | push af
13 |
14 | ;the value expected is $0100
15 |
--------------------------------------------------------------------------------
/tests/asm/test_PUSHHL_POPHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | ld l, 7
4 | ld h, 3
5 | push hl
6 | ld l, 0
7 | nop
8 | pop hl
9 | ;the expected value in l= 7 and h=3
10 | nop
11 | nop
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | - sudo apt-get update -qq
3 | - sudo apt-get install -qq iverilog
4 | - chmod +x script/ci_script.sh
5 |
6 | install: true
7 |
8 | script:
9 | - script/ci_script.sh
10 |
11 | after_failure: true
12 |
13 | after_script: true
14 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $ff
7 | and a, $15
8 | ;the value expected is $00 with flasgs Z=0 N=0 H=1 C=0
9 | ;af=$1520
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $20
7 | and a, a
8 | ;the value expected is $20 with flasgs Z=0 N=0 H=1 C=0
9 | ;af=$2020
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_CB_SHL_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld b, $0F
7 | ld c, $00
8 | srl b
9 | ld a, b
10 | ;the value expected is bc=$0710
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_PUSHDE_POPDE.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | ld d, 10
4 | ld e, 25
5 | push de
6 | ld d, 0
7 | nop
8 | pop de
9 | ;the expected value in d= 10 and e=25
10 | nop
11 | nop
12 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0F
7 | or a,a
8 | nop
9 | sbc a, a
10 | ;Expected Z=1 N=1 H=0 C=0 -- AF=00C0
11 | push af
12 |
--------------------------------------------------------------------------------
/sim/signals/gpu_src:
--------------------------------------------------------------------------------
1 | 0 null
2 | 12 vmem_addr
3 | 13 bh
4 | 14 bl
5 | 15 bg_buffer_block_sel
6 | 1 state
7 | 16 cur_tile
8 | 17 r1
9 | 18 r2
10 | 19 r3
11 | 20 vmem_data
12 | 21 bgmoffset
13 | 22 bg_col_offset
14 | 23 bgtoffset
15 | 24 ly_mod_8
16 | 25 vmem_data_shl_4
17 |
18 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_aa.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $12
7 | or a,a ;borra las banderas
8 |
9 | ld a, a
10 | push af
11 |
12 | ;the value expected is $1200
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ha.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld a, $08
9 |
10 | ld h, a
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_hb.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld b, $08
9 |
10 | ld h, b
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_hc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld c, $08
9 |
10 | ld h, c
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_hd.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld d, $08
9 |
10 | ld h, d
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_he.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld e, $08
9 |
10 | ld h, e
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_hh.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld h, $08
9 |
10 | ld h, h
11 | push hl
12 | ;the value expected is $0834
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_hl.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $3634
8 | ld l, $08
9 |
10 | ld h, l
11 | push hl
12 | ;the value expected is $0808
13 |
--------------------------------------------------------------------------------
/tests/asm/test_PUSHAF.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $dffb
6 | ld a, $1b
7 | push af
8 | nop
9 | ld a,$ff
10 | sub a,$ff
11 | nop
12 | nop
13 | pop af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0F
7 | or a,a
8 | nop
9 | adc a, a
10 | ;the value expected is a=$1E and f=$20 af=$1E20
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0F
7 | ld h, $1F
8 | add a, h
9 | ;the value expected is $2E with flags H = 1
10 | ;$2E20
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_JPCnn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $ff
7 | add $01
8 | jp c, carry_label
9 | ld a, $07
10 | carry_label:
11 | ;expected $00b0
12 | push af
13 |
--------------------------------------------------------------------------------
/tests/asm/test_JRNCn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0
7 | rr a
8 | jr nc, end
9 |
10 | ld a, $cc
11 | ;the value expected is af=$8000
12 | end:
13 | push af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $39
7 | ld b, $aa
8 | or a, b
9 | ;the value expected is $bb with flasgs $00
10 | ;af=$bb00
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $77
7 | ld c, $ca
8 | or a, c
9 | ;the value expected is $52 with flasgs Z=0
10 | ;af=$ff00
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | ld d, $00
8 | or a, d
9 | ;the value expected is $67 with flasgs Z=1
10 | ;af=$0080
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $e6
7 | ld h, $a9
8 | or a, h
9 | ;the value expected is $ef with flasgs Z=0
10 | ;af=$ef00
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | ld l, $00
8 | or a, l
9 | ;the value expected is $00 with flasgs Z=1
10 | ;af=$0080
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, 0
7 | ld b, 1
8 | sub a, b
9 | ;Expected A =-1. Flags Z=0, N=1, H=1, C=1.
10 | ; AF = FF70
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, 20
7 | ld c, 20
8 | sub a, c
9 | ;Expected A=0. Flags Z=1, N=1, H=0, C=0.
10 | ; AF = FFC0
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $f0
7 | ld e, $10
8 | add a, e
9 | ;the value expected is $00 with flags Z=1 C=1
10 | ;af=0090
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $81
7 | ld l, $0F
8 | add a, l
9 | ;the value expected is $90 with flags H=1
10 | ;af=$9020
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDIOCA.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 |
6 | ld a, $85
7 | ld c, $FD
8 | ld [$FF00+c],a
9 | ld a, $25
10 | dec c
11 | ld [$FF00+c],a
12 | ;the value expected is $8525
13 |
--------------------------------------------------------------------------------
/tests/asm/test_ORr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $11
7 | ld e, $10
8 | or a, e
9 | ;the value expected is $11 with flasgs $0000
10 | ;af=$1100
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $50
7 | ld d, $0F
8 | sub a, d
9 | ;Expected A = 41, Flags Z=0, N=1, H=1, C=0
10 | ; AF = $4160
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $A
7 | ld h, 0
8 | sub a, h
9 | ;Expected: A = $0A, Flags Z=0, N=1, H=0, C=0
10 | ; AF = $0A40
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $39
7 | ld b, $aa
8 | xor a, b
9 | ;the value expected is $93 with flasgs $00
10 | ;af=$9300
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $77
7 | ld c, $ca
8 | xor a, c
9 | ;the value expected is $bd with flasgs Z=0
10 | ;af=$bd00
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | ld d, $00
8 | xor a, d
9 | ;the value expected is $67 with flasgs Z=1
10 | ;af=$0080
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $11
7 | ld e, $10
8 | xor a, e
9 | ;the value expected is $01 with flasgs $0000
10 | ;af=$0100
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $e6
7 | ld h, $a9
8 | xor a, h
9 | ;the value expected is $ef with flasgs Z=0
10 | ;af=$4f00
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_XORr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $a9
7 | ld l, $a9
8 | xor a, l
9 | ;the valu1e expected is $ef with flasgs Z=0
10 | ;af=$0080
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $ff
7 | ld b, $01
8 | add a, b
9 | ;the value expected is 00 - with Flags Z-H-C = 1
10 | ;af=00b0
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0F
7 | ld c, $05
8 | add a, c
9 | ;the value expected is D-20 H-$14 with flags H = 1
10 | ;af=$1420
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_JPHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0F
7 | ld hl, da_label
8 | jp hl
9 | or a,a
10 | nop
11 | da_label:
12 | ;expected $0fbe
13 | push af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_JPNZnn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $FF
7 | or a,$ff
8 | jp nz, da_label
9 | or a,a
10 | nop
11 | da_label:
12 | ;expected $0fbe
13 | push af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | ld l, $0B
8 | sub a, l
9 | ;Expected: A = $F5, Flags Z=0, N=1, H=1, C=1
10 | ; AF = $F570
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $ff
7 | ld d, $11
8 | add a, d
9 | ;the value expected is D17 Hex-$10 with flags C=1 H=1
10 | ;af=$1030
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDr_d_2.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $02
7 | ld d, $ff
8 | add a, d
9 | ;the value expected is D17 Hex-$10 with flags C=1 H=1
10 | ;af=$1030
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $29
7 | ld b, $a8
8 | and a, b
9 | ;the value expected is $28 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$2820
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $77
7 | ld c, $5a
8 | and a, c
9 | ;the value expected is $52 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$5220
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $ff
7 | ld d, $67
8 | and a, d
9 | ;the value expected is $67 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$6720
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $20
7 | ld e, $49
8 | and a, e
9 | ;the value expected is $00 with flasgs Z=1 N=0 H=1 C=0
10 | ;af=$00a0
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $e6
7 | ld h, $a1
8 | and a, h
9 | ;the value expected is $a0 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$a020
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_ANDr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $71
7 | ld l, $2f
8 | and a, l
9 | ;the value expected is $21 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$2120
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $00
9 | ld c, $00
10 | inc b
11 | ;Expected BC = $0100
12 | push bc ; Tests BC
13 |
--------------------------------------------------------------------------------
/tests/asm/test_JPZnn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | and a,$ff
8 | jp z, zero_label
9 | ld a, $ff
10 | nop
11 | zero_label:
12 | ;expected $00a0
13 | push af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ab.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld b, $55
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, b
11 | push af
12 |
13 | ;the value expected is $5500
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ac.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld c, $90
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, c
11 | push af
12 |
13 | ;the value expected is $9000
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ad.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld d, $13
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, d
11 | push af
12 |
13 | ;the value expected is $1300
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ae.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld e, $33
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, e
11 | push af
12 |
13 | ;the value expected is $3300
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ah.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld h, $77
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, h
11 | push af
12 |
13 | ;the value expected is $7700
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_al.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld l, $26
7 | ld a, $12
8 | or a,a ;borra las banderas
9 |
10 | ld a, l
11 | push af
12 |
13 | ;the value expected is $2600
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_da.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $1313
8 | or a,a ;borra las banderas
9 |
10 | ld d, a
11 | push de
12 | ;the value expected is $1513
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_la.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $2120
8 | or a,a ;borra las banderas
9 |
10 | ld l, a
11 | push hl
12 | ;the value expected is $2115
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_lh.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $6463
8 | or a,a ;borra las banderas
9 |
10 | ld l, h
11 | push hl
12 | ;the value expected is $6464
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ll.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $7902
8 | or a,a ;borra las banderas
9 |
10 | ld l, l
11 | push hl
12 | ;the value expected is $7902
13 |
--------------------------------------------------------------------------------
/tests/asm/test_ORn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $01
7 | or a, a
8 | or a, $15
9 | ;the value expected is $00 with flasgs Z=0 N=0 H=1 C=0
10 | ;af=$1500
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ba.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | or a,a ;borra las banderas
9 |
10 | ld b, a
11 | push bc
12 |
13 | ;the value expected is $1597
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_bb.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $9745
8 | or a,a ;borra las banderas
9 |
10 | ld b, b
11 | push bc
12 |
13 | ;the value expected is $4545
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_bc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $9895
8 | or a,a ;borra las banderas
9 |
10 | ld b, c
11 | push bc
12 |
13 | ;the value expected is $9595
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ca.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $3634
8 | or a,a ;borra las banderas
9 |
10 | ld c, a
11 | push bc
12 |
13 | ;the value expected is $3615
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_cb.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | or a,a ;borra las banderas
9 |
10 | ld c, b
11 | push bc
12 |
13 | ;the value expected is $8888
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_cc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $1587
8 | or a,a ;borra las banderas
9 |
10 | ld c, c
11 | push bc
12 |
13 | ;the value expected is $1587
14 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $0
7 | or a,a
8 | ld a, $FF
9 | add a,$03
10 | nop
11 | sbc a, $01
12 | ;Expected C=1 -- AF=00C0
13 | push af
14 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld a, $10
9 | dec a ;Expected: AF = $0F03, Flags Z=0, N=1, H=1, C=1
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld a, $0F
9 | inc a ;Expected: AF = $1003, Flags Z=0, N=0, H=1, C=1
10 | push af
11 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $01
9 | ld c, $00
10 | dec b
11 | ;Expected BC = $0000, Flags Z=1, N=1, H=0, C=0
12 | push bc
13 |
--------------------------------------------------------------------------------
/tests/asm/test_SUBr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00 ; 0000 0000
7 | ld e, $80 ; 1000 0000
8 | sub a, e
9 | ;Expected: A=$80, Flags Z=0, N=1, H=0, C=1
10 | ;AF = $8050
11 | push af
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $00
9 | ld c, $FF
10 | inc c
11 | ;Expected BC = $0000
12 | push bc ; Tests BC
13 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_db.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $8782
8 | ld b, $11
9 | or a,a ;borra las banderas
10 |
11 | ld d, b
12 | push de
13 | ;the value expected is $1182
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_dc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld c, $47
9 | or a,a ;borra las banderas
10 |
11 | ld d, c
12 | push de
13 | ;the value expected is $4734
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_dd.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld d, $52
9 | or a,a ;borra las banderas
10 |
11 | ld d, d
12 | push de
13 | ;the value expected is $5234
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_de.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld d, $52
9 | or a,a ;borra las banderas
10 |
11 | ld d, e
12 | push de
13 | ;the value expected is $3434
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_dh.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld h, $33
9 | or a,a ;borra las banderas
10 |
11 | ld d, h
12 | push de
13 | ;the value expected is $3334
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_dl.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld l, $66
9 | or a,a ;borra las banderas
10 |
11 | ld d, l
12 | push de
13 | ;the value expected is $6634
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_eb.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld b, $47
9 | or a,a ;borra las banderas
10 |
11 | ld e, b
12 | push de
13 | ;the value expected is $3647
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ec.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld c, $89
9 | or a,a ;borra las banderas
10 |
11 | ld e, c
12 | push de
13 | ;the value expected is $3689
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ed.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld d, $89
9 | or a,a ;borra las banderas
10 |
11 | ld e, d
12 | push de
13 | ;the value expected is $8989
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_eh.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld h, $77
9 | or a,a ;borra las banderas
10 |
11 | ld e, h
12 | push de
13 | ;the value expected is $3677
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_el.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ld l, $08
9 | or a,a ;borra las banderas
10 |
11 | ld e, l
12 | push de
13 | ;the value expected is $3608
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_lb.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $6463
8 | ld b, $60
9 | or a,a ;borra las banderas
10 |
11 | ld l, b
12 | push hl
13 | ;the value expected is $6460
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_lc.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $6463
8 | ld c, $70
9 | or a,a ;borra las banderas
10 |
11 | ld l, c
12 | push hl
13 | ;the value expected is $6470
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ld.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $6463
8 | ld d, $80
9 | or a,a ;borra las banderas
10 |
11 | ld l, d
12 | push hl
13 | ;the value expected is $6480
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_le.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld hl, $6463
8 | ld e, $85
9 | or a,a ;borra las banderas
10 |
11 | ld l, e
12 | push hl
13 | ;the value expected is $6485
14 |
--------------------------------------------------------------------------------
/tests/asm/test_RETI.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, int_label
7 | push hl
8 | reti
9 | jp end_label
10 | int_label:
11 | ld hl, $71CE
12 | end_label:
13 | ;expected $71CE
14 | push hl
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADDHLSP.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $1
7 | or a, a
8 | ld a, $0
9 | nop
10 | ld hl, $0001
11 | add hl,sp
12 | or a,l
13 | ;the value expected is $FF00
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld d, $10
9 | ld e, $00
10 | dec d ;Expected: DE = $0F00, Flags Z=0, N=1, H=1, C=0
11 | push de
12 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld h, $11
9 | ld l, $00
10 | dec h ;Expected: HL = $1000, Flags Z=0, N=1, H=0, C=0
11 | push hl
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld d, $0F
9 | ld e, $00
10 | inc d ;Expected: DE = $1000, Flags Z=0, N=0, H=1, C=0
11 | push de
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld h, $10
9 | ld l, $00
10 | inc h ;Expected: HL = $1100, Flags Z=0, N=0, H=0, C=0
11 | push hl
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ea.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $aa
7 | ld de, $3634
8 | ;ld l, $08
9 | or a,a ;borra las banderas
10 |
11 | ld e, a
12 | push de
13 | ;the value expected is $36aa
14 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ee.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld de, $3634
8 | ;ld d, $89
9 | or a,a ;borra las banderas
10 |
11 | ld e, e
12 | push de
13 | ;the value expected is $3634
14 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $00
9 | ld c, $00
10 | dec c
11 | ;Expected BC = $00FF, Flags Z=0, N=1, H=1, C=0
12 | push bc
13 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld d, $00
9 | ld e, $F1
10 | dec e ;Expected: DE = $00F0, Flags Z=0, N=1, H=0, C=1
11 | push de
12 |
--------------------------------------------------------------------------------
/tests/asm/test_DECr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld h, $00
9 | ld l, $00
10 | dec l ;Expected: HL = $0011, Flags Z=0, N=1, H=1, C=1
11 | push hl
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_b_flags.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $00
9 | ld c, $00
10 | inc b
11 | ;Expected Flags Z=0 N=0 H=0 C=0, AF = $0000
12 | push af ; Tests Flags
13 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld d, $00
9 | ld e, $F0
10 | inc e ;Expected: DE = $00F1, Flags Z=0, N=0, H=0, C=1
11 | push de
12 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $80
7 | add a ; Sets carry flag <---OJO
8 | ld h, $00
9 | ld l, $FF
10 | inc l ;Expected: HL = $0011, Flags Z=1, N=0, H=1, C=1
11 | push hl
12 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_bd.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $3597
8 | ld d, $40
9 | or a,a ;borra las banderas
10 |
11 | ld b, d
12 | push bc
13 |
14 | ;the value expected is $4097
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_be.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | ld e, $35
9 | or a,a ;borra las banderas
10 |
11 | ld b, e
12 | push bc
13 |
14 | ;the value expected is $3597
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_bh.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | ld h, $17
9 | or a,a ;borra las banderas
10 |
11 | ld b, h
12 | push bc
13 |
14 | ;the value expected is $1797
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_bl.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | ld l, $65
9 | or a,a ;borra las banderas
10 |
11 | ld b, l
12 | push bc
13 |
14 | ;the value expected is $6597
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_cd.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $8897
8 | ld d, $71
9 | or a,a ;borra las banderas
10 |
11 | ld c, d
12 | push bc
13 |
14 | ;the value expected is $8871
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ce.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $3634
8 | ld e, $71
9 | or a,a ;borra las banderas
10 |
11 | ld c, e
12 | push bc
13 |
14 | ;the value expected is $3671
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_ch.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $3634
8 | ld h, $52
9 | or a,a ;borra las banderas
10 |
11 | ld c, h
12 | push bc
13 |
14 | ;the value expected is $3652
15 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrr_cl.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld bc, $3634
8 | ld l, $12
9 | or a,a ;borra las banderas
10 |
11 | ld c, l
12 | push bc
13 |
14 | ;the value expected is $3612
15 |
--------------------------------------------------------------------------------
/tests/asm/test_JRCn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a,a
8 | ld a,$FF
9 | add a,$10
10 | jr c, end
11 |
12 | ld a, $cc
13 | ;the value expected is af=$0F10
14 | end:
15 | push af
16 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $fF
7 | ld b, $0f
8 | or a,a
9 | nop
10 | add a, b
11 | nop
12 | sbc a, b
13 | ;Expected Z=0 N=1 H=1 C=1 -- AF =FE70
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $03
7 | ld c, $fe
8 | or a,a
9 | nop
10 | add a, c
11 | nop
12 | sbc a, c
13 | ;Expected Z=0 N=1 H=1 C=1 -- AF = 0270
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $02
7 | ld d, $ff
8 | or a,a
9 | nop
10 | add a, d
11 | nop
12 | sbc a, d
13 | ;Expected Z=0 N=1 H=1 C=1 -- AF = 0170
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld e, $ff
8 | or a,a
9 | nop
10 | add a, e
11 | nop
12 | sbc a, e
13 | ;Expected Z=0 N=1 H=1 C=1 -- AF = 1470
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $01
7 | ld h, $ff
8 | or a,a
9 | nop
10 | add a, h
11 | nop
12 | sbc a, h
13 | ;Expected Z=1 N=1 H=1 C=1 -- AF = 00F0
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_SBCr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $99
7 | ld l, $80
8 | or a,a
9 | nop
10 | add a, l
11 | nop
12 | sbc a, l
13 | ;Expected Z=0 N=1 H=0 C=1 -- AF = 9850
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ORHL.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, $FFFD
7 | nop
8 | nop
9 | ld e, $23
10 | ld [hl],e
11 | ld a, $dc
12 |
13 | nop
14 | or a,[hl]
15 |
16 | ;af=$ff00
17 | push af
18 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $fF
7 | ld b, $0f
8 | or a,a
9 | nop
10 | add a, b
11 | nop
12 | adc a, b
13 | ;the value expected is a=$1E and f=$20 af=$1E20
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $03
7 | ld c, $fe
8 | or a,a
9 | nop
10 | add a, c
11 | nop
12 | adc a, c
13 | ;the value expected is a=$00 and f=$b0 af=$00b0
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $02
7 | ld d, $ff
8 | or a,a
9 | nop
10 | add a, d
11 | nop
12 | adc a, d
13 | ;the value expected is a=$01 and f=$30 af=$0130
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $15
7 | ld e, $ff
8 | or a,a
9 | nop
10 | add a, e
11 | nop
12 | adc a, e
13 | ;the value expected is a=$14 and f=$30 af=$1430
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $01
7 | ld h, $ff
8 | or a,a
9 | nop
10 | add a, h
11 | nop
12 | adc a, h
13 | ;the value expected is a=$00 and f=$b0 af=$00b0
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_ADCr_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $99
7 | ld l, $80
8 | or a,a
9 | nop
10 | add a, l
11 | nop
12 | adc a, l
13 | ;the value expected is a=$9a and f=$00 af=$9a00
14 | push af
15 |
--------------------------------------------------------------------------------
/tests/asm/test_INCr_c_flags.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld a, $00
7 | or a, a ; Clears all flags
8 | ld b, $00
9 | ld c, $FF
10 | inc c
11 | ;Expected Flags Z=1 N=0 H=1 C=1, AF = $00B0
12 | push af ; Tests Flags
13 |
--------------------------------------------------------------------------------
/tests/asm/test_RETC.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, carry_label
7 | push hl
8 | ld a, $ff
9 | add $01
10 | ret c
11 | jp end_label
12 | carry_label:
13 | ld a, $71
14 | end_label:
15 | ;expected $71b0
16 | push af
17 |
--------------------------------------------------------------------------------
/tests/asm/test_JRn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 |
5 | DS $100
6 | ld sp, $FFFE
7 | ld a, $00
8 | or a,a
9 | ld a,$FF
10 | add a,$10
11 | jr hola
12 | cesar: jr end
13 | hola: jr cesar
14 |
15 | ld a, $cc
16 | ;the value expected is af=$0F10
17 | end:
18 | push af
19 |
--------------------------------------------------------------------------------
/sim/signals/flow_ids:
--------------------------------------------------------------------------------
1 | 1 LDSPnn
2 | 5 LDHLnn
3 | 9 LDHLDA
4 | 13 MAPcb
5 | 17 JRNZn
6 | 23 LDrn_c
7 | 26 LDrn_a
8 | 29 LDIOCA
9 | 32 INCr
10 | 33 LDHLmr_a
11 | 36 LDIOnA
12 | 43 LDDEnn
13 | 47 LDADEm
14 | 50 CALLnn
15 | 60 LDrn_b
16 | 63 PUSHBC
17 | 70 RLA
18 | 71 POPBC
19 | 77 DECr_b
20 | 78 LDHLIA
21 | 82 INCHL
22 | 83 RET
23 | 89 INCDE
24 | 90 CPn
25 | 98 LDmmA
26 | 184 ADDr_c
27 |
--------------------------------------------------------------------------------
/tests/asm/test_INCHLm.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $FFFE
6 | ld hl, $C000
7 | ld a , $62
8 |
9 | ld [hl],a
10 | inc [hl]
11 |
12 | ld a,[hl]
13 | sub $63
14 | jp Z,exit
15 | ld a,$33
16 | exit:
17 | push af
18 |
19 | ;the value expected is $00C0, flag Z affected
20 |
--------------------------------------------------------------------------------
/tests/asm/test_CALLNZnn.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld sp, $dfe2
6 | ld hl, $dfe0
7 | ld a, $ff
8 | sub a, $1
9 | call nz, label
10 | ld a, $cc
11 | label:
12 | ld a, [hl+]
13 | ld b, [hl]
14 | ld c, a
15 |
16 | ;the value expected is bc=$0208
17 | ld sp, $fffe
18 | push bc
19 |
--------------------------------------------------------------------------------
/sim/signals/dzcpu_uop_cmd:
--------------------------------------------------------------------------------
1 | 0 nop
2 | 1 sma
3 | 2 srm
4 | 3 jcb
5 | 4 z801bop
6 | 5 smw
7 | 6 dec16
8 | 7 bit
9 | 8 addx16
10 | 9 spc
11 | 10 sx16r
12 | 11 sx8r
13 | 12 inc16
14 | 13 srx8
15 | 14 shl
16 | 15 subx16
17 | 16 srx16
18 | 17 seti
19 | 18 cibit
20 | 19 ceti
21 | 20 jint
22 | 21 anda
23 | 22 xorx16
24 | 23 rrot
25 | 24 xora
26 | 25 addx16c
27 | 26 addx16u
28 | 27 shr
29 | 30 shl8
30 | 31 addx16c_ext
31 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_b.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $48
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld b,[hl]
20 |
21 | push bc
22 |
23 | ;the value expected is $4800
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_c.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $48
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld c,[hl]
20 |
21 | push bc
22 |
23 | ;the value expected is $0048
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_d.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $87
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld d,[hl]
20 |
21 | push de
22 |
23 | ;the value expected is $8700
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_e.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $87
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld e,[hl]
20 |
21 | push de
22 |
23 | ;the value expected is $0087
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_h.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $37
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld h,[hl]
20 |
21 | push hl
22 |
23 | ;the value expected is $37fd
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_l.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $37
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | nop
18 | nop
19 | ld l,[hl]
20 |
21 | push hl
22 |
23 | ;the value expected is $ff37
24 |
--------------------------------------------------------------------------------
/tests/asm/test_LDABCm.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld bc, $FFFD
7 | ld sp, $FFFe
8 |
9 | ld a, 1
10 | or a,a
11 |
12 | ld a, $58
13 |
14 | ldd [hl],a
15 | ldd [hl],a
16 |
17 | ld a, $10
18 | nop
19 | nop
20 | ld a,[bc]
21 |
22 | push af
23 |
24 | ;the value expected is $2000
25 |
--------------------------------------------------------------------------------
/tests/asm/test_LDADEm.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld de, $FFFD
7 | ld sp, $FFFe
8 |
9 | ld a, 1
10 | or a,a
11 |
12 | ld a, $20
13 |
14 | ldd [hl],a
15 | ldd [hl],a
16 |
17 | ld a, $10
18 | nop
19 | nop
20 | ld a,[de]
21 |
22 | push af
23 |
24 | ;the value expected is $2000
25 |
--------------------------------------------------------------------------------
/tests/asm/test_LDrHLm_a.asm:
--------------------------------------------------------------------------------
1 | SECTION "sec", ROM0
2 | DS $100
3 | jp $200
4 | DS $100
5 | ld hl, $FFFD
6 | ld sp, $FFFe
7 |
8 | ld a, 1
9 | or a,a
10 |
11 | ld a, $60
12 |
13 | ldd [hl],a
14 | ldd [hl],a
15 | ld hl, $FFFD
16 |
17 | ld a, $10
18 | nop
19 | nop
20 | ld a,[hl]
21 |
22 | push af
23 |
24 | ;the value expected is $2000
25 |
--------------------------------------------------------------------------------
/script/run_gearboysim.sh:
--------------------------------------------------------------------------------
1 | make clean && time make SIMFLAGS="-DREG_B=0 -DREG_IF=8\'he1 -DREG_TAC=8\'hf8 -DREG_C=19 -DREG_D=0 -DREG_E=216 -DREG_H=1 -DREG_L=77 -DREG_A=1 -DREG_SPL=254 -DREG_SPH=255 -DSKIP_BIOS -DENABLE_INSN_TRACE -DENABLE_CPU_LOG -DCARTRIGDE_DUMP_PATH='\"../tests/cpu_instrs/individual/test_02.dump\"' -DSTOP_AFTER_INSN_COUNT=800000 -DLY_OVERRIDE_PATH='\"ly_values.txt\"'" && vimdiff pgb_trace.dump ../../../tools/Gearboy/platforms/linux/Gearboy/gearboy.dump
2 |
--------------------------------------------------------------------------------
/tests/asm/README:
--------------------------------------------------------------------------------
1 |
2 | #Compile the file
3 | rgbasm -o test_INCr_b.obj test_INCr_b.asm
4 | rgblink -m test_INCr_b.map -n test_INCr_b.sym -o test_INCr_b.gb test_INCr_b.obj
5 | hexdump -v test_INCr_b.gb > test_INCr_b.dump
6 |
7 | #format the dump file into single byte and remove the address column
8 | vim ../tests/asm/test_INCr_b.dump
9 |
10 |
11 | #Run the simulation
12 | cd ../../sim
13 | make clean && make SIMFLAGS="-DENABLE_CPU_LOG -DLOAD_CARTRIDGE_FROM_FILE -DCARTRIGDE_DUMP_PATH='\"../tests/asm/test_INCr_b.dump\"' -DSKIP_BIOS"
14 |
--------------------------------------------------------------------------------
/script/create_dump_from_hex.pl:
--------------------------------------------------------------------------------
1 | #! /usr/bin/perl
2 | use strict;
3 |
4 | die "\nUsage: create_dump_from_hex.pl input_file output_file\n" if ($#ARGV + 1 != 2);
5 | die "\n File not found $ARGV[0]\n" if (! -e $ARGV[0]);
6 | my $dump_temp = "temp.dump";
7 | #Dont read the last line because that is just the last address
8 | `hexdump -v $ARGV[0] | head --lines=-1 > $dump_temp`;
9 |
10 | open my $hexfile, $dump_temp or die "Could not open $dump_temp: $!";
11 | open my $dumpfile, '>', $ARGV[1] or die "Could not open $ARGV[1]: $!";
12 |
13 | while( my $line = <$hexfile>) {
14 | $line =~ s/^....... //g ;
15 | $line =~ s/(..)(..) (..)(..)/$2 $1 $4 $3/g;
16 | print $dumpfile $line;
17 | }
18 |
19 | close $hexfile;
20 |
--------------------------------------------------------------------------------
/sim/Makefile:
--------------------------------------------------------------------------------
1 |
2 | VERILOGEX = .v # Verilog file extension
3 |
4 | # testbench path TESTBENCH is passed from the command line
5 | SCENEPATH =
6 | TESTBENCH = tb_simple_dzcpu
7 | TESTBENCHPATH = ../tb/${TESTBENCH}$(VERILOGEX)
8 | SOURCEPATH = ../rtl
9 | GPUCONFIGURATIONSCRIPT=../scripts/configure_gpu.pl
10 | INPUTCONFIGURATIONSCRIPT=../scripts/configure_params.pl
11 | #iverilog CONFIG
12 | VERILOG_CMD = iverilog
13 |
14 | # VVP (iverilog runtime engine)
15 | VVP_CMD = vvp
16 |
17 | #Simulation Vars
18 | SIMDIR = .
19 | DUMPTYPE = none
20 | #Viewer
21 | WAVEFORM_VIEWER = gtkwave # Waveform viewer executable
22 | SIMFLAGS = -DSTOP_AFTER_FIRST_FRAME -DLCD_SCXY_DISABLED -DENABLE_CPU_LOG -DENABLE_GPU_LOG
23 |
24 |
25 | all: compile run
26 |
27 |
28 | testbench_checktestbench_check:
29 | ifeq ($(strip $(TESTBENCH)),)
30 | @echo "TESTBENCH not set. Use TESTBENCH=value to set it."
31 | @exit 2
32 | endif
33 |
34 |
35 |
36 | check:
37 | $(VERILOG_CMD) -t null $(FILES)
38 |
39 | # Setup up project directory
40 | new :
41 | echo "Setting up project ${PROJECT}"
42 | mkdir rtl testbench simulation
43 |
44 |
45 | compile :
46 |
47 |
48 | $(VERILOG_CMD) $(SIMFLAGS) -o $(SIMDIR)/$(TESTBENCH) $(TESTBENCHPATH) $(SOURCEPATH)/* -I $(SOURCEPATH)/ -Wall
49 |
50 |
51 | run :
52 | $(VVP_CMD) ./$(TESTBENCH) -$(DUMPTYPE) $(VVP_FLAGS)
53 |
54 | view :
55 | $(WAVEFORM_VIEWER) $(SIMDIR)/$(TESTBENCH).vcd $(SIMDIR)/signals/$(TESTBENCH).gtkw
56 |
57 | clean :
58 | rm -f $(SIMDIR)/$(TESTBENCH)
59 | rm -f *.vcd *.log *.dump
60 | rm -f generated_frames/*.ppm
61 |
--------------------------------------------------------------------------------
/sim/resources/tetris_oam_fe00_fe9f.dump:
--------------------------------------------------------------------------------
1 | 80 10 58 00 00 00 00 00 00 00 00 00 00 00 00 00
2 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
12 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
14 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
15 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
17 | ff 55 fe ff ef 00 00 f8 ff ff ff ff ff ff ff e0
18 | 80 bf 74 ff bf ff bf c3 ff bf ff ff bf ff bf ff
19 | ff 00 00 ff 77 fd f7 ff ff ff ff ff ff ff ff ff
20 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
21 | d3 81 00 00 90 00 c0 e4 e4 c4 00 00 ff ff ff ff
22 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
23 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
24 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
25 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
26 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
27 | 00 09 00 00 00 00 43 00 00 00 00 00 00 00 00 00
28 | 00 00 00 00 00 00 3e c0 e0 46 3e 28 3d 20 fd c9
29 | 37 1c 00 00 00 00 13 00 00 00 00 00 00 00 00 00
30 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
31 | 00 07 b8 00 00 00 00 00 00 00 00 00 00 00 00 00
32 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09
33 |
--------------------------------------------------------------------------------
/ucf/pgb_vga.ucf:
--------------------------------------------------------------------------------
1 | # UCF file for the Papilio DUO board
2 |
3 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
4 | CONFIG PROHIBIT=P144;
5 | CONFIG PROHIBIT=P69;
6 | CONFIG PROHIBIT=P60;
7 |
8 | NET iClock LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
9 | NET iReset LOC="P116" | IOSTANDARD=LVTTL; # A0
10 | NET oVgaRed(0) LOC="P98" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D0
11 | NET oVgaRed(1) LOC="P95" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D1
12 | NET oVgaRed(2) LOC="P92" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D2
13 | NET oVgaRed(3) LOC="P87" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D3
14 | NET oVgaGreen(3) LOC="P84" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D4
15 | NET oVgaGreen(2) LOC="P82" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D5
16 | NET oVgaGreen(1) LOC="P80" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D6
17 | NET oVgaGreen(0) LOC="P78" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D7
18 | NET oVgaBlue(3) LOC="P74" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D8
19 | NET oVgaBlue(2) LOC="P66" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D9
20 | NET oVgaBlue(1) LOC="P61" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D10
21 | NET oVgaBlue(0) LOC="P51" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D13
22 | NET oVgaVsync LOC="P48" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D14
23 | NET oVgaHsync LOC="P39" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # D15
24 |
--------------------------------------------------------------------------------
/sim/resources/zelda_game_scene_1_oam_fe00_fe9f.dump:
--------------------------------------------------------------------------------
1 | 00 49 26 00 00 00 00 00 58 46 00 00 58 4e 02 00
2 | 00 00 00 00 00 00 00 00 00 97 a2 40 00 00 00 00
3 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4 | 50 78 58 00 50 80 5a 00 38 50 62 20 38 58 60 20
5 | 00 38 48 00 00 40 4a 00 00 00 00 00 00 00 00 00
6 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
12 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
14 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
15 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
17 | ff 00 7e ff f9 00 00 f8 ff ff ff ff ff ff ff f2
18 | 80 bf 27 ff bf ff bf 27 ff bf ff ff 9f ff bf ff
19 | ff 40 20 ff 77 ff f7 ff ff ff ff ff ff ff ff ff
20 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
21 | e3 c1 00 00 90 4f c0 e4 1c e4 80 06 ff ff ff ff
22 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
23 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
24 | ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
25 | 40 30 28 af 4b 6e 08 f3 01 df 25 5e be ee 04 ae
26 | 00 00 00 00 08 00 00 00 46 58 00 00 00 00 03 46
27 | 58 00 00 00 04 00 38 00 00 07 70 00 00 00 00 0d
28 | 1c 00 00 58 00 00 00 00 0d 00 00 00 00 1c 00 1c
29 | 3e c0 e0 46 3e 28 3d 20 fd c9 00 00 00 50 40 00
30 | 00 00 01 00 00 00 00 00 00 00 00 47 00 00 00 00
31 | 9a 00 00 03 00 00 05 e4 00 54 05 3e 38 00 50 38
32 | 03 01 00 00 00 00 a3 10 81 00 54 54 00 00 00 01
33 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/tb_simple_mx.v:
--------------------------------------------------------------------------------
1 | //Dummy tb for sound mx.
2 | //Tb is only for debug this module.
3 |
4 | `timescale 1ns / 1ps
5 | `include "aDefinitions.v"
6 | `include "collaterals.v"
7 | `include "SoundControllerMX.v"
8 | `include "SoundControllerOSC1.v"
9 | `include "SoundControllerOSC2.v"
10 |
11 | module tb;
12 |
13 | reg clk;
14 | wire clk131k;
15 | wire clk262k;
16 | reg rst;
17 |
18 | wire [4:0] right, left;
19 | reg [7:0] nr50, nr51;
20 | wire [4:0] wOut1, wOut2, wOut3, wOut4;
21 |
22 | always begin
23 | #`CLOCK_CYCLE clk = ~clk;
24 | end
25 |
26 | osc2 o2
27 | (
28 | .iClock(clk),
29 | .iReset(rst),
30 | .oOut131k(clk131k),
31 | .oOut262k(clk262k)
32 | );
33 |
34 | SoundCtrlMX # () smx1 (
35 | .iClock(clk),
36 | .iReset(rst),
37 | .iOsc262k(clk262k),
38 | .iNR50(nr50),
39 | .iNR51(nr51),
40 | .iOut1(wOut1),
41 | .iOut2(wOut2),
42 | .iOut3(wOut3),
43 | .iOut4(wOut4),
44 |
45 | .oSO1(left),
46 | .oSO2(right)
47 | );
48 |
49 | assign wOut1 = 5'hA;
50 | assign wOut2 = 5'hB;
51 | assign wOut3 = 5'hC;
52 | assign wOut4 = 5'hD;
53 |
54 | integer i;
55 |
56 | initial begin
57 | $dumpfile("dump_sound_mx.vcd");
58 | $dumpvars();
59 | $display("tiempo \t left \t right");
60 | $monitor ("%0d \t %0d \t %0d",$time, left, right);
61 | clk = 0;
62 | rst = 1'b0;
63 | #10 rst = 1'b1;
64 |
65 | //test1
66 | ///*
67 | nr50 = 8'h77; // max volume.
68 | nr51 = 8'hFF; // enable channels.
69 | //*/
70 |
71 | repeat (2) @ (negedge clk);
72 | rst = 1'b0;
73 |
74 | #50_000;
75 |
76 | $finish;
77 | end
78 |
79 | endmodule
80 |
--------------------------------------------------------------------------------
/rtl/aDefinitions.v:
--------------------------------------------------------------------------------
1 | /**********************************************************************************
2 | Theaia, Ray Cast Programable graphic Processing Unit.
3 | Copyright (C) 2009 Diego Valverde (diego.valverde.g@gmail.com)
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 |
19 | ***********************************************************************************/
20 |
21 |
22 | //Verilog provides a `default_nettype none compiler directive. When
23 | //this directive is set, implicit data types are disabled, which will make any
24 | //undeclared signal name a syntax error.This is very usefull to avoid annoying
25 | //automatic 1 bit long wire declaration where you don't want them to be!
26 | `default_nettype none
27 |
28 | //The clock cycle
29 | `define CLOCK_CYCLE 5
30 | `define CLOCK_PERIOD 10
31 |
32 |
33 | //The next section defines the length of the registers, buses and other structures,
34 | //do not change this valued unless you really know what you are doing (seriously!)
35 | `define WIDTH 8
36 | `define LONG_WIDTH 16
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/tb/tb_simple_io.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | `include "io.v"
4 | `include "Defintions.v"
5 |
6 | module tb_simple_io;
7 |
8 | // Inputs
9 | reg Clock;
10 | reg Reset;
11 |
12 | // Outputs
13 | wire [5:0] oP;
14 | wire oIE;
15 |
16 | reg [5:0] rBotcode;
17 |
18 | // Instantiate the Unit Under Test (UUT)
19 | io ionew (
20 | .Clock(Clock),
21 | .Reset(Reset),
22 |
23 | .iP(rBotcode),
24 | .oP(oP),
25 | .oIE(oIE)
26 | );
27 |
28 | always
29 | begin
30 | #5 Clock = ! Clock;
31 |
32 | end
33 |
34 | initial begin
35 | $display("Starting GameBoy IO Test\n");
36 |
37 | $dumpfile("tb_simple_io.vcd");
38 | $dumpvars(0,tb_simple_io);
39 |
40 | // Initialize Inputs
41 | Clock = 0;
42 | Reset = 0;
43 |
44 | rBotcode = `NOBOT;
45 |
46 | // Wait 100 ns for global reset to finish
47 | #10;
48 | Reset = 1;
49 | #10
50 | Reset = 0;
51 | $display("Reset ready at time %dns", $time);
52 | #10
53 | rBotcode = `NOBOT;
54 | $display("No button pressed at time %dns", $time);
55 |
56 | #10
57 | rBotcode = `A;
58 | #10
59 | rBotcode = `NOBOT;
60 | #10
61 | rBotcode = `B;
62 | #10
63 | rBotcode = `START;
64 | #10
65 | rBotcode = `SELECT;
66 | #10
67 | rBotcode = `UP;
68 | #10
69 | rBotcode = `DOWN;
70 | #10
71 | rBotcode = `LEFT;
72 | #10
73 | rBotcode = `RIGHT;
74 |
75 | // #10
76 | // rBotcode = `A;
77 | // #10
78 | // rBotcode = `NOBOT;
79 | // #10
80 | // rBotcode = `B;
81 | // #10
82 | // rBotcode = `B & `DOWN;
83 |
84 | #100
85 | rBotcode = `NOBOT;
86 | $display("No button pressed at time %dns", $time);
87 |
88 | // All done
89 | #100
90 | $finish();
91 |
92 | end
93 |
94 | endmodule
95 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerOSC2.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 1. Squate waves with variable timer, frequency, envelope functions and frequency sweep.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 | module osc2
25 | (
26 | input wire iClock,
27 | input wire iReset,
28 | output wire oOut131k,
29 | output wire oOut262k
30 | );
31 |
32 | reg [4:0] rOscCounter; // log2(4194204/131072*2) = log2(16)= 4. Last bit corresponds to the output.
33 |
34 |
35 | always @ (posedge iClock) begin
36 | if (iReset) begin
37 | rOscCounter <= 0;
38 | end
39 | else begin
40 | rOscCounter <= rOscCounter+1;
41 | end
42 | end
43 |
44 | assign oOut131k = rOscCounter[4];
45 | assign oOut262k = rOscCounter[3];
46 |
47 | endmodule
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerOSC1.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 1. Squate waves with variable timer, frequency, envelope functions and frequency sweep.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 | module osc1
25 | (
26 | input wire iClock,
27 | input wire iReset,
28 | output wire oOut64,
29 | output wire oOut128,
30 | output wire oOut256
31 | );
32 |
33 | reg [16:0] rOscCounter; // log2(4194204/256) = log2(4194204)= 14. Last bit correspond to the output.
34 |
35 |
36 | always @ (posedge iClock) begin
37 | if (iReset) begin
38 | rOscCounter <= 0;
39 | end
40 | else begin
41 | rOscCounter <= rOscCounter+1;
42 | end
43 | end
44 |
45 | assign oOut64 = rOscCounter[15];
46 | assign oOut128 = rOscCounter[14];
47 | assign oOut256 = rOscCounter[13];
48 |
49 | endmodule
--------------------------------------------------------------------------------
/ucf/pgb_lcd.ucf:
--------------------------------------------------------------------------------
1 | # UCF file for the Papilio DUO board
2 |
3 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
4 | CONFIG PROHIBIT=P144;
5 | CONFIG PROHIBIT=P69;
6 | CONFIG PROHIBIT=P60;
7 |
8 | NET iClock LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
9 | NET iReset LOC="P116" | IOSTANDARD=LVTTL; # A0
10 | NET oLCD_D(0) LOC="P100" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 0
11 | NET oLCD_D(1) LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 1
12 | NET oLCD_D(2) LOC="P102" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 2
13 | NET oLCD_D(3) LOC="P103" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 3
14 | NET oLCD_D(4) LOC="P104" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 4
15 | NET oLCD_D(5) LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 5
16 | NET oLCD_D(6) LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 6
17 | NET oLCD_D(7) LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 7
18 | NET oLCD_D(8) LOC="P108" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 8
19 | NET oLCD_D(9) LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 9
20 | NET oLCD_D(10) LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 10
21 | NET oLCD_D(11) LOC="P111" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 11
22 | NET oLCD_D(12) LOC="P112" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 12
23 | NET oLCD_D(13) LOC="P113" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 13
24 | NET oLCD_D(14) LOC="P114" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DATA 14
25 | NET oLCD_RD(15) LOC="P115" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD RD
26 | NET oLCD_WR(16) LOC="P116" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD W/R
27 | NET oLCD_DC(17) LOC="P117" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD DC
28 | NET oLCD_CS(18) LOC="P118" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; #LCD CS
29 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/tb_simple_channel2.v:
--------------------------------------------------------------------------------
1 | //Dummy tb for sound channel 4.
2 | //Tb is only for debug this module.
3 |
4 | `timescale 1ns / 1ps
5 | `include "aDefinitions.v"
6 | `include "collaterals.v"
7 | `include "SoundControllerChannel2.v"
8 | `include "SoundControllerOSC1.v"
9 | `include "SoundControllerOSC2.v"
10 |
11 | module tb;
12 |
13 | reg clk;
14 | wire clk64;
15 | wire clk256;
16 | wire clk131k;
17 | wire clk262k;
18 | reg rst;
19 | wire [4:0] out;
20 |
21 | reg [7:0] nr20;
22 | reg [7:0] nr21;
23 | reg [7:0] nr22;
24 | reg [7:0] nr23;
25 | reg [7:0] nr24;
26 |
27 | always begin
28 | #`CLOCK_CYCLE clk = ~clk;
29 | end
30 |
31 | osc1 o1
32 | (
33 | .iClock(clk),
34 | .iReset(rst),
35 | .oOut64(clk64),
36 | .oOut256(clk256)
37 | );
38 |
39 | osc2 o2
40 | (
41 | .iClock(clk),
42 | .iReset(rst),
43 | .oOut131k(clk131k),
44 | .oOut262k(clk262k)
45 | );
46 |
47 |
48 | SoundCtrlChannel2 # () scc2 (
49 | .iClock(clk),
50 | .iReset(rst),
51 | .iOsc64(clk64),
52 | .iOsc256(clk256),
53 | .iOsc262k(clk262k),
54 | .iNR21(nr21),
55 | .iNR22(nr22),
56 | .iNR23(nr23),
57 | .iNR24(nr24),
58 | .oOut(out)
59 | );
60 |
61 | initial begin
62 | $dumpfile("dump_sound_channel2.vcd");
63 | $dumpvars();
64 | $display("tiempo \t\t out2");
65 | $monitor ("%0d \t\t %0d",$time, out);
66 | clk = 0;
67 | rst = 1'b0;
68 | #10 rst = 1'b1;
69 |
70 |
71 | //test1
72 | /*
73 | nr21 = 8'h03; // length = $03 = 03.
74 | nr22 = 8'hF4; // attenuate envelope, step time = 3. initial value = $F = 15.
75 | nr23 = 8'hBC; // low fre = $BC.
76 | nr24 = 8'h43; // high freq = $3, freq = $3BC = 956. timer enabled.
77 | */
78 |
79 | //test2
80 | /*
81 | nr21 = 8'h50; // length = $1F = 31.
82 | nr22 = 8'h1C; // amplify envelope, step time = 7. initial value = $2 = 2.
83 | nr23 = 8'hBC; // low freq = $BC.
84 | nr24 = 8'h03; // high freq = $3 , freq = $3BC = 956. time disabled.
85 | */
86 |
87 | repeat (2) @ (negedge clk);
88 | rst = 1'b0;
89 | #50_000_000;
90 |
91 | $finish;
92 | end
93 |
94 | endmodule
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/tb_simple_channel4.v:
--------------------------------------------------------------------------------
1 | //Dummy tb for sound channel 4.
2 | //Tb is only for debug this module.
3 |
4 | `timescale 1ns / 1ps
5 | `include "aDefinitions.v"
6 | `include "collaterals.v"
7 | `include "SoundControllerChannel4.v"
8 | `include "SoundControllerOSC1.v"
9 | `include "SoundControllerOSC2.v"
10 |
11 | module tb;
12 |
13 | reg clk;
14 | wire clk64;
15 | wire clk256;
16 | wire clk131k;
17 | wire clk262k;
18 | reg rst;
19 | wire [4:0] out;
20 |
21 | reg [7:0] nr41;
22 | reg [7:0] nr42;
23 | reg [7:0] nr43;
24 | reg [7:0] nr44;
25 |
26 |
27 | always begin
28 | #`CLOCK_CYCLE clk = ~clk;
29 | end
30 |
31 | osc1 o1
32 | (
33 | .iClock(clk),
34 | .iReset(rst),
35 | .oOut64(clk64),
36 | .oOut256(clk256)
37 | );
38 |
39 | osc2 o2
40 | (
41 | .iClock(clk),
42 | .iReset(rst),
43 | .oOut131k(clk131k),
44 | .oOut262k(clk262k)
45 | );
46 |
47 |
48 | SoundCtrlChannel4 # () scc2 (
49 | .iClock(clk),
50 | .iReset(rst),
51 | .iOsc64(clk64),
52 | .iOsc256(clk256),
53 | .iNR41(nr41),
54 | .iNR42(nr42),
55 | .iNR43(nr43),
56 | .iNR44(nr44),
57 | .oOut(out)
58 | );
59 |
60 | integer i;
61 |
62 | initial begin
63 | // $dumpfile("dump_sound_channel4.vcd");
64 | // $dumpvars();
65 | // $display("tiempo \t\t out4");
66 | // $monitor ("%0d \t\t %0d",$time, out);
67 | clk = 0;
68 | rst = 1'b0;
69 | @(negedge clk) rst = 1'b1;
70 |
71 | //test1
72 | /*
73 | nr41 = 8'h03; // length = $XX, timer disabled
74 | nr42 = 8'hF4; // attenuate envelope, step time = 7. initial value = $F = 15.
75 | nr43 = 8'h52; // div ratio = 3. lfrs = 15 stages , shifts = 3
76 | nr44 = 8'h40; // timer disabled.
77 | */
78 |
79 | //test2
80 | ///*
81 | nr41 = 8'h00; // length = $XX, timer disabled
82 | nr42 = 8'h1C; // amplify envelope, step time = 7. initial value = $2 = 2.
83 | nr43 = 8'h52; // div ratio = 3. lfrs = 7 stages , shifts = 3
84 | nr44 = 8'h00; // timer disabled.
85 | //*/
86 |
87 | repeat (2) @ (negedge clk);
88 | rst = 1'b0;
89 | // #50_000_000;
90 | for ( i = 0; i < 10000; i = i+1) begin
91 | #5120 $display ("%0d, ", out);
92 | end
93 |
94 | $finish;
95 | end
96 |
97 | endmodule
98 |
--------------------------------------------------------------------------------
/rtl/interrupts.v:
--------------------------------------------------------------------------------
1 | module interrupt_controller
2 | (
3 | input wire iClock,
4 | input wire iReset,
5 |
6 | input wire iMcuWe,
7 | input wire [3:0] iMcuRegSelect, //control register select comes from cpu
8 | input wire [7:0] iMcuWriteData, //what does the cpu want to write
9 |
10 | output wire[7:0] oInterruptEnableRegister,
11 | output wire[7:0] oInterruptFlag,
12 |
13 |
14 | input wire [7:0] iInterruptRequest,
15 | output reg [7:0] oInterruptResquestPending
16 | );
17 |
18 |
19 |
20 |
21 | ////////////////////////////////////////////////
22 | //
23 | // Register 0xFFFF: IE. Interrupt Enable register
24 | // reset to 0 whenever written to
25 | //
26 | // Bit 0: V-Blank Interrupt Enable (INT 40h) (1=Enable)
27 | // Bit 1: LCD STAT Interrupt Enable (INT 48h) (1=Enable)
28 | // Bit 2: Timer Interrupt Enable (INT 50h) (1=Enable)
29 | // Bit 3: Serial Interrupt Enable (INT 58h) (1=Enable)
30 | // Bit 4: Joypad Interrupt Enable (INT 60h) (1=Enable)
31 | ////////////////////////////////////////////////
32 |
33 | wire wWeInterrutpRegister;
34 | assign wWeInterrutpRegister = (iMcuWe & iMcuRegSelect == 4'h0) ? 1'b1 : 1'b0;
35 | FFD_POSEDGE_SYNCRONOUS_RESET # ( 8 )FF_IE(
36 | iClock, iReset , wWeInterrutpRegister , iMcuWriteData, oInterruptEnableRegister );
37 |
38 | ////////////////////////////////////////////////
39 | //
40 | // Register 0xFF0F: IF. Interrupt Flag
41 | // Bit 0: V-Blank Interrupt Request (INT 40h) (1=Request)
42 | // Bit 1: LCD STAT Interrupt Request (INT 48h) (1=Request)
43 | // Bit 2: Timer Interrupt Request (INT 50h) (1=Request)
44 | // Bit 3: Serial Interrupt Request (INT 58h) (1=Request)
45 | // Bit 4: Joypad Interrupt Request (INT 60h) (1=Request)
46 | ////////////////////////////////////////////////
47 |
48 | wire wWeInterruptFlag;
49 | assign wWeInterruptFlag = (iMcuWe & iMcuRegSelect == 4'hf) ? 1'b1: 1'b0;
50 | FFD_POSEDGE_SYNCRONOUS_RESET_INIT # ( 8 )FF_IF(
51 | iClock, iReset | wWeInterruptFlag , |iInterruptRequest , iMcuWriteData, iInterruptRequest, oInterruptFlag );
52 |
53 |
54 | wire [7:0] wPendingInterrupts;
55 | assign wPendingInterrupts = oInterruptFlag & oInterruptEnableRegister;
56 |
57 |
58 | always @ (*)
59 | begin
60 | case (wPendingInterrupts)
61 | 8'h1: oInterruptResquestPending = 8'b00000001; //VBLANK
62 | 8'h2: oInterruptResquestPending = 8'b00000010; //LCDSTAT
63 | 8'h4: oInterruptResquestPending = 8'b00000100; //TIMER
64 | 8'h8: oInterruptResquestPending = 8'b00001000; //SERIAL
65 | 8'h10: oInterruptResquestPending = 8'b00010000; //JOYPAD
66 | default: oInterruptResquestPending = 8'b0;
67 | endcase
68 | end
69 |
70 | endmodule
71 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/tb_simple_channel3.v:
--------------------------------------------------------------------------------
1 | //Dummy tb for sound channel 4.
2 | //Tb is only for debug this module.
3 |
4 | `timescale 1ns / 1ps
5 | `include "aDefinitions.v"
6 | `include "collaterals.v"
7 | `include "SoundControllerChannel3.v"
8 | `include "SoundControllerOSC1.v"
9 | `include "SoundControllerOSC2.v"
10 |
11 | module tb;
12 |
13 | reg clk;
14 | wire clk256;
15 | wire clk262k;
16 | reg rst;
17 | wire [4:0] out;
18 |
19 | reg [7:0] nr30;
20 | reg [7:0] nr31;
21 | reg [7:0] nr32;
22 | reg [7:0] nr33;
23 | reg [7:0] nr34;
24 |
25 | always begin
26 | #`CLOCK_CYCLE clk = ~clk;
27 | end
28 |
29 | osc1 o1
30 | (
31 | .iClock(clk),
32 | .iReset(rst),
33 | .oOut256(clk256)
34 | );
35 |
36 | osc2 o2
37 | (
38 | .iClock(clk),
39 | .iReset(rst),
40 | .oOut262k(clk262k)
41 | );
42 |
43 | SoundCtrlChannel3 # () scc3 (
44 | .iClock(clk),
45 | .iReset(rst),
46 | .iOsc256(clk256),
47 | .iOsc262k(clk262k),
48 | .iNR30(nr30),
49 | .iNR31(nr31),
50 | .iNR32(nr32),
51 | .iNR33(nr33),
52 | .iNR34(nr34),
53 | .oOut(out)
54 | );
55 |
56 | integer i;
57 |
58 | initial begin
59 | // $dumpfile("dump_sound_channel3.vcd");
60 | // $dumpvars();
61 | // $display("tiempo \t\t out3");
62 | // $monitor ("%0d \t\t %0d",$time, out);
63 | clk = 0;
64 | rst = 1'b0;
65 | #10 rst = 1'b1;
66 |
67 | //test1
68 | ///*
69 | nr30 = 8'h80;
70 | nr31 = 8'h8A;
71 | nr32 = 8'h20;
72 | nr33 = 8'hBC;
73 | nr34 = 8'h43; // timer mode
74 |
75 | repeat (2) @ (negedge clk);
76 | rst = 1'b0;
77 |
78 | for ( i = 0; i < 5000; i = i+1) begin
79 | #5120 $display ("%0d, ", out);
80 | end
81 |
82 | nr30 = 8'h80;
83 | nr31 = 8'h00;
84 | nr32 = 8'h40; // A = A/2
85 | nr33 = 8'hBC; // Lower frequency
86 | nr34 = 8'hC2; // timed mode
87 |
88 | repeat (2) @ (negedge clk);
89 | nr34 = 8'h02; // timed mode
90 |
91 | for ( i = 0; i < 5000; i = i+1) begin
92 | #5120 $display ("%0d, ", out);
93 | end
94 |
95 | //#25_000_000; // 596ms, dmg_clock
96 | //*/
97 |
98 | //test2
99 | /*
100 | nr30 = 8'h80;
101 | nr31 = 8'h8A; // L2
102 | nr32 = 8'h20;
103 | nr33 = 8'hBC;
104 | nr34 = 8'h43; // timer mode
105 |
106 | repeat (2) @ (negedge clk);
107 | rst = 1'b0;
108 | #25_000_000;
109 |
110 | nr30 = 8'h80;
111 | nr31 = 8'h00; // L2
112 | nr32 = 8'h60; // A = A/4
113 | nr33 = 8'hBC; // Lower frequency
114 | nr34 = 8'hC2;
115 |
116 | repeat (2) @ (negedge clk);
117 | nr34 = 8'h02; // continuous mode
118 | #25_000_000;
119 | */
120 |
121 | $finish;
122 | end
123 |
124 | endmodule
125 |
--------------------------------------------------------------------------------
/cad/papiGB.scad:
--------------------------------------------------------------------------------
1 |
2 | //All distances are in milimeters!
3 |
4 |
5 | case_w=140;
6 | case_h=case_w*0.5714;
7 | case_thickness=case_w/70;
8 | case_depth = case_w*0.12;
9 |
10 | //---------------------------------------------------------------------------------
11 | module papiGB_case_top()
12 | {
13 |
14 | //Let's start by setting some basic sizes
15 |
16 |
17 | lcd_w= case_w*0.535;
18 | lcd_h= case_h*0.6875;
19 |
20 | lcd_x = (case_w-lcd_w)/2;
21 | lcd_y = (case_h-lcd_h)/2;
22 | pad_diameter = case_w/14;
23 | button_diameter =case_w/28;
24 |
25 |
26 | pad_pos = [ lcd_x/2, (2*case_h)/3, 0];
27 |
28 | button_a_pos = [ case_w - (case_w - lcd_w)/5, (7*case_h)/10, 0];
29 | button_b_pos = [ case_w - (case_w - lcd_w)/3, (5*case_h)/10, 0];
30 |
31 | button_start_pos = [ lcd_x/4, (2*case_h)/10, 0];
32 | button_select_pos = [ lcd_x/4, (3*case_h)/10, 0];
33 |
34 | speaker_hole_0 = [ case_w - (case_w - lcd_w)/2.75, (2*case_h)/10, 0];
35 |
36 | speaker_hole_1 = [ case_w - (case_w - lcd_w)/2.5, (2.3*case_h)/10, 0];
37 |
38 | speaker_hole_2 = [ case_w - (case_w - lcd_w)/2.5, (2.6*case_h)/10, 0];
39 |
40 | speaker_hole_3 = [ case_w - (case_w - lcd_w)/2.75, (2.9*case_h)/10, 0];
41 |
42 |
43 | difference()
44 | {
45 | //Create the enclosure body
46 | color("LightGray") square([case_w,case_h]);
47 |
48 |
49 | //Create the hole to place the LCD 7.5mm x 5.5mm
50 | translate([lcd_x, lcd_y, 0]) square([lcd_w, lcd_h ]);
51 |
52 |
53 | //Create the hole to place the joystick
54 | translate(pad_pos) scale(pad_diameter) circle( $fn=8 );
55 |
56 | //Place the A button
57 | translate(button_a_pos) scale(button_diameter) circle( $fn=16 );
58 |
59 | //Place the B button
60 | translate(button_b_pos) scale(button_diameter) circle( $fn=16 );
61 |
62 | //Place the start button
63 | translate(button_start_pos) scale(button_diameter) square([3,1]);
64 |
65 | //Place the select button
66 | translate(button_select_pos) scale(button_diameter) square([3,1]);
67 |
68 | //Place the speaker holes
69 | translate(speaker_hole_0) scale(button_diameter) square([3,0.20]);
70 | translate(speaker_hole_1) scale(button_diameter) square([4,0.20]);
71 | translate(speaker_hole_2) scale(button_diameter) square([4,0.20]);
72 | translate(speaker_hole_3) scale(button_diameter) square([3,0.20]);
73 |
74 |
75 | };
76 | };
77 | //---------------------------------------------------------------------------------
78 | module papiGB_case_side()
79 | {
80 |
81 |
82 |
83 | difference()
84 | {
85 | // cubeX(size=[case_w,case_h,case_depth],radius=10,center=true );
86 |
87 | cube(size=[case_w,case_h,case_depth]);
88 | translate( [case_thickness,case_thickness,-1] )
89 | cube(size=[case_w-2*case_thickness,case_h-2*case_thickness,case_depth+case_thickness]);
90 | };
91 | }
92 | //---------------------------------------------------------------------------------
93 | //Instantiate the case
94 | papiGB_case_top();
95 | translate([0,0,-case_depth]) papiGB_case_side();
96 |
97 |
--------------------------------------------------------------------------------
/script/check_bios_log.py:
--------------------------------------------------------------------------------
1 | import re
2 | from sys import argv
3 |
4 | reg_names = ['SP', 'B', 'C', 'D', 'E', 'H', 'L', 'A', 'Flags']
5 | # PC SP B C D E H L A Flags
6 | # 0x0000 LD SP, $0xFFFE
7 | bios_checker = {'00000003': ['fffe', '*', '*', '*', '*', '*', '*', '*', '*'],
8 | # 0x0003 XOR A
9 | '00000004': ['*', '*', '*', '*', '*', '*', '*', '00', '*'],
10 | # 0x000C LD HL, $0xFF26 # load 0xFF26 to HL
11 | '0000000f': ['*', '*', '*', '*', '*', 'ff', '26', '*', '*'],
12 | # 0x000F LD C, $0x11 # load 0x11 to C
13 | '00000011': ['*', '*', '11', '*', '*', '*', '*', '*', '*'],
14 | # 0x0011 LD A, $0x80 # load 0x80 to A
15 | '00000013': ['*', '*', '*', '*', '*', '*', '*', '80', '*'],
16 | # 0x0013 LD (HL-), A # load A [HL], HL--
17 | '00000015': ['*', '*', '*', '*', '*', 'ff', '25', '*', '*'],
18 | # 0x0015 INC C # increment C register
19 | '00000016': ['*', '*', '12', '*', '*', '*', '*', '*', '*'],
20 | # 0x0016 LD A, $0xF3 # load 0xF3 to A
21 | '00000018': ['*', '*', '*', '*', '*', '*', '*', 'f3', '*'],
22 | # 0x001A LD A, $0x77 # load 0x77 to A
23 | '0000001c': ['*', '*', '*', '*', '*', '*', '*', '77', '*'],
24 | # 0x001D LD A, $0xFC # A represents the color number mappings
25 | '0000001f': ['*', '*', '*', '*', '*', '*', '*', 'fc', '*'],
26 | # 0x0021 LD DE, $0x0104 # pointer to Nintendo Logo
27 | '00000024': ['*', '*', '*', '01', '04', '*', '*', '*', '*'],
28 | # 0x0024 LD HL, $0x8010 # pointer to Video RAM
29 | '00000027': ['*', '*', '*', '*', '*', '80', '10', '*', '*'],
30 | # 0x0027 LD A, (DE) # load next byte from Nintendo Logo
31 | '00000028': ['*', '*', '*', '*', '*', '*', '*', 'ce', '*'],
32 | # 0x0028 CALL $0x0095 # decompress, scale
33 | # 0x0095 LD C, A # load A to C
34 | '00000096': ['*', '*', 'ce', '*', '*', '*', '*', 'ce', '*'],
35 | # 0x0096 LD B, $0x4 #
36 | '00000098': ['*', '04', '*', '*', '*', '*', '*', '*', '*'],
37 | # 0x0099 RL C # rotate left register C through carry flag
38 | '0000009b': ['*', '*', '9c', '*', '*', '*', '*', '*', '00010000'],
39 | }
40 |
41 |
42 | script, filename = argv
43 |
44 | with open(filename, "r") as file:
45 | for line in file:
46 | if (not re.match("^\[regs\]", line)):
47 | continue
48 |
49 | regs = re.split("\s+", line)
50 | pc = regs[1]
51 | regs = regs[2:]
52 |
53 | if (pc not in bios_checker):
54 | continue
55 |
56 | print(line)
57 | for reg, value, name in zip(regs, bios_checker[pc], reg_names):
58 | if (value == '*'):
59 | continue
60 |
61 | print(("pc {0}. {1} {2} found {3}").format(pc, name, value, reg))
62 | if (value != reg):
63 | raise Exception(("Register mismatch\n"))
64 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/tb_simple_channel1.v:
--------------------------------------------------------------------------------
1 | //Dummy tb for sound channel 1.
2 | //Tb is only for debug this module.
3 |
4 | `timescale 1ns / 1ps
5 | `include "aDefinitions.v"
6 | `include "collaterals.v"
7 | `include "SoundControllerChannel1.v"
8 | `include "SoundControllerOSC1.v"
9 | `include "SoundControllerOSC2.v"
10 |
11 | module tb;
12 |
13 | reg clk;
14 | wire clk64;
15 | wire clk128;
16 | wire clk256;
17 | wire clk131k;
18 | wire clk262k;
19 | reg rst;
20 | wire [4:0] out;
21 |
22 | reg [7:0] nr10;
23 | reg [7:0] nr11;
24 | reg [7:0] nr12;
25 | reg [7:0] nr13;
26 | reg [7:0] nr14;
27 |
28 | always begin
29 | #`CLOCK_CYCLE clk = ~clk;
30 | end
31 |
32 | osc1 o1
33 | (
34 | .iClock(clk),
35 | .iReset(rst),
36 | .oOut64(clk64),
37 | .oOut128(clk128),
38 | .oOut256(clk256)
39 | );
40 |
41 | osc2 o2
42 | (
43 | .iClock(clk),
44 | .iReset(rst),
45 | .oOut131k(clk131k),
46 | .oOut262k(clk262k)
47 | );
48 |
49 | SoundCtrlChannel1 # () scc1 (
50 | .iClock(clk),
51 | .iReset(rst),
52 | .iOsc64(clk64),
53 | .iOsc128(clk128),
54 | .iOsc256(clk256),
55 | .iOsc262k(clk262k),
56 | .iNR10(nr10),
57 | .iNR11(nr11),
58 | .iNR12(nr12),
59 | .iNR13(nr13),
60 | .iNR14(nr14),
61 | .oOut(out)
62 | );
63 |
64 |
65 | integer i;
66 |
67 | initial begin
68 | //$dumpfile("dump_sound_channel1.vcd");
69 | //$dumpvars();
70 | //$display("tiempo \t\t out1");
71 | //$monitor ("%0d \t\t %0d",$time, out);
72 | clk = 0;
73 | rst = 1'b0;
74 | #10 rst = 1'b1;
75 |
76 | //test1
77 | ///*
78 | nr10 = 8'h00; // disable sweep control.
79 | nr11 = 8'h1F; // length = $1F = 31.
80 | nr12 = 8'hF4; // attenuate envelope, step time = 4. initial value = $F = 15.
81 | nr13 = 8'hBC; // low fre = $BC.
82 | nr14 = 8'h03; // high freq = $3, freq = $3BC = 956. timer disabled.
83 | //*/
84 |
85 | //test2
86 | /*
87 | nr10 = 8'h00; // disable sweep control
88 | nr11 = 8'h01; // length = $01 = 01.
89 | nr12 = 8'h1C; // amplify envelope, step time = 7. initial value = $2 = 2.
90 | nr13 = 8'hBC; // low freq = $BC.
91 | nr14 = 8'h43; // high freq = $3 , freq = $3BC = 956. time enabled.
92 | */
93 |
94 | //test3
95 | /*
96 | nr10 = 8'h59; // subtraction sweep, n= 1. sweep time = 3.
97 | nr11 = 8'h1F; // length = $1F = 31.
98 | nr12 = 8'hF0; // disable envelope, step time = 7. initial value = $F = 15.
99 | nr13 = 8'hD0; // low freq = $0D
100 | nr14 = 8'h07; // high freq = $7, freq = $70D = 1805. timer disabled.
101 | */
102 |
103 | //test4
104 | /*
105 | nr10 = 8'h51; // addition sweep, n = 1. sweep time = 3.
106 | nr11 = 8'h1F; // length = $1F = 31
107 | nr12 = 8'hF0; // disable envelope, step time = 3. initial value = $2 = 2.
108 | nr13 = 8'h30; // low freq = $30.
109 | nr14 = 8'h00; // high freq = $0 , freq = $030 = 48. timer disabled.
110 | */
111 |
112 | repeat (2) @ (negedge clk);
113 | rst = 1'b0;
114 |
115 | for ( i = 0; i < 10000; i = i+1) begin
116 | #5120 $display ("%0d, ", out);
117 | end
118 | // #50_000_000;
119 |
120 | $finish;
121 | end
122 |
123 | endmodule
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # papiGB
4 | Game Boy Classic fully functional FPGA implementation from scratch
5 |
6 | ###Requirements
7 |
8 | `sudo apt-get install iverilog gtkwave`
9 |
10 |
11 | ##Compiling code
12 | `cd sim/`
13 |
14 | `make compile`
15 |
16 | ##Running a simulation
17 |
18 | `cd sim/`
19 |
20 | `make run`
21 |
22 | Once the simulation completes, the following ASCII files are generated under the sim/ folder:
23 |
24 | * pgb_cpu.log : Z80 macro instructions and their corresponding micro-code flows
25 | * pgb_gpu.log: GPU micro code dump
26 | * generated_frames/*.ppm : PPM representation of the video buffer frames at the time the simulation ended. (Open it with gimp)
27 | * papi_vram_8000_8fff.dump : Memory dump for the Tile set region 0
28 | * papi_vram_9800_9bff.dump : Memory dump for the Tile map region 0
29 | * tb_simple_dzcpu : Simulation testbench executable
30 |
31 | Simulations will not automatically generate a VCD dump file.
32 | To generate a VCD dump do:
33 |
34 | `make DUMPTYPE=vcd`
35 |
36 | ##Simulation Options
37 | To control additional simulation options, use the SIMFLAGS flag. Valid values are:
38 |
39 | * ``-DSTOP_AFTER_FIRST_FRAME`` : The simulation will stop once the first frame has been generated under the sim/generated_frames/ folder
40 | * ``-DENABLE_CPU_LOG`` : Enables pgb_cpu.log generation (enabled by default)
41 | * ``-DENABLE_GPU_LOG`` : Enables pgb_cpu.log generation (enabled by default)
42 | * ``-DCARTRIGDE_DUMP_PATH`` : When LOAD_CARTRIDGE_FROM_FILE is set, then this flag specifies the path to the dump file
43 | * ``-DSKIP_BIOS`` : Skips the BIOS code, first 256 instructions, effectively jumping directly to 0x100
44 | * ``-DDISABLE_CPU``: Disables the CPU from running
45 | * ``-DVMEM_DUMP_PATH``: When LOAD_VMEM_DUMP is set, then this flag specifies the path to the VMEME dump file.
46 | * ``-DSIMULATION_TIME_OUT``: Specify a simulation timeout in nanoseconds
47 | Example:
48 |
49 | The following command will stop the simulation after the first frame, will generate GPU log, but will not generate CPU log.
50 |
51 | `make SIMFLAGS="-DSTOP_AFTER_FIRST_FRAME -DENABLE_GPU_LOG"`
52 |
53 | The following command will simulate RTL using a cartrigde file:
54 |
55 | `make SIMFLAGS=" -DCARTRIGDE_DUMP_PATH='\"resources/tetris.dump\"'"`
56 |
57 | The following command will disable the CPU and load VMEM data from a dump file:
58 |
59 | `make SIMFLAGS="-DDISABLE_CPU -DVMEM_DUMP_PATH='\"resources/tetris_vmem_8000_9fff.dump\"' -DENABLE_GPU_LOG -DSTOP_AFTER_FIRST_FRAME"`
60 |
61 |
62 | ##Looking at simulation results
63 |
64 | `cd sim/`
65 |
66 | `make view`
67 |
68 | ##Cleaning up simulation files.
69 | This also erases the vcd and the log files!
70 |
71 | `make clean`
72 |
73 | ##Installing a game boy assembly
74 |
75 | RGBDS is a great gameboy assembly (https://www.anjbe.name/rgbds/)
76 |
77 | To install it do:
78 |
79 | `git clone https://github.com/bentley/rgbds/`
80 |
81 | `cd rgbds`
82 |
83 | `sudo apt-get install bison flex`
84 |
85 | `make`
86 |
87 | `sudo make install`
88 |
89 | To compile an assebly program called test_INCr_b.asm do:
90 |
91 | `rgbasm -o test_INCr_b.obj test_INCr_b.asm`
92 |
93 | `rgblink -m test_INCr_b.map -n test_INCr_b.sym -o test_INCr_b.gb test_INCr_b.obj`
94 |
95 | The use hexdump to get the ASCII hex dump to load into the RTL simulation:
96 |
97 | `hexdump -v test_INCr_b.gb > test_INCr_b.hex`
98 |
99 |
100 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerMX.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 2. Squate waves with variable timmer, configurable frequency and envelope functions.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 | module SoundCtrlMX //parameters
25 | (
26 | input wire iClock, //CPU CLOCK, 4194304Hz
27 | input wire iReset,
28 | input wire iOsc262k, //OSC2 clock 131072Hz
29 |
30 | input wire [4:0] iOut1, // Channel 1.
31 | input wire [4:0] iOut2, // Channel 2.
32 | input wire [4:0] iOut3, // Channel 3.
33 | input wire [4:0] iOut4, // Channel 4.
34 |
35 | input wire [7:0] iNR50, // Left/Right enable + Left/Right volume.
36 | input wire [7:0] iNR51, // Enable channel 1/2/3/4 in Left/Right.
37 |
38 | output reg [4:0] oSO1, // Left channel.
39 | output reg [4:0] oSO2, // Right channel.
40 |
41 | output wire [1:0] oChSel,
42 | output wire oChClk
43 | );
44 |
45 | reg [7:0] rNR50, rNR51;
46 | reg [4:0] rSO1_PRE, rSO2_PRE;
47 | reg rSer_clk; // 8kHz clock, used for serializer.
48 | reg [1:0] rSer_sel; // Indicates which channel data were sent.
49 |
50 |
51 | //Registers load
52 | always @ (posedge iClock) begin
53 | if (iReset) begin
54 | rNR50 <= iNR50;
55 | rNR51 <= iNR51;
56 | rSer_sel <= 2'b0;
57 | rSer_clk <= 1'b0;
58 |
59 | rSO1_PRE <= 5'd15;
60 | rSO2_PRE <= 5'd15;
61 |
62 | end
63 | end
64 |
65 | //Serializer
66 | always @ (posedge iOsc262k) begin
67 | rSer_clk <= ~rSer_clk;
68 | rSer_sel <= (~rSer_clk) ? rSer_sel + 1 : rSer_sel;
69 | end
70 |
71 | //Volume control
72 | always @ (*) begin
73 |
74 | case (rSer_sel)
75 | 2'd0: begin
76 | rSO1_PRE = (rNR51[0]) ? iOut1 : 5'd15;
77 | rSO2_PRE = (rNR51[4]) ? iOut1 : 5'd15;
78 | end
79 | 2'd1: begin
80 | rSO1_PRE = (rNR51[1]) ? iOut2 : 5'd15;
81 | rSO2_PRE = (rNR51[5]) ? iOut2 : 5'd15;
82 | end
83 | 2'd2: begin
84 | rSO1_PRE = (rNR51[2]) ? iOut3 : 5'd15;
85 | rSO2_PRE = (rNR51[6]) ? iOut3 : 5'd15;
86 | end
87 | 2'd3: begin
88 | rSO1_PRE = (rNR51[3]) ? iOut4 : 5'd15;
89 | rSO2_PRE = (rNR51[7]) ? iOut4 : 5'd15;
90 | end
91 | default: begin
92 | rSO1_PRE = 5'dX;
93 | rSO2_PRE = 5'dX;
94 | end
95 | endcase
96 |
97 | oSO1 = rSO1_PRE >> (3'd7-rNR50[2:0]);
98 | oSO2 = rSO1_PRE >> (3'd7-rNR50[6:4]);
99 |
100 | end
101 |
102 | assign oChSel = rSer_sel;
103 | assign oChClk = rSer_clk;
104 |
105 | endmodule
106 |
--------------------------------------------------------------------------------
/rtl/io.v:
--------------------------------------------------------------------------------
1 |
2 | `timescale 1ns / 1ps
3 |
4 | `include "collaterals.v"
5 |
6 | module io
7 | (
8 | input wire Clock,
9 | input wire Reset,
10 | input wire [5:0] iP, //Pressed button
11 | output wire [5:0] oP, //[5:4] most be triggered before [3:0]
12 | output wire oIE //Enable interruption $FFFF
13 | );
14 |
15 | wire [5:0] wiPlast;
16 | wire [5:0] woPlast;
17 | wire [5:0] wXnorAresult;
18 | wire [5:0] wXnorBresult;
19 | wire [5:0] wXnorCresult;
20 | wire [5:0] wMuxAresult;
21 | wire [5:0] wMuxBresult;
22 |
23 | reg [5:0] rP;
24 | `ifdef PRESS_A_KEY_AFTER
25 | FFD_POSEDGE_SYNCRONOUS_RESET # ( 6 ) FFD_oHack
26 | (
27 | .Clock(Clock),
28 | .Reset(Reset),
29 | .Enable(1'b1),
30 | .D(6'b111101),
31 | .Q(oP)
32 | );
33 | `else
34 | assign oP = rP;
35 | `endif
36 |
37 | FFD_POSEDGE_SYNCRONOUS_RESET # ( 6 ) FFD_oP
38 | (
39 | .Clock(Clock),
40 | .Reset(Reset),
41 | .Enable(1'b1),
42 | .D(oP),
43 | .Q(woPlast)
44 | );
45 |
46 | FFD_POSEDGE_SYNCRONOUS_RESET # ( 6 ) FFD2_iP
47 | (
48 | .Clock(Clock),
49 | .Reset(Reset),
50 | .Enable(1'b1),
51 | .D(iP),
52 | .Q(wiPlast)
53 | );
54 |
55 | XNOR # ( 6 ) XOR1
56 | (
57 | .inA(iP),
58 | .inB(woPlast),
59 | .out(wXnorAresult)
60 | );
61 |
62 | XNOR # ( 6 ) XNOR2
63 | (
64 | .inA(iP),
65 | .inB(wiPlast),
66 | .out(wXnorBresult)
67 | );
68 |
69 | MUX2 # ( 6 ) MUX1
70 | (
71 | .select(&iP),
72 | .inA(wXnorAresult),
73 | .inB(iP),
74 | .out(wMuxAresult)
75 | );
76 |
77 | // assign wMuxBresult = (woPlast == iP) ? iP : wMuxAresult;
78 | MUX2 # ( 6 ) MUX2
79 | (
80 | .select(&wXnorAresult),
81 | .inA(wMuxAresult),
82 | .inB(iP),
83 | .out(wMuxBresult)
84 | );
85 |
86 | // assign oIE = (&oP == 0) ? 1 : 0;
87 | MUX2 # ( 1 ) MUX3
88 | (
89 | .select(&oP),
90 | .inA(1),
91 | .inB(0),
92 | .out(oIE)
93 | );
94 |
95 |
96 | always @ ( * )
97 | begin
98 | case (wMuxBresult)
99 | // one button is pressed. Or two buttons pressed with diferrent ending and type. Ex. Left + Start. Or juest A.
100 | 6'b101110, 6'b101101, 6'b101011, 6'b100111, 6'b011110, 6'b011101, 6'b011011, 6'b010111:
101 | begin
102 | `ifdef JOYPAD_TOGGLE_PRESSED_KEY
103 | rP <= wMuxBresult;
104 | `else
105 | if (&wXnorBresult == 0)
106 | rP <= wMuxBresult;
107 | else
108 | rP <= woPlast;
109 | `endif
110 | end
111 |
112 |
113 | // two buttons pressed with the same ending. Ex A + Right (10 1110 + 01 1110)
114 | 6'b011111,6'b101111:
115 | begin
116 | `ifdef JOYPAD_TOGGLE_PRESSED_KEY
117 | rP <= wMuxBresult;
118 | `else
119 | if (&wXnorBresult == 0)
120 | rP <= {wMuxBresult[5:4],woPlast[3:0]};
121 | else
122 | rP <= woPlast;
123 | `endif
124 | end
125 |
126 |
127 | // two buttons pressed with the same type. Ex. Up + Down. A + B
128 | 6'b111110,6'b111101,6'b111011,6'b110111:
129 | begin
130 | `ifdef JOYPAD_TOGGLE_PRESSED_KEY
131 | rP <= wMuxBresult;
132 | `else
133 | if (&wXnorBresult == 0)
134 | rP <= {woPlast[5:4],wMuxBresult[3:0]};
135 | else
136 | rP <= woPlast;
137 | `endif
138 | end
139 |
140 | default:
141 | begin
142 | $display("Default %dns",$time);
143 | rP <= 6'b111111;
144 | end
145 |
146 | endcase
147 | end
148 |
149 | endmodule
150 |
--------------------------------------------------------------------------------
/sim/reference/bios_vram_9800_9bff.dump:
--------------------------------------------------------------------------------
1 |
2 | 00009800 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3 | 00009810 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4 | 00009820 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5 | 00009830 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6 | 00009840 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7 | 00009850 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8 | 00009860 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9 | 00009870 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 | 00009880 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 | 00009890 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
12 | 000098a0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13 | 000098b0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
14 | 000098c0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
15 | 000098d0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16 | 000098e0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
17 | 000098f0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
18 | 00009900 : 00 00 00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c
19 | 00009910 : 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 | 00009920 : 00 00 00 00 0d 0e 0f 10 11 12 13 14 15 16 17 18
21 | 00009930 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22 | 00009940 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
23 | 00009950 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
24 | 00009960 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
25 | 00009970 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
26 | 00009980 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
27 | 00009990 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
28 | 000099a0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
29 | 000099b0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 | 000099c0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
31 | 000099d0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32 | 000099e0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
33 | 000099f0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
34 | 00009a00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
35 | 00009a10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
36 | 00009a20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
37 | 00009a30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
38 | 00009a40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
39 | 00009a50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40 | 00009a60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
41 | 00009a70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
42 | 00009a80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
43 | 00009a90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
44 | 00009aa0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
45 | 00009ab0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
46 | 00009ac0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
47 | 00009ad0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
48 | 00009ae0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
49 | 00009af0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50 | 00009b00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
51 | 00009b10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
52 | 00009b20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
53 | 00009b30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 | 00009b40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
55 | 00009b50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
56 | 00009b60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
57 | 00009b70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
58 | 00009b80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
59 | 00009b90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60 | 00009ba0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
61 | 00009bb0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
62 | 00009bc0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
63 | 00009bd0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
64 | 00009be0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
65 | 00009bf0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
--------------------------------------------------------------------------------
/rtl/gpu_definitions.v:
--------------------------------------------------------------------------------
1 | //`timescale 1ns / 1ps
2 | ////////////////////////////////////////////////////////////////////////////////////
3 | //
4 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
5 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
6 | //
7 | // This program is free software; you can redistribute it and/or
8 | // modify it under the terms of the GNU General Public License
9 | // as published by the Free Software Foundation; either version 2
10 | // of the License, or (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with this program; if not, write to the Free Software
19 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 | //
21 | ////////////////////////////////////////////////////////////////////////////////////
22 |
23 |
24 |
25 | `ifndef GPU_DEFINITIONS_V
26 | `define GPU_DEFINITIONS_V
27 |
28 | `define GPU_UOP_SZ 23
29 | `define GPU_OP_RNG 22:18
30 | `define GPU_DST_RNG 17:12
31 | `define GPU_S1_RNG 11:6
32 | `define GPU_S0_RNG 5:0
33 | `define GPU_LIT_RNG 9:0
34 |
35 | `define GPU_S1_RNG_SEL_BIT 11
36 | `define GPU_S1_RNG_H 10:6
37 | `define GPU_S1_RNG_L 9:6
38 |
39 | `define GPU_S0_RNG_SEL_BIT 5
40 | `define GPU_S0_RNG_H 4:0
41 | `define GPU_S0_RNG_L 3:0
42 |
43 |
44 |
45 | `define SPRITE_COLOR_TRANSPARENT 2'b0
46 | `define SCANLINE_VRAM_READ 12'd3
47 |
48 |
49 | //Operations
50 | `define gnop 5'd0
51 | `define gwrl 5'd1
52 | `define gwrr 5'd2
53 | `define gadd 5'd3
54 | `define gsub 5'd4
55 | `define gaddl 5'd5
56 | `define gjnz 5'd6
57 | `define gwfbuffer 5'd7
58 | `define gsubl 5'd8
59 | `define grvmem 5'd9
60 | `define gshl 5'd10
61 | `define ggoto 5'd11
62 | `define gjz 5'd12
63 | `define gand 5'd13
64 | `define gsprtt 5'd14 //Test if sprite is within (or partially in) current tile rectangle
65 | `define ginfbaddr 5'd16 //Increment the FrameBuffer write pointer
66 | `define gwx 5'd17
67 | `define gwy 5'd18
68 | //Registers
69 | `define gnull 6'd0
70 |
71 | `define lcdc 6'd0
72 | `define state 6'd1
73 | `define scx 6'd2
74 | `define scy 6'd3
75 | `define ly 6'd4
76 | `define lyc 6'd5
77 | `define dma 6'd6
78 | `define bgp 6'd7
79 | `define obp0 6'd8
80 | `define obp1 6'd9
81 | `define wx 6'd10
82 | `define wy 6'd11
83 | `define vmem_addr 6'd12
84 | `define bh 6'd13
85 | `define bl 6'd14
86 | `define fbuffer_addr 6'd15
87 | `define cur_tile 6'd16
88 | `define sprite_current_row_offset 6'd17
89 | `define sprite_x_coord 6'd18
90 | `define sprite_y_coord 6'd19
91 | `define tile_row 6'd20
92 | `define sh 6'd21 //Sprite MSByte
93 | `define sl 6'd22 //Sprite MSByte
94 | `define r0 6'd23
95 | `define r1 6'd24
96 | `define r2 6'd25
97 | `define r3 6'd26
98 | `define r4 6'd27
99 | `define r5 6'd28
100 | `define r6 6'd29
101 | `define WinTile 6'd30
102 | `define sprite_info 6'd31
103 | `define bgmoffset 6'd32
104 | `define bgtoffset 6'd33
105 | `define vmem_data 6'd34
106 | `define bg_row_offset 6'd35
107 | `define ly_mod_8 6'd36
108 | `define r8191 6'd37
109 | `define oam_offset 6'd38
110 | `define vmem_data_shl_4 6'd39
111 | `define scy_shl_5__plus_scx 6'd40
112 | `define scy_tile_row_offset 6'd41
113 | `define IsThisTileWin 6'd42
114 | `define Win_index 6'd43
115 | `define Winmoffset 6'd44
116 | `define Window_render 6'd23 //save window render in r0
117 | //Jump labels
118 | `define get_next_sprite 18'd51
119 | `define skip_the_sprites 18'd54 //remember to change during testing of new uop
120 | `define skip_the_window 18'd84
121 | `define render_window 18'd68
122 | `define initialize_window 18'd66
123 | `endif
124 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerChannel2.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 2. Squate waves with variable timmer, configurable frequency and envelope functions.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 |
25 | module SoundCtrlChannel2 //parameters
26 | (
27 | input wire iClock, //CPU CLOCK, 4194304Hz
28 | input wire iReset,
29 | input wire iOsc64, //OSC1 clock 64Hz
30 | input wire iOsc256, //OSC1 clock 256Hz
31 | input wire iOsc262k, //OSC2 clock 131072Hz
32 |
33 | input wire [7:0] iNR21,
34 | input wire [7:0] iNR22,
35 | input wire [7:0] iNR23,
36 | input wire [7:0] iNR24,
37 |
38 | output reg [4:0] oOut,
39 | output wire oOnFlag
40 | );
41 |
42 | reg [5:0] rLength;
43 | reg [19:0] rLengthCounter;
44 | reg [1:0] rDutyCycle;
45 | reg rTimedMode;
46 | reg rLengthComplete; // Channe disable.
47 |
48 | reg rTone;
49 | reg [10:0] rSoundFrequency;
50 | reg [10:0] rSoundFrequencyCounter;
51 |
52 | reg [3:0] rStep;
53 | reg [18:0] rStepTime;
54 | reg [18:0] rStepCounter;
55 | reg [3:0] rInitialValue;
56 | reg rEvelopeMode;
57 |
58 | wire [4:0] up_value, down_value;
59 |
60 | // register load
61 | always @(posedge iClock) begin
62 | if (iReset || iNR24[7]) begin // Register reload and counters restart.
63 |
64 | rLength <= iNR21[5:0];
65 | rLengthCounter <= 64-iNR21[5:0]; // Decrements to zero then load rLength.
66 | rLengthComplete <= 0; // Disables channel when is asserted.
67 | rDutyCycle <= iNR21[7:6];
68 | rTimedMode <= iNR24[6];
69 |
70 | rStepTime <= iNR22[2:0];
71 | rStepCounter <= iNR22[2:0]; // Decrements to zero then load rStepTime.
72 | rEvelopeMode <= iNR22[3];
73 | rInitialValue <= iNR22[7:4];
74 | rStep <= iNR22[7:4];
75 |
76 | rTone <= 0;
77 | rSoundFrequency[7:0] <= iNR23[7:0];
78 | rSoundFrequency[10:8] <= iNR24[2:0];
79 | rSoundFrequencyCounter <= 2048-{iNR24[2:0],iNR23[7:0]};
80 |
81 | end
82 | end
83 |
84 | // step gen: generates the output amplitud value.
85 | always @(posedge iOsc64) begin
86 | if (rStepTime != 0) begin // Check if channel is enabled.
87 | if (rStepCounter ==1 ) begin
88 | rStepCounter <= rStepTime; // Reset counter.
89 | if(rEvelopeMode) begin // Envelope mode.
90 | rStep <= ((rStep == 4'hF) ? rStep : rStep+1); //INCREASES ONLY IF STEP IF LOWER THAN TOP VALUE
91 | end
92 | else begin
93 | rStep <= ((rStep == 4'h0) ? rStep : rStep-1); //DECREASES ONLY IF STEP IF LOWER THAN BOTTOM VALUE
94 | end
95 | end
96 | else begin
97 | rStepCounter <= rStepCounter-1;
98 | end
99 | end
100 | end
101 |
102 | // tone gen: generates the frecuency of the output.
103 | always @(posedge iOsc262k) begin
104 | if (rSoundFrequencyCounter ==0) begin
105 | rSoundFrequencyCounter <= 2048-rSoundFrequency;
106 | rTone <= ~rTone;
107 | end
108 | else begin
109 | rSoundFrequencyCounter <= rSoundFrequencyCounter-1;
110 | end
111 | end
112 |
113 |
114 | // timmer: enable or disable channel output.
115 | always @(posedge iOsc256) begin
116 | if (rLengthCounter == 0) begin
117 | rLengthCounter <= 64-rLength;
118 | rLengthComplete <= rTimedMode; // Disable channel only if timmer is enabled.
119 | end
120 | else begin
121 | rLengthCounter <= rLengthCounter-1;
122 | end
123 | end
124 |
125 | //re-map mux
126 | assign up_value = 5'd15 + rStep;
127 | assign down_value = 5'd15 - rStep;
128 |
129 | always @(posedge iClock) begin
130 | if (rLengthComplete) begin
131 | oOut[4:0] <= 5'd15;
132 | end
133 | else begin
134 | if (rTone) begin
135 | oOut[4:0] <= up_value[4:0];
136 | end
137 | else begin
138 | oOut[4:0] <= down_value[4:0];
139 | end
140 | end
141 | end
142 |
143 | assign oOnFlag = rLengthComplete;
144 | endmodule
145 |
--------------------------------------------------------------------------------
/rtl/VgaController.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //The papilio logic start wing has 4096 color depth.
3 | //Each color R,G and B is 4 bits.
4 | //The VGA section of the LogicStart Shield uses 12 resistors to implement
5 | // 4096 color depth. VGA video is analog in nature so there needs to be
6 | // some way to vary the RGB (Red, Green, and Blue) signals between 0V and
7 | //.7V. For each RGB signal the shade, or intensity, of the color is
8 | // controlled by varying the voltage of the pin between 0 and .7V.
9 | //The finer control you have over the voltage the more colors you
10 | //can create. For the LogicStart Shield we are able to control 4
11 | // Red, 4 Green, and 4 Blue bits which allows us to generate 16
12 | //different voltage levels between 0 and .7V for Red and Green and Blue.
13 | //If we add all three colors together we have 12 bit video which gives
14 | //us (2^12=4096) the possibility of 4096 colors.
15 |
16 | module VgaController
17 | (
18 | input wire Clock,
19 | input wire Reset,
20 | output wire [3:0] oVgaRed,oVgaGreen,oVgaBlue,
21 | output wire oVgaVsync, //Polarity of horizontal sync pulse is negative.
22 | output wire oVgaHsync, //Polarity of vertical sync pulse is negative.
23 | output wire [15:0] oRow,oCol
24 |
25 | );
26 |
27 | wire wHSync,wVSync,wPolarity_V,wPolarity_H;
28 |
29 |
30 |
31 | //The Papilio Duo clock is 32Mhz. We will create a 64Mhz to trick
32 | //the VGA into thinking that we are XGA 1024x768@60 Hz (pixel clock 65.0 MHz)
33 |
34 |
35 | //`define XGA_1280x1024_60Hz
36 | //`define XGA_1024x768_60Hz
37 | `ifdef XGA_1024x768_60Hz
38 | //http://tinyvga.com/vga-timing/1024x768@60Hz
39 | parameter HSYNC_VISIBLE_AREA = 1024;
40 | parameter HSYNC_FRONT_PORCH = 24;
41 | parameter HSYNC_PULSE = 136;
42 | parameter HSYN_BACK_PORCH = 48;
43 | parameter HORIZONTAL_LINE = 1344;
44 |
45 |
46 | parameter VSYNC_VISIBLE_AREA = 768;
47 | parameter VSYNC_FRONT_PORCH = 3;
48 | parameter VSYNC_PULSE = 6;
49 | parameter VSYN_BACK_PORCH = 38;
50 | parameter VERTICAL_LINE = 806;
51 |
52 | //65.0Mhz = 32Mhz*27/8 = 66Mhz
53 | parameter CLK_M = 31;
54 | parameter CLK_D = 15;
55 |
56 | assign wPolarity_V = 1'b0;
57 | assign wPolarity_H = 1'b0;
58 |
59 | `elsif XGA_1280x1024_60Hz
60 | //http://tinyvga.com/vga-timing/1280x1024@60Hz
61 | //Tested in a Dell LCD Monitor from LICIT and also in my home LCD Monitor
62 |
63 | parameter HSYNC_VISIBLE_AREA = 1280;
64 | parameter HSYNC_FRONT_PORCH = 48;
65 | parameter HSYNC_PULSE = 112;
66 | parameter HSYNC_BACK_PORCH = 248;
67 | parameter HORIZONTAL_LINE = 1688;
68 |
69 |
70 | parameter VSYNC_VISIBLE_AREA = 1024;
71 | parameter VSYNC_FRONT_PORCH = 1;
72 | parameter VSYNC_PULSE = 3;
73 | parameter VSYNC_BACK_PORCH = 38;
74 | parameter VERTICAL_LINE = 1066;
75 |
76 | //108.0Mhz = 32Mhz*27/8
77 | parameter CLK_M = 27;
78 | parameter CLK_D = 8;
79 |
80 | assign wPolarity_V = 1'b0;
81 | assign wPolarity_H = 1'b0;
82 |
83 |
84 | `else
85 |
86 | //http://tinyvga.com/vga-timing/640x480@60Hz
87 | //Works fine on LICIT LCD Dell monitor
88 | parameter HSYNC_VISIBLE_AREA = 640;
89 | parameter HSYNC_FRONT_PORCH = 16;
90 | parameter HSYNC_PULSE = 96;
91 | parameter HSYNC_BACK_PORCH = 48;
92 | parameter HORIZONTAL_LINE = 800;
93 |
94 |
95 | parameter VSYNC_VISIBLE_AREA = 480;
96 | parameter VSYNC_FRONT_PORCH = 10;
97 | parameter VSYNC_PULSE = 2;
98 | parameter VSYN_BACK_PORCH = 33;
99 | parameter VERTICAL_LINE = 525;
100 |
101 | //25.175Mhz = 32Mhz*27/28 = 25.14Mhz
102 | parameter CLK_M = 25;
103 | parameter CLK_D = 32;
104 |
105 | assign wPolarity_V = 1'b0;
106 | assign wPolarity_H = 1'b0;
107 |
108 |
109 | `endif
110 |
111 | wire wClockVga,wHCountEnd,wVCountEnd;
112 | wire [15:0] wHCount,wVCount;
113 | wire wPllLocked,wPsDone;
114 |
115 |
116 | `ifdef XILINX_IP
117 | DCM_SP
118 | #
119 | (
120 | .CLKFX_MULTIPLY(CLK_M), //Values range from 2..32
121 | .CLKFX_DIVIDE(CLK_D) //Values range from 1..32
122 |
123 | )
124 | ClockVga
125 | (
126 | .CLKIN(Clock), //32Mhz
127 | .CLKFB(wClockVga), //Feed back
128 | .RST( Reset ), //Global reset
129 | .PSEN(1'b0), //Disable variable phase shift. Ignore inputs to phase shifter
130 | .LOCKED(wPllLocked), //Use this signal to make sure PLL is locked
131 | .PSDONE(wPsDone), //I am not really using this one
132 | .CLKFX(wClockVga) //FCLKFX = FCLKIN * CLKFX_MULTIPLY / CLKFX_DIVIDE
133 |
134 | );
135 | `else
136 | assign wClockVga = Clock;
137 | assign wPllLocked = 1'b1;
138 | `endif
139 | assign wHCountEnd = (wHCount == HORIZONTAL_LINE-1)? 1'b1 : 1'b0;
140 | assign wVCountEnd = (wVCount == VERTICAL_LINE-1) ? 1'b1 : 1'b0;
141 |
142 | UPCOUNTER_POSEDGE # (.SIZE(16)) HCOUNT
143 | (
144 | .Clock(wClockVga),
145 | .Reset(Reset | ~wPllLocked | wHCountEnd),
146 | .Initial(16'b0),
147 | .Enable(wPllLocked),
148 | .Q(wHCount)
149 | );
150 |
151 | UPCOUNTER_POSEDGE # (.SIZE(16)) VCOUNT
152 | (
153 | .Clock(wClockVga),
154 | .Reset(Reset | ~wPllLocked | wVCountEnd ),
155 | .Initial( 16'b0 ),
156 | .Enable(wHCountEnd),
157 | .Q(wVCount)
158 | );
159 |
160 | assign wVSync =
161 | (
162 | wVCount >= (VSYNC_VISIBLE_AREA + VSYNC_FRONT_PORCH ) &&
163 | wVCount <= (VSYNC_VISIBLE_AREA + VSYNC_FRONT_PORCH + VSYNC_PULSE )
164 | ) ? 1'b1 : 1'b0;
165 |
166 | assign wHSync =
167 | (
168 | wHCount >= (HSYNC_VISIBLE_AREA + HSYNC_FRONT_PORCH ) &&
169 | wHCount <= (HSYNC_VISIBLE_AREA + HSYNC_FRONT_PORCH + HSYNC_PULSE )
170 | ) ? 1'b1 : 1'b0;
171 |
172 |
173 | assign oVgaVsync = (wPolarity_V == 1'b1) ? wVSync : ~wVSync ;
174 | assign oVgaHsync = (wPolarity_H == 1'b1) ? wHSync : ~wHSync ;
175 |
176 |
177 |
178 | wire[3:0] wColorR, wColorG, wColorB;
179 | assign wColorR = (wHCount < (HSYNC_VISIBLE_AREA/2)) ? 4'b1111 : 4'b0000;
180 | assign wColorG = (wVCount < (VSYNC_VISIBLE_AREA/2)) ? 4'b1111 : 4'b0000;
181 | assign wColorB = (wHCount >= (HSYNC_VISIBLE_AREA/2) && wVCount < (VSYNC_VISIBLE_AREA/2)) ? 4'b1111: 4'b0000;
182 |
183 | assign {oVgaRed,oVgaGreen,oVgaBlue} = (wHCount < HSYNC_VISIBLE_AREA && wVCount < VSYNC_VISIBLE_AREA) ?
184 | {wColorR,wColorG,wColorB} : //display color
185 | {4'b1111,4'b0,4'b0}; //black
186 |
187 | assign oCol = wHCount;
188 | assign oRow = wVCount;
189 |
190 | endmodule
191 |
--------------------------------------------------------------------------------
/doc/papiGB_design_document.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | Welcome to papiGB!
4 | ===================
5 |
6 |
7 | **papiGB** is an open source project intended to replicate the behavior of the original Nintendo Game Boy.
8 | This guide is intended to walk you through the different parts of the system, providing an overview to understand and contribute to individual project blocks.
9 | papiGB project is hosted on github, this document has been created using StackEdit .
10 |
11 | ----------
12 |
13 | ## Table of contents
14 |
15 | [TOC]
16 |
17 | Why writing RTL design from scratch?
18 | ------------------------------------------------------
19 | In a word: **because it is lots of fun** !
20 |
21 | Besides, nothing compared to the bragging right of playing your favorite game and knowing that deep inside you understand every single signal, and clock, every multiplexer and Flip Flop such allowing Samus to make that next jump!
22 |
23 | 
24 |
25 | Submitting issues and getting help
26 | -------------------------------------------------
27 |
28 | Installing the project
29 | ------------------------------
30 | ### Project dependencies and recommended tool chain
31 |
32 | ### Cloning the repository
33 |
34 | ### Running your first simulation and checking results
35 |
36 |
37 | > **Note:**
38 |
39 | > - Make clean deletes all of the log files under the **/sim** folder, you may want to create a backup if you really need those for later.
40 |
41 |
42 |
43 | Project directory structure
44 | -------------------------------------
45 |
46 | **papiGB** stores the design and simularton files a series of directories.
47 |
48 | - rtl/ :
49 | - tb/ :
50 | - doc/ :
51 | - sim/ :
52 | - scripts/ :
53 | - tests/ :
54 | - /asm/ :
55 |
56 | Simulation Flags
57 | ------------------------
58 | It's possible to customize a simulation through the simulation flag, these are described below.
59 |
60 | Flag | Description
61 | ---- | -----------
62 | STOP\_AFTER\_FIRST\_FRAME | When this flag is ON the CPU raises the flag `rSimulationDone` for stop the simulation after the first frame is completed.
63 | ENABLE\_CPU\_LOG | When this flag is ON generates a log file named "pgb\_cpu.log" that records CPU's state at the beginning of a new flow.
64 | ENABLE\_GPU\_LOG | When this flag is ON generates a log file named "pgb\_gpu.log" that records GPU's state when it is activated.
65 | ENABLE\_SOUND\_TRACE | When this flag is ON generates a dump file named "pgb\_sound\_trace.dump"
66 | VMEM\_DUMP\_PATH | Loads into the Video Memory the file indicated.
67 | OAM\_DUMP\_PATH | Loads into the OAM Memory the file indicated.
68 | START\_DUMP\_INSN | Indicates the first instruction that is recorded in the file pgb\_cpu.log.
69 | SKIP\_BIOS | When this flag is ON the CPU skips bios's data and starts reading cartridge's data.
70 | REG\_TAC | Sets an initial value on register TAC.
71 | REG\_IF | Sets an initial value on register IF.
72 | REG\_A | Sets an initial value on register A.
73 | REG\_F | Sets an initial value on register F.
74 | REG\_B | Sets an initial value on register B.
75 | REG\_C | Sets an initial value on register C.
76 | REG\_H | Sets an initial value on register H.
77 | REG\_L | Sets an initial value on register L.
78 | REG\_D | Sets an initial value on register D.
79 | REG\_E | Sets an initial value on register E.
80 | REG\_SPL | Sets an initial value on the low part of register SP.
81 | REG\_SPH | Sets an initial value on the high part of register SP.
82 | REG\_LCDC | Sets an initial value on register LCDC.
83 | REG\_BGP | Sets an initial value on register BGP.
84 | REG\_DIFF | Sets an initial value for a parameter of register DIV.
85 | DISABLE\_CPU | When this flag is ON the CPU is disabled and the GPU is forced to start.
86 | SIMULATION\_TIME\_OUT | The simulation stops after the time indicated.
87 | CPU\_TRACE\_WORK\_MEMORY | When this flag is ON records the memory used in pgb\_cpu.log.
88 | -------- | --------------
89 |
90 | Running a simulation
91 | ------------------------------
92 |
93 | In order to run a simulation the **Makefile** under the sim folder is used.
94 |
95 | ### Using the **Makefile** SIMFLAGS
96 |
97 | The **Makefile** SIMFLAGS allows you to set the values of many flags in order to change the behavior of the simulation. the -DSIMFLAGS consists of a string which the make command passes to the icarus RTL simulator.
98 | For example, the following make invocation will set the CPU register B=0 at the beginning of the simulation:
99 | > $ make SIMFLAGS=" -DREG_B=0"
100 |
101 |
102 | - -R
103 |
104 | The CPU: **dzCPU!**
105 | ---------------------------
106 |
107 | The original GB CPU was an 8bit Sharp LR35902, which is sort of a Z80
108 | processor specially modified by Nintendo. Essentially, Nintendo took some
109 | opcodes out of the instruction set and added some opcodes of their own. The
110 | Z80 is very similar to an 8080 processor from the early 90s, in the sense
111 | that it has a CISC instruction set. In other words, it features lots of
112 | complex instructions, and each individual instruction does lots of things.
113 | Furthermore, decoding the Z80 instruction set may be a challenging task since
114 | the instruction width varies from single BYTE instruction up to 5 BYTE
115 | instructions. Also instructions take multiple clock cycles to execute and the
116 | time to fetch data from main memory (SRAM) adds additional latency to
117 | individual Z80 instructions.
118 | The dZCPU! uses a micro-code approach to mimic the original Z80 CISC
119 | instruction set. The following diagram illustrates the overall processor
120 | architecture.
121 |
122 | **Insert drawing here **
123 |
124 | Figure 1 shows the basic blocks of the dZCPU!. Essentially, each time a Z80
125 | macro insn is fetched from the MMU, the index to a mirco-code is obtained
126 | from an uCode Look-up-table block. The ucode flow corresponding to that macro
127 | instruction is executed and the next macro instruction is fetched.
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerChannel1.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 1. Squate waves with variable timmer, configurable frequency and envelope functions.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 |
25 | module SoundCtrlChannel1 //parameters
26 | (
27 | input wire iClock, //CPU CLOCK, 4194304Hz
28 | input wire iReset,
29 | input wire iOsc64, //OSC1 clock 64Hz
30 | input wire iOsc256, //OSC1 clock 256Hz
31 | input wire iOsc128, //OSC1 clock 128Hz
32 | input wire iOsc262k, //OSC2 clock 131072Hz
33 |
34 | input wire [7:0] iNR10,
35 | input wire [7:0] iNR11,
36 | input wire [7:0] iNR12,
37 | input wire [7:0] iNR13,
38 | input wire [7:0] iNR14,
39 |
40 | output reg [4:0] oOut,
41 | output wire oOnFlag
42 | );
43 |
44 |
45 | reg [2:0] rSweepShifts;
46 | reg rSweepMode;
47 | reg [2:0] rSweepTime;
48 | reg [17:0] rSweepCounter;
49 | reg [11:0] rSoundFrequencyNew;
50 |
51 |
52 | reg [5:0] rLength;
53 | reg [19:0] rLengthCounter;
54 | reg [1:0] rDutyCycle;
55 | reg rTimedMode;
56 | reg rLengthComplete; // Channe disable.
57 |
58 | reg rTone;
59 | reg [10:0] rSoundFrequency;
60 | reg [10:0] rSoundFrequencyCounter;
61 |
62 |
63 | reg [3:0] rStep;
64 | reg [18:0] rStepTime;
65 | reg [18:0] rStepCounter;
66 | reg [3:0] rInitialValue;
67 | reg rEvelopeMode;
68 |
69 | wire [4:0] up_value, down_value;
70 |
71 | // register load
72 | always @(posedge iClock) begin
73 | if (iReset || iNR14[7]) begin // Register reload and counters restart.
74 |
75 | rLength <= iNR11[5:0];
76 | rLengthCounter <= 64-iNR11[5:0]; // Decrements to zero then load rLength.
77 | rLengthComplete <= 0; // Disables channel when is asserted.
78 | rDutyCycle <= iNR11[7:6];
79 | rTimedMode <= iNR14[6];
80 |
81 | rStepTime <= iNR12[2:0];
82 | rStepCounter <= iNR12[2:0]; // Decrements to zero then load rStepTime.
83 | rEvelopeMode <= iNR12[3];
84 | rInitialValue <= iNR12[7:4];
85 | rStep <= iNR12[7:4];
86 |
87 | rTone <= 0;
88 | rSoundFrequency[10:0] <= 2048-{iNR14[2:0],iNR13[7:0]};
89 | rSoundFrequencyCounter[10:0] <= 2048-{iNR14[2:0],iNR13[7:0]};
90 |
91 | rSoundFrequencyNew <= 2048-{iNR14[2:0],iNR13[7:0]};
92 |
93 | //FREQUENCY SWEEP REGISTERS
94 | rSweepShifts <= iNR10[2:0];
95 | rSweepMode <= iNR10[3];
96 | rSweepTime <= iNR10[6:4];
97 | rSweepCounter <= iNR10[6:4];
98 |
99 | end
100 | end
101 |
102 | // step gen: generates the output amplitud value.
103 | always @(posedge iOsc64) begin
104 | if (rStepTime != 0) begin // Check if channels step function is enabled.
105 | if (rStepCounter ==1 ) begin
106 | rStepCounter <= rStepTime; // Reset counter.
107 | if(rEvelopeMode) begin // Envelope mode.
108 | rStep <= ((rStep == 4'hF) ? rStep : rStep+1); //INCREASES ONLY IF STEP IF LOWER THAN TOP VALUE
109 | end
110 | else begin
111 | rStep <= ((rStep == 4'h0) ? rStep : rStep-1); //DECREASES ONLY IF STEP IF LOWER THAN BOTTOM VALUE
112 | end
113 | end
114 | else begin
115 | rStepCounter <= rStepCounter-1;
116 | end
117 | end
118 | end
119 |
120 | // tone gen: generates the frecuency of the output.
121 | always @(posedge iOsc262k) begin
122 | if (rSoundFrequencyCounter ==0) begin
123 | rSoundFrequencyCounter <= rSoundFrequency;
124 | rTone <= ~rTone;
125 | end
126 | else begin
127 | rSoundFrequencyCounter <= rSoundFrequencyCounter-1;
128 | end
129 | end
130 |
131 | // sweep gen: generates the frequency sweep
132 | always @(posedge iOsc128) begin //128Hz
133 |
134 | if (rSweepCounter ==1 && rSweepShifts != 0 && rSweepTime > 0) begin // calucates new frequency
135 | if (rSweepMode) begin
136 | rSoundFrequencyNew <= rSoundFrequency + (rSoundFrequency >> rSweepShifts);
137 | end
138 | else begin
139 | rSoundFrequencyNew <= rSoundFrequency - (rSoundFrequency >> rSweepShifts);
140 | end
141 | end
142 |
143 | if (rSweepCounter ==0 && rSweepTime > 0) begin // set new frequency counter
144 | if (rSoundFrequencyNew == 1 && rSoundFrequency == 1) begin // frequency is more than 131072
145 | rLengthComplete = 1'b1 ;
146 | end
147 | else if (rSoundFrequencyNew <= 2047) begin // frequency is more than 131072
148 | rSoundFrequency <= rSoundFrequencyNew;
149 | end
150 | rSweepCounter <= rSweepTime;
151 | end
152 |
153 | else begin
154 | rSweepCounter = rSweepCounter-1;
155 | end
156 | end
157 |
158 | // timmer: enable or disable channel output.
159 | always @(posedge iOsc256) begin
160 | if (rLengthCounter == 0) begin
161 | rLengthCounter <= 64-rLength;
162 | rLengthComplete <= (rTimedMode || rLengthComplete); // Disable channel only if timmer is enabled.
163 | end
164 | else begin
165 | rLengthCounter <= rLengthCounter-1;
166 | end
167 | end
168 |
169 | //re-map mux
170 | assign up_value = 5'd15 + rStep;
171 | assign down_value = 5'd15 - rStep;
172 |
173 | always @(posedge iClock) begin
174 | if (rLengthComplete) begin
175 | oOut[4:0] <= 5'd15;
176 | end
177 | else begin
178 | if (rTone) begin
179 | oOut[4:0] <= up_value[4:0];
180 | end
181 | else begin
182 | oOut[4:0] <= down_value[4:0];
183 | end
184 | end
185 | end
186 |
187 | assign oOnFlag = rLengthComplete;
188 |
189 | endmodule
190 |
--------------------------------------------------------------------------------
/sim/signals/tb_simple_dzcpu.gtkw:
--------------------------------------------------------------------------------
1 | [*]
2 | [*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
3 | [*] Sun Aug 21 04:24:36 2016
4 | [*]
5 | [dumpfile] "/home/diego/workspace/projects/papiGB/sim/tb_simple_dzcpu.vcd"
6 | [dumpfile_mtime] "Sun Aug 21 01:21:13 2016"
7 | [dumpfile_size] 265149706
8 | [savefile] "/home/diego/workspace/projects/papiGB/sim/signals/tb_simple_dzcpu.gtkw"
9 | [timestart] 12098558900
10 | [size] 1366 744
11 | [pos] -1 -1
12 | *-15.674738 12098645000 111600 1875031400 1876195000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
13 | [treeopen] tb_simple_dzcpu.
14 | [treeopen] tb_simple_dzcpu.uut.
15 | [sst_width] 256
16 | [signals_width] 418
17 | [sst_expanded] 1
18 | [sst_vpaned_height] 211
19 | @28
20 | tb_simple_dzcpu.uut.iClock
21 | tb_simple_dzcpu.uut.iReset
22 | @200
23 | -dzCPU
24 | @800200
25 | -TIMERS
26 | @25
27 | tb_simple_dzcpu.uut.TIMERS.rMTime[7:0]
28 | @28
29 | tb_simple_dzcpu.uut.TIMERS.iMcuWe
30 | tb_simple_dzcpu.uut.TIMERS.iBranchTaken
31 | tb_simple_dzcpu.uut.TIMERS.iInterrupt
32 | tb_simple_dzcpu.uut.TIMERS.iEof
33 | @22
34 | tb_simple_dzcpu.uut.TIMERS.iOpcode[7:0]
35 | @24
36 | tb_simple_dzcpu.uut.TIMERS.wClockIncrement[2:0]
37 | @28
38 | tb_simple_dzcpu.uut.TIMERS.rIncTimer
39 | @22
40 | [color] 2
41 | tb_simple_dzcpu.uut.TIMERS.rCurrentState[7:0]
42 | tb_simple_dzcpu.uut.TIMERS.iMcuWriteData[7:0]
43 | tb_simple_dzcpu.uut.TIMERS.iMcuRegSelect[3:0]
44 | @1000200
45 | -TIMERS
46 | @c00200
47 | -INTERRUPT
48 | @28
49 | tb_simple_dzcpu.uut.INTERRUPTS.iClock
50 | tb_simple_dzcpu.uut.INTERRUPTS.iMcuWe
51 | @22
52 | tb_simple_dzcpu.uut.INTERRUPTS.iMcuRegSelect[3:0]
53 | tb_simple_dzcpu.uut.INTERRUPTS.iMcuWriteData[7:0]
54 | tb_simple_dzcpu.uut.INTERRUPTS.oInterruptResquestPending[7:0]
55 | @1401200
56 | -INTERRUPT
57 | @800200
58 | -dzCPU
59 | @200
60 | -interrupts
61 | @c00022
62 | tb_simple_dzcpu.uut.DZCPU.iInterruptRequests[3:0]
63 | @28
64 | (0)tb_simple_dzcpu.uut.DZCPU.iInterruptRequests[3:0]
65 | (1)tb_simple_dzcpu.uut.DZCPU.iInterruptRequests[3:0]
66 | (2)tb_simple_dzcpu.uut.DZCPU.iInterruptRequests[3:0]
67 | (3)tb_simple_dzcpu.uut.DZCPU.iInterruptRequests[3:0]
68 | @1401200
69 | -group_end
70 | @28
71 | tb_simple_dzcpu.uut.DZCPU.wInterruptRoutineJumpDetected
72 | @22
73 | tb_simple_dzcpu.uut.DZCPU.wPc[15:0]
74 | tb_simple_dzcpu.uut.DZCPU.oMCUAddr[15:0]
75 | tb_simple_dzcpu.uut.DZCPU.iMCUData[7:0]
76 | tb_simple_dzcpu.uut.DZCPU.wNextFlow[9:0]
77 | @24
78 | tb_simple_dzcpu.uut.DZCPU.wuOpFlowIdx[9:0]
79 | @22
80 | tb_simple_dzcpu.uut.DZCPU.wInterruptRequestBitMaps_pre[3:0]
81 | tb_simple_dzcpu.uut.DZCPU.wInterruptRequestBitMap[3:0]
82 | tb_simple_dzcpu.uut.DZCPU.wInterruptVectorAddress[15:0]
83 | @24
84 | tb_simple_dzcpu.uut.DZCPU.wIsCBFlow
85 | @200
86 | -cpu
87 | @22
88 | tb_simple_dzcpu.uut.DZCPU.wuOpFlowIdx[9:0]
89 | @28
90 | tb_simple_dzcpu.uut.DZCPU.wTimerTick
91 | @2024
92 | ^1 /home/diego/workspace/projects/papiGB/sim/signals/dzcpu_states
93 | tb_simple_dzcpu.uut.DZCPU.rCurrentState[7:0]
94 | @22
95 | tb_simple_dzcpu.uut.DZCPU.iMCUData[7:0]
96 | tb_simple_dzcpu.uut.DZCPU.oMCUData[7:0]
97 | @28
98 | tb_simple_dzcpu.uut.DZCPU.oMCUwe
99 | @22
100 | tb_simple_dzcpu.uut.DZCPU.oMCUAddr[15:0]
101 | tb_simple_dzcpu.uut.DZCPU.wPc[15:0]
102 | @28
103 | tb_simple_dzcpu.uut.DZCPU.wJcbDetected
104 | @2024
105 | ^2 /home/diego/workspace/projects/papiGB/sim/signals/dzcpu_uop_cmd
106 | tb_simple_dzcpu.uut.DZCPU.wuCmd[4:0]
107 | @28
108 | tb_simple_dzcpu.uut.DZCPU.wIPC
109 | [color] 6
110 | tb_simple_dzcpu.uut.DZCPU.wEof
111 | [color] 3
112 | tb_simple_dzcpu.uut.DZCPU.rFlowEnable
113 | tb_simple_dzcpu.uut.DZCPU.wZ
114 | @22
115 | tb_simple_dzcpu.uut.DZCPU.wRegData[15:0]
116 | @c00028
117 | tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
118 | @28
119 | (0)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
120 | (1)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
121 | (2)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
122 | (3)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
123 | (4)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
124 | (5)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
125 | (6)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
126 | (7)tb_simple_dzcpu.uut.DZCPU.wBitMask[7:0]
127 | @1401200
128 | -group_end
129 | @22
130 | [color] 5
131 | tb_simple_dzcpu.uut.DZCPU.rUopDstRegData[15:0]
132 | @200
133 | -Registers
134 | @2024
135 | ^3 /home/diego/workspace/projects/papiGB/sim/signals/dzcpu_reg_select
136 | tb_simple_dzcpu.uut.DZCPU.wUopSrc[15:0]
137 | @28
138 | tb_simple_dzcpu.uut.DZCPU.rRegWe
139 | @22
140 | tb_simple_dzcpu.uut.DZCPU.wFlags[7:0]
141 | tb_simple_dzcpu.uut.DZCPU.wSpH[7:0]
142 | tb_simple_dzcpu.uut.DZCPU.wSpL[7:0]
143 | tb_simple_dzcpu.uut.DZCPU.wB[7:0]
144 | tb_simple_dzcpu.uut.DZCPU.wC[7:0]
145 | tb_simple_dzcpu.uut.DZCPU.wD[7:0]
146 | tb_simple_dzcpu.uut.DZCPU.wE[7:0]
147 | @c00022
148 | tb_simple_dzcpu.uut.DZCPU.wH[7:0]
149 | @28
150 | (0)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
151 | (1)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
152 | (2)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
153 | (3)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
154 | (4)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
155 | (5)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
156 | (6)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
157 | (7)tb_simple_dzcpu.uut.DZCPU.wH[7:0]
158 | @1401200
159 | -group_end
160 | @22
161 | tb_simple_dzcpu.uut.DZCPU.wL[7:0]
162 | tb_simple_dzcpu.uut.DZCPU.wA[7:0]
163 | tb_simple_dzcpu.uut.DZCPU.wX8[7:0]
164 | tb_simple_dzcpu.uut.DZCPU.wX16[15:0]
165 | @1000200
166 | -dzCPU
167 | @800200
168 | -MMU
169 | @22
170 | tb_simple_dzcpu.uut.MMU.iInterruptRequest[7:0]
171 | tb_simple_dzcpu.uut.MMU.iInterruptFlag[7:0]
172 | tb_simple_dzcpu.uut.MMU.iInterruptEnable[7:0]
173 | @2024
174 | ^4 /home/diego/workspace/projects/papiGB/sim/signals/mmu_cpu_gpu_sel
175 | tb_simple_dzcpu.uut.MMU.wCPU_GPU_Sel
176 | @28
177 | tb_simple_dzcpu.uut.MMU.iCpuReadRequest
178 | tb_simple_dzcpu.uut.MMU.iGpuReadRequest
179 | @22
180 | tb_simple_dzcpu.uut.MMU.iCpuAddr[15:0]
181 | tb_simple_dzcpu.uut.MMU.wRegMapBootStapRom[7:0]
182 | tb_simple_dzcpu.uut.MMU.wReadCartridgeBank0[7:0]
183 | tb_simple_dzcpu.uut.MMU.wCartridgeDataBank0[7:0]
184 | @28
185 | tb_simple_dzcpu.uut.MMU.wInBios
186 | @22
187 | tb_simple_dzcpu.uut.MMU.oCpuData[7:0]
188 | tb_simple_dzcpu.uut.MMU.iGpuAddr[15:0]
189 | tb_simple_dzcpu.uut.MMU.oGpuVmemReadData[7:0]
190 | tb_simple_dzcpu.uut.MMU.wVmemReadAddr[15:0]
191 | tb_simple_dzcpu.uut.MMU.wOAMData[7:0]
192 | tb_simple_dzcpu.uut.MMU.wReadVmem[7:0]
193 | tb_simple_dzcpu.uut.MMU.wAddr[15:0]
194 | @28
195 | tb_simple_dzcpu.uut.MMU.wWeVRam
196 | tb_simple_dzcpu.uut.MMU.wWeZeroPage
197 | tb_simple_dzcpu.uut.MMU.wInBios
198 | tb_simple_dzcpu.uut.MMU.wInCartridgeBank0
199 | @1000200
200 | -MMU
201 | @c00200
202 | -GPU
203 | @28
204 | tb_simple_dzcpu.uut.GPU.iClock
205 | tb_simple_dzcpu.uut.GPU.iReset
206 | tb_simple_dzcpu.uut.GPU.wZ
207 | tb_simple_dzcpu.uut.GPU.wGpuActive
208 | @24
209 | tb_simple_dzcpu.uut.GPU.wIp[7:0]
210 | @22
211 | tb_simple_dzcpu.uut.GPU.wOp0[15:0]
212 | tb_simple_dzcpu.uut.GPU.wOp1[15:0]
213 | @800200
214 | -tb_simple_dzcpu.uut.GPU.wUop
215 | @1401200
216 | -group_end
217 | -group_end
218 | [pattern_trace] 1
219 | [pattern_trace] 0
220 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerChannel3.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 3. Squate waves with variable timmer, configurable frequency and envelope functions.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 |
25 | module SoundCtrlChannel3 //parameters
26 | (
27 | input wire iClock, //CPU CLOCK, 4194304Hz
28 | input wire iReset,
29 | input wire iOsc256, //OSC1 clock 256Hz
30 | input wire iOsc262k, //OSC2 clock 131072Hz
31 |
32 | input wire [7:0] iNR30,
33 | input wire [7:0] iNR31,
34 | input wire [7:0] iNR32,
35 | input wire [7:0] iNR33,
36 | input wire [7:0] iNR34,
37 |
38 | output reg [4:0] oOut,
39 | output wire oOnFlag
40 | );
41 |
42 |
43 | reg [8:0] rLength;
44 | reg [19:0] rLengthCounter;
45 | reg rTimedMode;
46 | reg rLengthComplete; // Channe disable.
47 |
48 | reg rTone;
49 | reg [10:0] rSoundFrequency;
50 | reg [10:0] rSoundFrequencyCounter;
51 |
52 | reg rChannelEnable;
53 | reg [1:0] rOutLevel;
54 | reg [3:0] rStep;
55 | reg [3:0] rStepScaled;
56 |
57 | wire [4:0] up_value, down_value;
58 |
59 | reg [4:0] rWaveRamIndex;
60 | reg rWaveRamHnL;
61 |
62 | reg [7:0] iWaveRam [0:31]; // Wave samples Ram 64 samples of 4 bits
63 |
64 | // triangular waveform
65 | ///*
66 | always @ (posedge iClock) begin
67 | if (iReset) begin
68 | iWaveRam[0]=8'h01;
69 | iWaveRam[1]=8'h23;
70 | iWaveRam[2]=8'h45;
71 | iWaveRam[3]=8'h67;
72 | iWaveRam[4]=8'h89;
73 | iWaveRam[5]=8'hAB;
74 | iWaveRam[6]=8'hCD;
75 | iWaveRam[7]=8'hEF;
76 | iWaveRam[8]=8'hED;
77 | iWaveRam[9]=8'hCB;
78 | iWaveRam[10]=8'hA9;
79 | iWaveRam[11]=8'h87;
80 | iWaveRam[12]=8'h65;
81 | iWaveRam[13]=8'h43;
82 | iWaveRam[14]=8'h21;
83 | iWaveRam[15]=8'h00;
84 | iWaveRam[16]=8'h01;
85 | iWaveRam[17]=8'h23;
86 | iWaveRam[18]=8'h45;
87 | iWaveRam[19]=8'h67;
88 | iWaveRam[20]=8'h89;
89 | iWaveRam[21]=8'hAB;
90 | iWaveRam[22]=8'hCD;
91 | iWaveRam[23]=8'hEF;
92 | iWaveRam[24]=8'hED;
93 | iWaveRam[25]=8'hCB;
94 | iWaveRam[26]=8'hA9;
95 | iWaveRam[27]=8'h87;
96 | iWaveRam[28]=8'h65;
97 | iWaveRam[29]=8'h43;
98 | iWaveRam[30]=8'h21;
99 | iWaveRam[31]=8'h00;
100 | end
101 | end
102 | //*/
103 |
104 | // sawtooth waveform
105 | /*
106 | always @ (posedge iClock) begin
107 | if (iReset) begin
108 | iWaveRam[0]=8'hFE;
109 | iWaveRam[1]=8'hDC;
110 | iWaveRam[2]=8'hBA;
111 | iWaveRam[3]=8'h98;
112 | iWaveRam[4]=8'h76;
113 | iWaveRam[5]=8'h54;
114 | iWaveRam[6]=8'h32;
115 | iWaveRam[7]=8'h10;
116 | iWaveRam[8]=8'hFE;
117 | iWaveRam[9]=8'hDC;
118 | iWaveRam[10]=8'hBA;
119 | iWaveRam[11]=8'h98;
120 | iWaveRam[12]=8'h76;
121 | iWaveRam[13]=8'h54;
122 | iWaveRam[14]=8'h32;
123 | iWaveRam[15]=8'h10;
124 | iWaveRam[16]=8'hFE;
125 | iWaveRam[17]=8'hDC;
126 | iWaveRam[18]=8'hBA;
127 | iWaveRam[19]=8'h98;
128 | iWaveRam[20]=8'h76;
129 | iWaveRam[21]=8'h54;
130 | iWaveRam[22]=8'h32;
131 | iWaveRam[23]=8'h10;
132 | iWaveRam[24]=8'hFE;
133 | iWaveRam[25]=8'hDC;
134 | iWaveRam[26]=8'hBA;
135 | iWaveRam[27]=8'h98;
136 | iWaveRam[28]=8'h76;
137 | iWaveRam[29]=8'h54;
138 | iWaveRam[30]=8'h32;
139 | iWaveRam[31]=8'h10;
140 | end
141 | end
142 | */
143 |
144 | // register load
145 | always @(posedge iClock) begin
146 | if (iReset || iNR34[7]) begin // Register reload and counters restart.
147 |
148 | rChannelEnable <= iNR30[7];
149 |
150 | rLength <= iNR31[7:0];
151 | rLengthCounter <= 256 - iNR31[7:0]; // Decrements to zero then load rLength.
152 | rLengthComplete <= 0; // Disables channel when is asserted.
153 |
154 | rTimedMode <= iNR34[6];
155 |
156 | rOutLevel <= iNR32[6:5];
157 | rStep <= iWaveRam[0][3:0];
158 | rWaveRamIndex <= 0;
159 | rWaveRamHnL <= 1; // Indicates if low or high part have been read.
160 |
161 | rTone <= 0;
162 | rSoundFrequency[10:0] <= 2048-{iNR34[2:0],iNR33[7:0]};
163 | rSoundFrequencyCounter <= 2048-{iNR34[2:0],iNR33[7:0]};
164 |
165 | end
166 | end
167 |
168 | // wave ram reader
169 | always @ (posedge rTone) begin
170 | if (rChannelEnable) begin
171 | if (~rWaveRamHnL) begin
172 | rStep <= iWaveRam[rWaveRamIndex][7:4];
173 | rWaveRamHnL <= ~rWaveRamHnL;
174 | end
175 | else begin
176 | rStep <= iWaveRam[rWaveRamIndex][3:0];
177 | rWaveRamHnL <= ~rWaveRamHnL;
178 |
179 | if (rWaveRamIndex == 5'd31) begin
180 | rWaveRamIndex <= rWaveRamIndex+1;
181 | rLengthComplete <= rTimedMode;
182 | end
183 | else begin
184 | rWaveRamIndex <= rWaveRamIndex+1;
185 | end
186 | end
187 | end
188 | else begin
189 | rStep <= 4'b0;
190 | end
191 | end
192 |
193 | // tone gen: generates the frecuency of the output.
194 | always @(posedge iOsc262k) begin
195 | if (rSoundFrequencyCounter ==0) begin
196 | rSoundFrequencyCounter <= rSoundFrequency;
197 | rTone <= ~rTone;
198 | end
199 | else begin
200 | rSoundFrequencyCounter <= rSoundFrequencyCounter-1;
201 | end
202 | end
203 |
204 |
205 | // timmer: enable or disable channel output.
206 | always @(posedge iOsc256) begin
207 | if (rLengthCounter == 0) begin
208 | rLengthCounter <= 256-rLength;
209 | rLengthComplete <= rTimedMode; // Disable channel only if timmer is enabled.
210 | end
211 | else begin
212 | rLengthCounter <= rLengthCounter-1;
213 | end
214 | end
215 |
216 | //re-map mux
217 | assign up_value = 5'd15 + rStepScaled;
218 | assign down_value = 5'd15 - rStepScaled;
219 |
220 | always @(posedge iClock) begin
221 | if (rLengthComplete) begin
222 | oOut[4:0] <= 5'd15;
223 | end
224 | else begin
225 | if (rTone) begin
226 | oOut[4:0] <= up_value[4:0];
227 | end
228 | else begin
229 | oOut[4:0] <= down_value[4:0];
230 | end
231 | end
232 | end
233 |
234 |
235 | // output level manager
236 | always @ (rOutLevel or rStep) begin
237 | case (rOutLevel[1:0])
238 | 2'd0: rStepScaled = 0;
239 | 2'd1: rStepScaled = rStep;
240 | 2'd2: rStepScaled = rStep >> 1;
241 | 2'd3: rStepScaled = rStep >> 2;
242 | endcase
243 | end
244 |
245 | assign oOnFlag = rLengthComplete;
246 |
247 | endmodule
248 |
--------------------------------------------------------------------------------
/rtl/pGB.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | `include "aDefinitions.v"
3 |
4 | ////////////////////////////////////////////////////////////////////////////////////
5 | //
6 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
7 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, write to the Free Software
21 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////////
24 | module pGB
25 | (
26 |
27 | input wire iClock,
28 |
29 | `ifdef VGA_ENABLED
30 | output wire [3:0] oVgaRed,
31 | output wire [3:0] oVgaGreen,
32 | output wire [3:0] oVgaBlue,
33 | output wire oVgaHsync,
34 | output wire oVgaVsync,
35 | `endif
36 |
37 | //IO input ports
38 | //ASCII IMAGE BUTTON MATRIX
39 | input wire [5:0] iButtonRegister, //Pressed button
40 |
41 |
42 | `ifndef XILINX_IP
43 | output wire oFrameBufferWe,
44 | output wire [15:0] oFrameBufferData,
45 | output wire [15:0] oFrameBufferAddr,
46 |
47 | `endif
48 |
49 | input wire iReset
50 | );
51 |
52 | wire [15:0] wdZCPU_2_MMU_Addr, wGPU_2_MCU_Addr;
53 | wire [7:0] wdZCPU_2_MMU_WriteData, wMMU_ReadData;
54 | wire wdZCPU_2_MMU_We, wdZCPU_2_MMU_ReadRequest;
55 |
56 | wire[7:0] wGPU_2_MCU_LCDC;
57 | wire[7:0] wGPU_2_MCU_STAT;
58 | wire[7:0] wGPU_2_MCU_SCY;
59 | wire[7:0] wGPU_2_MCU_SCX;
60 | wire[7:0] wGPU_2_MCU_LY;
61 | wire[7:0] wGPU_2_MCU_LYC;
62 | wire[7:0] wGPU_2_MCU_DMA;
63 | wire[7:0] wGPU_2_MCU_BGP;
64 | wire[7:0] wGPU_2_MCU_OBP0;
65 | wire[7:0] wGPU_2_MCU_OBP1;
66 | wire[7:0] wGPU_2_MCU_WY;
67 | wire[7:0] wGPU_2_MCU_WX, wMMU_RegData, wMMU_2_GPU_VmemReadData;
68 | wire[7:0] wButtonRegister;
69 | wire[7:0] wCurrentZ80Insn;
70 | wire[15:0] wGpuAddr;
71 | wire [2:0] wMMU_RegWe;
72 | wire[3:0] wMMU_RegSelect, wMCU_2_TIMER_RegSelect;
73 | wire wGPU_2_MCU_ReadRequest, wMCU_2_TIMER_We;
74 | wire wIOInterruptTrigger, wdZCPU_Eof, wdZCPU_BranchTaken, wDZCPU_2_Timer_IntDetected;
75 | wire [7:0] wInterruptRequest,wInt_2_MMU_InterruptFlag, wInt_2_MMU_IntEnable;
76 | wire wInterrupt0x50;
77 |
78 | dzcpu DZCPU
79 | (
80 | .iClock( iClock ),
81 | .iReset( iReset ),
82 | .iMCUData( wMMU_ReadData ),
83 | .oMCUAddr( wdZCPU_2_MMU_Addr ),
84 | .oMCUwe( wdZCPU_2_MMU_We ),
85 | .oMCUData( wdZCPU_2_MMU_WriteData ),
86 | .oMcuReadRequest( wdZCPU_2_MMU_ReadRequest ),
87 | .oCurrentZ80Insn( wCurrentZ80Insn ),
88 | .oEof( wdZCPU_Eof ),
89 | .iInterruptRequests( wInterruptRequest ),
90 | .oInterruptJump( wDZCPU_2_Timer_IntDetected ),
91 | .oBranchTaken( wdZCPU_BranchTaken ),
92 | .iJoypad(wButtonRegister[5:0])
93 | );
94 |
95 |
96 | interrupt_controller INTERRUPTS
97 | (
98 | .iClock(iClock ),
99 | .iReset( iReset ),
100 |
101 | .iMcuWe( wMMU_RegWe[2] ),
102 | .iMcuRegSelect(wMMU_RegSelect ), //control register select comes from cpu
103 | .iMcuWriteData( wMMU_RegData ), //what does the cpu want to write
104 |
105 | .oInterruptEnableRegister( wInt_2_MMU_IntEnable ),
106 | .oInterruptFlag( wInt_2_MMU_InterruptFlag),
107 |
108 |
109 | .iInterruptRequest( {5'b0, wInterrupt0x50, 2'b0} ),
110 | .oInterruptResquestPending( wInterruptRequest )
111 | );
112 |
113 | timers TIMERS
114 | (
115 | .iClock( iClock ),
116 | .iReset( iReset ),
117 | .iOpcode( wCurrentZ80Insn ),
118 | .iBranchTaken( wdZCPU_BranchTaken ),
119 | .iEof( wdZCPU_Eof ),
120 | .iMcuWe( wMMU_RegWe[1] ),
121 | .iMcuRegSelect( wMMU_RegSelect ),
122 | .iInterrupt( wDZCPU_2_Timer_IntDetected ),
123 | .iMcuWriteData( wMMU_RegData ),
124 |
125 | //output wire oInterrupt0x50
126 | .oInterrupt0x50( wInterrupt0x50 )
127 |
128 | );
129 |
130 | assign wButtonRegister[7:6] = 2'b0;
131 | //IO unit is in charge of marshalling the GameBoy push butons
132 | io IO
133 | (
134 | .Clock( iClock ),
135 | .Reset( iReset ),
136 | .iP( iButtonRegister ),
137 | .oP( wButtonRegister[5:0] ),
138 | .oIE( wIOInterruptTrigger )
139 |
140 | );
141 |
142 |
143 | mmu MMU
144 | (
145 | .iClock( iClock ),
146 | .iReset( iReset ),
147 |
148 | //CPU
149 | .iCpuReadRequest( wdZCPU_2_MMU_ReadRequest ),
150 | .iGpuReadRequest( wGPU_2_MCU_ReadRequest ),
151 | .iCpuAddr( wdZCPU_2_MMU_Addr ),
152 | .iCpuWe( wdZCPU_2_MMU_We ),
153 | .iCpuData( wdZCPU_2_MMU_WriteData ),
154 | .oCpuData( wMMU_ReadData ),
155 |
156 | //GPU
157 | .oGpuVmemReadData( wMMU_2_GPU_VmemReadData ),
158 | .iGpuAddr( wGPU_2_MCU_Addr ),
159 | .oRegData( wMMU_RegData ),
160 | .oRegSelect( wMMU_RegSelect ),
161 | .oRegWe( wMMU_RegWe ),
162 |
163 | .iGPU_LCDC( wGPU_2_MCU_LCDC ),
164 | .iGPU_STAT( wGPU_2_MCU_STAT ),
165 | .iGPU_SCY( wGPU_2_MCU_SCY ),
166 | .iGPU_SCX( wGPU_2_MCU_SCX ),
167 | .iGPU_LY( wGPU_2_MCU_LY ),
168 | .iGPU_LYC( wGPU_2_MCU_LYC ),
169 | .iGPU_DMA( wGPU_2_MCU_DMA ),
170 | .iGPU_BGP( wGPU_2_MCU_BGP ),
171 | .iGPU_OBP0( wGPU_2_MCU_OBP0 ),
172 | .iGPU_OBP1( wGPU_2_MCU_OBP1 ),
173 | .iGPU_WY( wGPU_2_MCU_WY ),
174 | .iGPU_WX( wGPU_2_MCU_WX ),
175 |
176 | .iInterruptEnable( wInt_2_MMU_IntEnable ),
177 | .iInterruptFlag( wInt_2_MMU_InterruptFlag ),
178 |
179 | //IO
180 | .iButtonRegister( wButtonRegister )
181 | );
182 |
183 |
184 | `ifdef VGA_ENABLED
185 |
186 | wire [15:0] wFramBufferWriteData, wVgaFBReadData, wVgaFBReadData_Pre, wFrameBufferReadAddress, wFramBufferWriteAddress;
187 | wire [15:0] wVgaRow, wVgaCol;
188 | wire [3:0] wVgaR, wVgaG, wVgaB;
189 | wire [9:0] wVgaFBReadAddr;
190 | wire [1:0] wVgaColor2Bits;
191 | wire wFramBufferWe;
192 |
193 | RAM_SINGLE_READ_PORT # ( .DATA_WIDTH(16), .ADDR_WIDTH(10), .MEM_SIZE(8192) ) FBUFFER
194 | (
195 | .Clock( iClock ), //TODO: Should we use graphic clock here?
196 | .iWriteEnable( wFramBufferWe ),
197 | //.iReadAddress0( {3'b0,wFrameBufferReadAddress[15:3]} ), //Divide by 8
198 | .iReadAddress0( wFrameBufferReadAddress ), //Divide by 8
199 | .iWriteAddress( wFramBufferWriteAddress ),
200 | .iDataIn( wFramBufferWriteData ),
201 | .oDataOut0( wVgaFBReadData_Pre )
202 |
203 | );
204 |
205 | assign wFrameBufferReadAddress = (wVgaRow << 5) + (wVgaCol >> 3);
206 |
207 | MUXFULLPARALELL_3SEL_GENERIC # (2) MUX_COLOR (
208 | .Sel( wVgaCol[2:0] ),
209 | .I7( wVgaFBReadData_Pre[1:0]),
210 | .I6( wVgaFBReadData_Pre[3:2]),
211 | .I5( wVgaFBReadData_Pre[5:4]),
212 | .I4( wVgaFBReadData_Pre[7:6]) ,
213 | .I3( wVgaFBReadData_Pre[9:8]),
214 | .I2( wVgaFBReadData_Pre[11:10]),
215 | .I1( wVgaFBReadData_Pre[13:12]),
216 | .I0( wVgaFBReadData_Pre[15:14]) ,
217 | .O( wVgaColor2Bits )
218 | );
219 |
220 | wire [3:0] wRed,wGreen,wBlue;
221 | MUXFULLPARALELL_2SEL_GENERIC # (12) MUX_COLOR_OUT (
222 | .Sel( wVgaColor2Bits ),
223 | .I0( {4'b0000, 4'b0000, 4'b0000 } ),
224 | .I1( {4'b1111, 4'b0000, 4'b0000 } ),
225 | .I2( {4'b0000, 4'b1111, 4'b0000 } ),
226 | .I3( {4'b0000, 4'b0000, 4'b1111 }) ,
227 | .O( {wRed,wGreen,wBlue} )
228 | );
229 |
230 |
231 |
232 | assign oVgaRed = ( wVgaRow >= 16'd255 || wVgaCol >= 255 ) ? 4'b0111 : wRed;
233 | assign oVgaGreen = ( wVgaRow >= 16'd255 || wVgaCol >= 255 ) ? 4'b0111 : wGreen;
234 | assign oVgaBlue = ( wVgaRow >= 16'd255 || wVgaCol >= 255 ) ? 4'b0111 : wBlue;
235 |
236 |
237 | VgaController VGA
238 | (
239 | .Clock(iClock),
240 | .Reset(iReset),
241 | .oVgaVsync( oVgaVsync ),
242 | .oVgaHsync( oVgaHsync ),
243 | /*.oVgaRed( oVgaRed ),
244 | .oVgaGreen( oVgaGreen ),
245 | .oVgaBlue( oVgaBlue ),*/
246 | .oRow( wVgaRow ),
247 | .oCol( wVgaCol )
248 |
249 | );
250 |
251 | `ifndef XILINX_IP
252 | assign oFrameBufferAddr = wFramBufferWriteAddress;
253 | assign oFrameBufferData = wFramBufferWriteData;
254 | assign oFrameBufferWe = wFramBufferWe;
255 | `endif
256 |
257 | `endif
258 |
259 | gpu GPU
260 | (
261 | .iClock( iClock ),
262 | .iReset( iReset ),
263 | `ifndef VGA_ENABLED
264 | .oFramBufferWe( oFrameBufferWe ),
265 | .oFramBufferData( oFrameBufferData ),
266 | .oFramBufferAddr( oFrameBufferAddr ),
267 | `else
268 | .oFramBufferWe( wFramBufferWe ),
269 | .oFramBufferData( wFramBufferWriteData ),
270 | .oFramBufferAddr( wFramBufferWriteAddress ),
271 |
272 | `endif
273 | .oMcuAddr( wGPU_2_MCU_Addr ),
274 | .oMcuReadRequest( wGPU_2_MCU_ReadRequest ),
275 | .iMcuRegSelect( wMMU_RegSelect),
276 | .iMcuWriteData( wMMU_RegData ),
277 | .iMcuReadData( wMMU_2_GPU_VmemReadData ),
278 | .iMcuWe( wMMU_RegWe[0] ),
279 | .oSTAT( wGPU_2_MCU_STAT ),
280 | .oLCDC( wGPU_2_MCU_LCDC ),
281 | .oSCY( wGPU_2_MCU_SCY ),
282 | .oSCX( wGPU_2_MCU_SCX ),
283 | .oLY( wGPU_2_MCU_LY ),
284 | .oLYC( wGPU_2_MCU_LYC ),
285 | .oDMA( wGPU_2_MCU_DMA ),
286 | .oBGP( wGPU_2_MCU_BGP ),
287 | .oOBP0( wGPU_2_MCU_OBP0 ),
288 | .oOBP1( wGPU_2_MCU_OBP1 ),
289 | .oWY( wGPU_2_MCU_WY ),
290 | .oWX( wGPU_2_MCU_WX )
291 | );
292 |
293 | endmodule
294 |
--------------------------------------------------------------------------------
/rtl/bios.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | ////////////////////////////////////////////////////////////////////////////////////
3 | //
4 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
5 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
6 | //
7 | // This program is free software; you can redistribute it and/or
8 | // modify it under the terms of the GNU General Public License
9 | // as published by the Free Software Foundation; either version 2
10 | // of the License, or (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with this program; if not, write to the Free Software
19 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 | //
21 | ////////////////////////////////////////////////////////////////////////////////////
22 |
23 | module bios
24 | (
25 | input wire iClock,
26 | input wire [7:0] iAddr,
27 | output reg [7:0] oData
28 | );
29 |
30 |
31 | always @ ( posedge iClock )
32 | begin
33 | case ( iAddr )
34 | 8'd0: oData = 8'h31;
35 | 8'd1: oData = 8'hFE;
36 | 8'd2 : oData = 8'hFF;
37 | 8'd3 : oData = 8'hAF;
38 | 8'd4 : oData = 8'h21;
39 | 8'd5 : oData = 8'hFF;
40 | 8'd6 : oData = 8'h9F;
41 | 8'd7 : oData = 8'h32;
42 | 8'd8 : oData = 8'hCB;
43 | 8'd9 : oData = 8'h7C;
44 | 8'd10 : oData = 8'h20;
45 | 8'd11 : oData = 8'hFB;
46 | 8'd12 : oData = 8'h21;
47 | 8'd13 : oData = 8'h26;
48 | 8'd14 : oData = 8'hFF;
49 | 8'd15 : oData = 8'h0E;
50 | 8'd16 : oData = 8'h11;
51 | 8'd17 : oData = 8'h3E;
52 | 8'd18 : oData = 8'h80;
53 | 8'd19 : oData = 8'h32;
54 | 8'd20 : oData = 8'hE2;
55 | 8'd21 : oData = 8'h0C;
56 | 8'd22 : oData = 8'h3E;
57 | 8'd23 : oData = 8'hF3;
58 | 8'd24 : oData = 8'hE2;
59 | 8'd25 : oData = 8'h32;
60 | 8'd26 : oData = 8'h3E;
61 | 8'd27 : oData = 8'h77;
62 | 8'd28 : oData = 8'h77;
63 | 8'd29 : oData = 8'h3E;
64 | 8'd30 : oData = 8'hFC;
65 | 8'd31 : oData = 8'hE0;
66 | 8'd32 : oData = 8'h47;
67 | 8'd33 : oData = 8'h11;
68 | 8'd34 : oData = 8'h04;
69 | 8'd35 : oData = 8'h01;
70 | 8'd36 : oData = 8'h21;
71 | 8'd37 : oData = 8'h10;
72 | 8'd38 : oData = 8'h80;
73 | 8'd39 : oData = 8'h1A;
74 | 8'd40 : oData = 8'hCD;
75 | 8'd41 : oData = 8'h95;
76 | 8'd42 : oData = 8'h00;
77 | 8'd43 : oData = 8'hCD;
78 | 8'd44 : oData = 8'h96;
79 | 8'd45 : oData = 8'h00;
80 | 8'd46 : oData = 8'h13;
81 | 8'd47 : oData = 8'h7B;
82 | 8'd48 : oData = 8'hFE;
83 | 8'd49 : oData = 8'h34;
84 | 8'd50 : oData = 8'h20;
85 | 8'd51 : oData = 8'hF3;
86 | 8'd52 : oData = 8'h11;
87 | 8'd53 : oData = 8'hD8;
88 | 8'd54 : oData = 8'h00;
89 | 8'd55 : oData = 8'h06;
90 | 8'd56 : oData = 8'h08;
91 | 8'd57 : oData = 8'h1A;
92 | 8'd58 : oData = 8'h13;
93 | 8'd59 : oData = 8'h22;
94 | 8'd60 : oData = 8'h23;
95 | 8'd61 : oData = 8'h05;
96 | 8'd62 : oData = 8'h20;
97 | 8'd63 : oData = 8'hF9;
98 | 8'd64 : oData = 8'h3E;
99 | 8'd65 : oData = 8'h19;
100 | 8'd66 : oData = 8'hEA;
101 | 8'd67 : oData = 8'h10;
102 | 8'd68 : oData = 8'h99;
103 | 8'd69 : oData = 8'h21;
104 | 8'd70 : oData = 8'h2F;
105 | 8'd71 : oData = 8'h99;
106 | 8'd72 : oData = 8'h0E;
107 | 8'd73 : oData = 8'h0C;
108 | 8'd74 : oData = 8'h3D;
109 | 8'd75 : oData = 8'h28;
110 | 8'd76 : oData = 8'h08;
111 | 8'd77 : oData = 8'h32;
112 | 8'd78 : oData = 8'h0D;
113 | 8'd79 : oData = 8'h20;
114 | 8'd80 : oData = 8'hF9;
115 | 8'd81 : oData = 8'h2E;
116 | 8'd82 : oData = 8'h0F;
117 | 8'd83 : oData = 8'h18;
118 | 8'd84 : oData = 8'hF3;
119 | 8'd85 : oData = 8'h67;
120 | 8'd86 : oData = 8'h3E;
121 | 8'd87 : oData = 8'h64;
122 | 8'd88 : oData = 8'h57;
123 | 8'd89 : oData = 8'hE0;
124 | 8'd90 : oData = 8'h42;
125 | 8'd91 : oData = 8'h3E;
126 | 8'd92 : oData = 8'h91;
127 | 8'd93 : oData = 8'hE0;
128 | 8'd94 : oData = 8'h40;
129 | 8'd95 : oData = 8'h04;
130 | 8'd96 : oData = 8'h1E;
131 | 8'd97 : oData = 8'h02;
132 | 8'd98 : oData = 8'h0E;
133 | 8'd99 : oData = 8'h0C;
134 | 8'd100 : oData = 8'hF0;
135 | 8'd101 : oData = 8'h44;
136 | 8'd102 : oData = 8'hFE;
137 | 8'd103 : oData = 8'h90;
138 | 8'd104 : oData = 8'h20;
139 | 8'd105 : oData = 8'hFA;
140 | 8'd106 : oData = 8'h0D;
141 | 8'd107 : oData = 8'h20;
142 | 8'd108 : oData = 8'hF7;
143 | 8'd109 : oData = 8'h1D;
144 | 8'd110 : oData = 8'h20;
145 | 8'd111 : oData = 8'hF2;
146 | 8'd112 : oData = 8'h0E;
147 | 8'd113 : oData = 8'h13;
148 | 8'd114 : oData = 8'h24;
149 | 8'd115 : oData = 8'h7C;
150 | 8'd116 : oData = 8'h1E;
151 | 8'd117 : oData = 8'h83;
152 | 8'd118 : oData = 8'hFE;
153 | 8'd119 : oData = 8'h62;
154 | 8'd120 : oData = 8'h28;
155 | 8'd121 : oData = 8'h06;
156 | 8'd122 : oData = 8'h1E;
157 | 8'd123 : oData = 8'hC1;
158 | 8'd124 : oData = 8'hFE;
159 | 8'd125 : oData = 8'h64;
160 | 8'd126 : oData = 8'h20;
161 | 8'd127 : oData = 8'h06;
162 | 8'd128 : oData = 8'h7B;
163 | 8'd129 : oData = 8'hE2;
164 | 8'd130 : oData = 8'h0C;
165 | 8'd131 : oData = 8'h3E;
166 | 8'd132 : oData = 8'h87;
167 | 8'd133 : oData = 8'hF2;
168 | 8'd134 : oData = 8'hF0;
169 | 8'd135 : oData = 8'h42;
170 | 8'd136 : oData = 8'h90;
171 | 8'd137 : oData = 8'hE0;
172 | 8'd138 : oData = 8'h42;
173 | 8'd139 : oData = 8'h15;
174 | 8'd140 : oData = 8'h20;
175 | 8'd141 : oData = 8'hD2;
176 | 8'd142 : oData = 8'h05;
177 | 8'd143 : oData = 8'h20;
178 | 8'd144 : oData = 8'h4F;
179 | 8'd145 : oData = 8'h16;
180 | 8'd146 : oData = 8'h20;
181 | 8'd147 : oData = 8'h18;
182 | 8'd148 : oData = 8'hCB;
183 | 8'd149 : oData = 8'h4F;
184 | 8'd150 : oData = 8'h06;
185 | 8'd151 : oData = 8'h04;
186 | 8'd152 : oData = 8'hC5;
187 | 8'd153 : oData = 8'hCB;
188 | 8'd154 : oData = 8'h11;
189 | 8'd155 : oData = 8'h17;
190 | 8'd156 : oData = 8'hC1;
191 | 8'd157 : oData = 8'hCB;
192 | 8'd158 : oData = 8'h11;
193 | 8'd159 : oData = 8'h17;
194 | 8'd160 : oData = 8'h05;
195 | 8'd161 : oData = 8'h20;
196 | 8'd162 : oData = 8'hF5;
197 | 8'd163 : oData = 8'h22;
198 | 8'd164 : oData = 8'h23;
199 | 8'd165 : oData = 8'h22;
200 | 8'd166 : oData = 8'h23;
201 | 8'd167 : oData = 8'hC9;
202 | 8'd168 : oData = 8'hCE;
203 | 8'd169 : oData = 8'hED;
204 | 8'd170 : oData = 8'h66;
205 | 8'd171 : oData = 8'h66;
206 | 8'd172 : oData = 8'hCC;
207 | 8'd173 : oData = 8'h0D;
208 | 8'd174 : oData = 8'h00;
209 | 8'd175 : oData = 8'h0B;
210 | 8'd176 : oData = 8'h03;
211 | 8'd177 : oData = 8'h73;
212 | 8'd178 : oData = 8'h00;
213 | 8'd179 : oData = 8'h83;
214 | 8'd180 : oData = 8'h00;
215 | 8'd181 : oData = 8'h0C;
216 | 8'd182 : oData = 8'h00;
217 | 8'd183 : oData = 8'h0D;
218 | 8'd184 : oData = 8'h00;
219 | 8'd185 : oData = 8'h08;
220 | 8'd186 : oData = 8'h11;
221 | 8'd187 : oData = 8'h1F;
222 | 8'd188 : oData = 8'h88;
223 | 8'd189 : oData = 8'h89;
224 | 8'd190 : oData = 8'h00;
225 | 8'd191 : oData = 8'h0E;
226 | 8'd192 : oData = 8'hDC;
227 | 8'd193 : oData = 8'hCC;
228 | 8'd194 : oData = 8'h6E;
229 | 8'd195 : oData = 8'hE6;
230 | 8'd196 : oData = 8'hDD;
231 | 8'd197 : oData = 8'hDD;
232 | 8'd198 : oData = 8'hD9;
233 | 8'd199 : oData = 8'h99;
234 | 8'd200 : oData = 8'hBB;
235 | 8'd201 : oData = 8'hBB;
236 | 8'd202 : oData = 8'h67;
237 | 8'd203 : oData = 8'h63;
238 | 8'd204 : oData = 8'h6E;
239 | 8'd205 : oData = 8'h0E;
240 | 8'd206 : oData = 8'hEC;
241 | 8'd207 : oData = 8'hCC;
242 | 8'd208 : oData = 8'hDD;
243 | 8'd209 : oData = 8'hDC;
244 | 8'd210 : oData = 8'h99;
245 | 8'd211 : oData = 8'h9F;
246 | 8'd212 : oData = 8'hBB;
247 | 8'd213 : oData = 8'hB9;
248 | 8'd214 : oData = 8'h33;
249 | 8'd215 : oData = 8'h3E;
250 | 8'd216 : oData = 8'h3c;
251 | 8'd217 : oData = 8'h42;
252 | 8'd218 : oData = 8'hB9;
253 | 8'd219 : oData = 8'hA5;
254 | 8'd220 : oData = 8'hB9;
255 | 8'd221 : oData = 8'hA5;
256 | 8'd222 : oData = 8'h42;
257 | 8'd223 : oData = 8'h3C;
258 | 8'd224 : oData = 8'h21;
259 | 8'd225 : oData = 8'h04;
260 | 8'd226 : oData = 8'h01;
261 | 8'd227 : oData = 8'h11;
262 | 8'd228 : oData = 8'hA8;
263 | 8'd229 : oData = 8'h00;
264 | 8'd230 : oData = 8'h1A;
265 | 8'd231 : oData = 8'h13;
266 | 8'd232 : oData = 8'hBE;
267 | 8'd233 : oData = 8'h20;
268 | 8'd234 : oData = 8'hFE;
269 | 8'd235 : oData = 8'h23;
270 | 8'd236 : oData = 8'h7D;
271 | 8'd237 : oData = 8'hFE;
272 | 8'd238 : oData = 8'h34;
273 | 8'd239 : oData = 8'h20;
274 | 8'd240 : oData = 8'hF5;
275 | 8'd241 : oData = 8'h06;
276 | 8'd242 : oData = 8'h19;
277 | 8'd243 : oData = 8'h78;
278 | 8'd244 : oData = 8'h86;
279 | 8'd245 : oData = 8'h23;
280 | 8'd246 : oData = 8'h05;
281 | 8'd247 : oData = 8'h20;
282 | 8'd248 : oData = 8'hFB;
283 | 8'd249 : oData = 8'h86;
284 | 8'd250 : oData = 8'h20;
285 | 8'd251 : oData = 8'hFE;
286 | 8'd252 : oData = 8'h3E;
287 | 8'd253 : oData = 8'h01;
288 | 8'd254 : oData = 8'hE0;
289 | 8'd255 : oData = 8'h50;
290 | default:
291 | oData = 8'h0;
292 | endcase
293 | end
294 |
295 |
296 | endmodule
297 |
--------------------------------------------------------------------------------
/rtl/sound_controller_modules/SoundControllerChannel4.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
4 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
5 | //
6 | // This program is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU General Public License
8 | // as published by the Free Software Foundation; either version 2
9 | // of the License, or (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program; if not, write to the Free Software
18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////////
21 | // Sound module, channel 4. White noise generation module using LFSR.
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 |
25 | module SoundCtrlChannel4 //parameters
26 | (
27 | input wire iClock, //CPU CLOCK, 4194304Hz
28 | input wire iReset,
29 | input wire iOsc64, //OSC1 clock 64Hz
30 | input wire iOsc256, //OSC1 clock 256Hz
31 |
32 | input wire [7:0] iNR41,
33 | input wire [7:0] iNR42,
34 | input wire [7:0] iNR43,
35 | input wire [7:0] iNR44,
36 |
37 | output reg [4:0] oOut,
38 | output wire oOnFlag
39 | );
40 |
41 |
42 | reg [5:0] rLength;
43 | reg [19:0] rLengthCounter;
44 | reg rLengthComplete; // Channe disable.
45 |
46 | wire rTone;
47 |
48 | reg [3:0] rStep;
49 | reg [18:0] rStepTime;
50 | reg [18:0] rStepCounter;
51 | reg [3:0] rInitialValue;
52 | reg rEvelopeMode;
53 |
54 | reg [2:0] rDivRatioFreq;
55 | reg [3:0] rShiftClockFreq;
56 |
57 | reg rPolCoutSteps;
58 |
59 | reg rClkDiv;
60 | reg [5:0] rDivRatioCounter;
61 |
62 | reg rCountPre;
63 | reg [14:0] rShiftCounter;
64 |
65 | reg rTimedMode;
66 |
67 | wire [4:0] up_value, down_value;
68 |
69 | // register load
70 | always @(posedge iClock) begin
71 | if (iReset || iNR44[7]) begin // Register reload and counters restart.
72 |
73 | rLength <= iNR41[5:0];
74 | rLengthCounter <= 64-iNR41[5:0]; // Decrements to zero then load rLength.
75 | rLengthComplete <= 0; // Disables channel when is asserted.
76 |
77 | rStepTime <= iNR42[2:0];
78 | rStepCounter <= iNR42[2:0]; // Decrements to zero then load rStepTime.
79 | rEvelopeMode <= iNR42[3];
80 | rInitialValue <= iNR42[7:4];
81 | rStep <= iNR42[7:4];
82 |
83 | rDivRatioFreq <= iNR43[2:0];
84 |
85 | // rDivRatioCounter <= 6'd16;
86 | if (iNR43[2:0]==0) begin
87 | rDivRatioCounter[5:0] <= 6'd4;
88 | end
89 | else begin
90 | rDivRatioCounter[5:0] <= {iNR43[2:0],3'b0};
91 | end
92 |
93 | // rDivRatioCounter <= (iNR43[2:0]==0) ? 6'd4 : (iNR43[2:0]<<3) ; // fcpu/8
94 | rClkDiv <= 0;
95 |
96 | rPolCoutSteps <= iNR43[3];
97 |
98 | rShiftClockFreq <= iNR43[7:4];
99 | rShiftCounter <= (iNR43[7:4] < 15) ? 1 << iNR43[7:4] : 1 << 14;
100 | rCountPre <= 0;
101 |
102 | rTimedMode <= iNR44[6];
103 | end
104 | end
105 |
106 | // step gen: generates the output amplitud value.
107 | always @(posedge iOsc64) begin
108 | if (rStepTime != 0) begin // Check if channel is enabled.
109 | if (rStepCounter ==1 ) begin
110 | rStepCounter <= rStepTime; // Reset counter.
111 | if(rEvelopeMode) begin // Envelope mode.
112 | rStep <= ((rStep == 4'hF) ? rStep : rStep+1); //INCREASES ONLY IF STEP IF LOWER THAN TOP VALUE
113 | end
114 | else begin
115 | rStep <= ((rStep == 4'h0) ? rStep : rStep-1); //DECREASES ONLY IF STEP IF LOWER THAN BOTTOM VALUE
116 | end
117 | end
118 | else begin
119 | rStepCounter <= rStepCounter-1;
120 | end
121 | end
122 | end
123 |
124 |
125 | // clock divider
126 | always @(posedge iClock) begin
127 | if (rDivRatioCounter === 0) begin
128 | rClkDiv <= ~rClkDiv;
129 |
130 | if (rDivRatioFreq==0) begin
131 | rDivRatioCounter <= 6'd4;
132 | end
133 | else begin
134 | rDivRatioCounter <= {rDivRatioFreq,3'b0};
135 | end
136 | // rDivRatioCounter <= 6'd16;
137 | // rDivRatioCounter <= (rDivRatioFreq==0) ? 6'd4 : (rDivRatioFreq<<3) ; // fcpu/8
138 | end
139 | else begin
140 | rDivRatioCounter <= rDivRatioCounter-1;
141 | end
142 | end
143 |
144 | // counter pre-scaler
145 | always @(posedge rClkDiv) begin
146 | if (rShiftCounter == 0) begin
147 | rCountPre <= ~rCountPre;
148 | rShiftCounter <= (rShiftClockFreq < 15) ? 1 << rShiftClockFreq : 1 << 14;
149 | end
150 | else begin
151 | rShiftCounter <= rShiftCounter-1;
152 | end
153 | end
154 |
155 | // white noise gen
156 | lfsr l0 (
157 | .iClock(rCountPre),
158 | .iReset(iReset),
159 | .iStages(rPolCoutSteps),
160 | .oOut(rTone)
161 | );
162 |
163 |
164 | // timmer: enable or disable channel output.
165 | always @(posedge iOsc256) begin
166 | if (rLengthCounter == 0) begin
167 | rLengthCounter <= 64-rLength;
168 | rLengthComplete <= rTimedMode; // Disable channel only if timmer is enabled.
169 | end
170 | else begin
171 | rLengthCounter <= rLengthCounter-1;
172 | end
173 | end
174 |
175 | //re-map mux
176 | assign up_value = 5'd15 + rStep;
177 | assign down_value = 5'd15 - rStep;
178 |
179 | always @(posedge iClock) begin
180 | if (rLengthComplete) begin
181 | oOut[4:0] <= 5'd15;
182 | end
183 | else begin
184 | if (rTone) begin
185 | oOut[4:0] <= up_value[4:0];
186 | end
187 | else begin
188 | oOut[4:0] <= down_value[4:0];
189 | end
190 | end
191 | end
192 |
193 | assign oOnFlag = rLengthComplete;
194 | endmodule
195 |
196 | // misc modules.
197 |
198 | module lfsr //parameters
199 | (
200 | input wire iClock,
201 | input wire iReset,
202 | input wire iStages,
203 | output oOut
204 | );
205 |
206 | //Stage conection wires.
207 | wire wS0S1, wS1S2, wS2S3, wS3S4, wS4S5, wS5S6, wS6S7, wS7S8;
208 | wire wS8S9, wS9S10, wS10S11, wS11S12, wS12S13, wS13S14, wS14S15, wS15S16;
209 |
210 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_0 (
211 | .Clock(iClock),
212 | .Reset(iReset),
213 | .Enable(1),
214 | .iInitial(1),
215 | .D(oOut ^ wS6S7),
216 | .Q(wS0S1)
217 | );
218 |
219 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_1 (
220 | .Clock(iClock),
221 | .Reset(iReset),
222 | .Enable(1),
223 | .iInitial(1),
224 | .D(wS0S1),
225 | .Q(wS1S2)
226 | );
227 |
228 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_2 (
229 | .Clock(iClock),
230 | .Reset(iReset),
231 | .Enable(1),
232 | .iInitial(1),
233 | .D(wS1S2),
234 | .Q(wS2S3)
235 | );
236 |
237 |
238 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_3 (
239 | .Clock(iClock),
240 | .Reset(iReset),
241 | .Enable(1),
242 | .iInitial(1),
243 | .D(wS2S3),
244 | .Q(wS3S4)
245 | );
246 |
247 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_4 (
248 | .Clock(iClock),
249 | .Reset(iReset),
250 | .Enable(1),
251 | .iInitial(1),
252 | .D(wS3S4),
253 | .Q(wS4S5)
254 | );
255 |
256 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_5 (
257 | .Clock(iClock),
258 | .Reset(iReset),
259 | .Enable(1),
260 | .iInitial(1),
261 | .D(wS4S5),
262 | .Q(wS5S6)
263 | );
264 |
265 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_6 (
266 | .Clock(iClock),
267 | .Reset(iReset),
268 | .Enable(1),
269 | .iInitial(1),
270 | .D(wS5S6),
271 | .Q(wS6S7)
272 | );
273 |
274 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_7 (
275 | .Clock(iClock),
276 | .Reset(iReset),
277 | .Enable(1),
278 | .iInitial(1),
279 | .D(wS6S7),
280 | .Q(wS7S8)
281 | );
282 |
283 |
284 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_8 (
285 | .Clock(iClock),
286 | .Reset(iReset),
287 | .Enable(1),
288 | .iInitial(1),
289 | .D(wS7S8),
290 | .Q(wS8S9)
291 | );
292 |
293 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_9 (
294 | .Clock(iClock),
295 | .Reset(iReset),
296 | .Enable(1),
297 | .iInitial(1),
298 | .D(wS8S9),
299 | .Q(wS9S10)
300 | );
301 |
302 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_10 (
303 | .Clock(iClock),
304 | .Reset(iReset),
305 | .Enable(1),
306 | .iInitial(1),
307 | .D(wS9S10),
308 | .Q(wS10S11)
309 | );
310 |
311 |
312 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_11 (
313 | .Clock(iClock),
314 | .Reset(iReset),
315 | .Enable(1),
316 | .iInitial(1),
317 | .D(wS10S11),
318 | .Q(wS11S12)
319 | );
320 |
321 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_12 (
322 | .Clock(iClock),
323 | .Reset(iReset),
324 | .Enable(1),
325 | .iInitial(1),
326 | .D(wS11S12),
327 | .Q(wS12S13)
328 | );
329 |
330 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_13 (
331 | .Clock(iClock),
332 | .Reset(iReset),
333 | .Enable(1),
334 | .iInitial(1),
335 | .D(wS12S13),
336 | .Q(wS13S14)
337 | );
338 |
339 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_14 (
340 | .Clock(iClock),
341 | .Reset(iReset),
342 | .Enable(1),
343 | .iInitial(1),
344 | .D(wS13S14),
345 | .Q(wS14S15)
346 | );
347 |
348 | FFD_POSEDGE_ASYNCRONOUS_RESET_INIT # ( 1 ) FF_CH4_15 (
349 | .Clock(iClock),
350 | .Reset(iReset),
351 | .Enable(1),
352 | .iInitial(1),
353 | .D(wS14S15),
354 | .Q(wS15S16)
355 | );
356 |
357 | assign oOut = (iStages) ? wS7S8 : wS15S16 ;
358 | endmodule
359 |
--------------------------------------------------------------------------------
/rtl/gpu_ucode_rom.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | `include "gpu_definitions.v"
3 | ////////////////////////////////////////////////////////////////////////////////////
4 | //
5 | // pGB, yet another FPGA fully functional and super fun GB classic clone!
6 | // Copyright (C) 2015-2016 Diego Valverde (diego.valverde.g@gmail.com)
7 | //
8 | // This program is free software; you can redistribute it and/or
9 | // modify it under the terms of the GNU General Public License
10 | // as published by the Free Software Foundation; either version 2
11 | // of the License, or (at your option) any later version.
12 | //
13 | // This program is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with this program; if not, write to the Free Software
20 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 | //
22 | ////////////////////////////////////////////////////////////////////////////////////
23 |
24 |
25 | module gpu_ucode_rom
26 | (
27 | input wire[7:0] iAddr,
28 | output reg [`GPU_UOP_SZ-1:0] oUop
29 | );
30 |
31 |
32 |
33 | always @ ( iAddr )
34 | begin
35 | case ( iAddr )
36 |
37 | /*
38 | /////////////PSEUDO CODE FOR BETTER UNDERSTANDING////////////////////
39 |
40 | state = SCANLINE_VRAM_READ
41 | cur_tile = 0
42 | 1:
43 | tile_row = 0
44 | 2:
45 | r2 = 32
46 | 3:
47 |
48 | vmem_addr = bgmoffset + cur_tile
49 | grvmem
50 | vmem_addr = bgtoffset + tile_row + vmem_data_shl_4
51 | grvmem
52 |
53 | bh = vmem_data
54 | vmem_addr++
55 | grvmem
56 | bl = vmem_data
57 | gwfbuffer
58 |
59 | cur_tile++
60 | r2--
61 | if (r2 > 0)
62 | goto 3
63 |
64 |
65 | tile_row += 2;
66 | ly++
67 | if (tile_row <= f)
68 | cur_tile -= 32
69 | goto 2;
70 | else
71 | goto 1
72 |
73 |
74 | */
75 | ///////////////////////////////////////////////////////////////////////////
76 | //defines code for getting the first tile and applying color pallete to it
77 | 0: oUop = { `gnop, `gnull, `gnull, `gnull }; //always has to be a nop because of pc definition
78 | 1: oUop = { `gwrl, `state, `SCANLINE_VRAM_READ };// writes a literal to register state for cpu to know which state the GPU currently is
79 |
80 | //Frame buffer render main loop. Ie. current_tile = 0
81 | 2: oUop = { `gwrr, `cur_tile, `scy_shl_5__plus_scx, `gnull };//which tile am I on, (oScy >>3) <<5 + oScx)
82 | 3: oUop = { `gwrr, `WinTile, `Win_index, `gnull }; // set up window tile index
83 | //Next tile row loop
84 | 4: oUop = { `gwrr, `tile_row, `scy_tile_row_offset, `gnull}; // which tile row am I on
85 | //
86 | 5: oUop = { `gwrl, `r2, 12'd32 };//assign a literal to r2, 32 tiles
87 |
88 | //Current tile render loop
89 | 6: oUop = { `gadd, `vmem_addr, `bgmoffset, `cur_tile };// adds current tile with bg offset to get vmem adress to know where to read
90 | 7: oUop = { `grvmem, `gnull, `gnull, `gnull };//reads vmem and stores in vmem_data
91 | 8: oUop = { `gwrr, `r3, `vmem_addr, `gnull };// store vmem adress in r3
92 | 9: oUop = { `gadd, `r1,`vmem_data_shl_4, `tile_row };//add tile row with vmem data shifted left by 4
93 | 10: oUop = { `gadd, `vmem_addr, `r1, `bgtoffset };// get address for tile memory with r1 and BG tile offset
94 | 11: oUop = { `grvmem, `gnull, `gnull, `gnull };//read from tile memory stores in vmem data
95 | 12: oUop = { `gwrr, `bh, `vmem_data, `gnull };// save in BH for high byte
96 | 13: oUop = { `gaddl, `vmem_addr, 12'd1 };// get adress for BL adding one to current adress, reads next byte
97 | 14: oUop = { `grvmem, `gnull, `gnull, `gnull }; // save in vmem data
98 | 15: oUop = { `gwrr, `bl, `vmem_data, `gnull };//save in BL for low byte
99 | 16: oUop = { `gwfbuffer, `gnull,`gnull, `gnull};// BH and BL go through bg pallete and result gets saved in framebuffer
100 |
101 | /////////////////////////uCode for sprite loop/////////////////////////////////////
102 |
103 | 17: oUop = {`gwrl, `r6, 12'b10}; // set bit 2 as 1 for next oUopp
104 | 18: oUop = {`gand, `r3, `r6, `lcdc}; //and bitwise for r6 and lcdc[1] = 1 sprites are on
105 | 19: oUop = {`gjz,`skip_the_sprites};
106 | 20:
107 | begin
108 | oUop = {`gwrl, `r6, 12'd0}; //we have a maximum of 40 sprites x= 39*4 because if 4 byte descriptors
109 |
110 | end
111 |
112 | 21: oUop = {`gadd, `vmem_addr, `r6, `oam_offset}; //get address of sprite
113 | 22: oUop = {`grvmem, `gnull, `gnull, `gnull}; //store vmem data loads first byte of sprite descriptor
114 | 23: oUop = {`gsubl, `vmem_data, 12'd0}; //Test to see if the sprite_y_coord is zero
115 | 24: oUop = {`gjz, `get_next_sprite}; //if y coord is zero jump to next sprite
116 | 25: oUop = {`gwrl,`r4 , 12'd16}; //Since the sprite_y_coord was no zero, we need to substract 16 in order to obtain the real sprite_y_coord
117 | 26: oUop = {`gsub,`sprite_y_coord ,`vmem_data,`r4}; //get y coord of the sprite
118 | 27: oUop = {`gaddl, `vmem_addr, 12'd1}; //get address for next byte of sprite descriptor
119 | 28: oUop = {`grvmem, `gnull,`gnull,`gnull};
120 | 29: oUop = {`gsubl, `vmem_data, 12'd0}; //Test to see if the sprite_x_coord is zero
121 | 30: oUop = {`gjz, `get_next_sprite}; //if x coord is zero jump to next sprite
122 | 31: oUop = {`gwrl,`r4 , 12'd8};
123 | 32: oUop = {`gsub, `sprite_x_coord ,`vmem_data ,`r4 }; //get x coord
124 | 33: oUop = {`gnop, `gnull, `gnull, `gnull}; //{`gsub, `r5, `tile_column, `vmem_data};
125 | 34: oUop = {`gsprtt, `r4, `sprite_x_coord, `sprite_y_coord}; //Test if the sprite is in the current tile
126 | 35: oUop = {`gjz, `get_next_sprite};
127 | //Fetch sprite tile number
128 | 36: oUop = {`gaddl, `vmem_addr, 12'd1};//get next byte sprite index
129 | 37: oUop = {`grvmem, `gnull,`gnull,`gnull};
130 | 38: oUop = {`gadd, `r4 ,`vmem_data_shl_4, `tile_row };//`sprite_current_row_offset}; //define sprite tile index shifted by 4 to the left would get added with bgomffset for tile memory read
131 | 39: oUop = {`gaddl, `vmem_addr, 12'd1};//get next byte sprite options
132 | 40: oUop = {`grvmem, `gnull,`gnull,`gnull};
133 | 41: oUop = {`gwrr, `sprite_info,`vmem_data}; //define `sprite_info bits are important for effects flips and flashes
134 | //TODO DEFINE LOGIC FOR SpriteOPTIONS (LA FLECHA DE TETRIS NO TIENE OPTIONS ENTONCES QUIERO PROBAR DIBUJARLA SIN HACER LA PARTE
135 | //DE OPTIONS)
136 | //GO read tile memory
137 |
138 | 42: oUop = {`gadd, `vmem_addr,`bgtoffset,`r4}; //by adding this two you get the address of the tile memory
139 | 43: oUop = {`grvmem,`gnull,`gnull,`gnull};
140 | 44: oUop = {`gwrr, `sh, `vmem_data, `gnull}; //first tile high byte for current sprite
141 | 45: oUop = {`gaddl, `vmem_addr, 12'd1};
142 | 46: oUop = {`grvmem, `gnull,`gnull,`gnull};
143 | 47: oUop = {`gwrr, `sl,`vmem_data, `gnull}; //second tile low byte for current sprite
144 | 48: oUop = {`gnop, `gnull, `gnull, `gnull};//{`glsprtt, `gnull, `tile_row,`sprite_y_coord}; //test if sprite is in current row
145 | 49: oUop = {`gnop, `gnull, `gnull, `gnull};//{`gjz,`get_next_sprite};
146 | //TODO LOGIC FOR BACKGROUND AND FOREGROUND display for sprites
147 | //sprite palette logic
148 | 50: oUop = {`gwfbuffer, `gnull,`gnull, `gnull};// SH and SL go through sprite palletes and result gets saved in framebuffer
149 | //get_next_sprite
150 | 51: oUop = {`gaddl,`r6, 12'd4};
151 | 52: oUop = {`gsubl,`r6, 12'd156};//39*4 = 156
152 | 53: begin
153 | //$display("DRAW THE ARROW PLZ \n");
154 | //oUop = {`gjnz, 15'd20}; // end of sprites go to next tile
155 | oUop = {`gwrr, `sprite_current_row_offset, `tile_row, `gnull}; //Each sprite row is 2Bytes (8 pixles). Increment the sprite row offset by 2 for next iteration
156 | // $finish();
157 | end
158 | /***************End of ucode for sprite loop********************************/
159 |
160 | /************** Start of ucode for window **********************************/
161 | //skip_the_sprites
162 | 54: oUop = {`gwrl, `r6, 12'b00100001}; //set 1 on pos[5] of a temporal register
163 | 55: oUop = {`gand, `r3, `r6, `lcdc}; // and with lcdc and save in r3
164 | 56: oUop = {`gjz,`skip_the_window}; // if lcdc[5] and lcdc[0] not 1 then window display is off
165 | 57: oUop = {`gwx, `gnull, `gnull, `gnull};
166 | 58: oUop = {`gjz,`skip_the_window};
167 | 59: oUop = {`gwy, `gnull, `gnull, `gnull}; //check if wx and wy are on screen
168 | 60: //begin
169 | // $display("I would check for a window tile...if i had one !!!");
170 | oUop = {`gjz,`skip_the_window};
171 | //end
172 | ///////at this point ,window is on and wx and wy are inside screen////////////////
173 | 61: oUop = {`gsubl, `IsThisTileWin, 12'b0 }; //first we ask if current tile is a window tile
174 | 62: oUop = {`gjnz,`initialize_window}; // if Isthistilewin is 0 background tile isn't inside of window
175 | 63: oUop = {`gsubl,`Window_render,12'b0};
176 | 64: oUop = {`gjnz,`render_window};
177 | 65: oUop = {`ggoto,`skip_the_window};
178 | //initialize_window
179 | 66: oUop = {`gwrl,`r5, 12'b0};
180 | 67: oUop = {`gwrl,`Window_render, 12'b1};
181 | ///render_window
182 | 68: oUop = { `gadd, `vmem_addr, `Winmoffset, `r5 };//r5 is 0 so this would get the mem adress 9C00//{ `gadd, `vmem_addr, `Winmoffset, `WinTile }//this one is not working
183 | 69: oUop = { `grvmem, `gnull, `gnull, `gnull };//reads vmem and stores in vmem_data
184 | 70: oUop = { `gwrr, `r3, `vmem_addr, `gnull };// store vmem adress in r3
185 | 71: oUop = { `gadd, `r1,`vmem_data_shl_4, `tile_row };//add tile row with vmem data shifted left by 4
186 | 72: oUop = { `gadd, `vmem_addr, `r1, `bgtoffset };// get address for tile memory with r1 and BG tile offset which is the same for window
187 | 73: oUop = { `grvmem, `gnull, `gnull, `gnull };//read from tile memory stores in vmem data
188 | 74: oUop = { `gwrr, `bh, `vmem_data, `gnull };// save in BH for high byte
189 | 75: oUop = { `gaddl, `vmem_addr, 12'd1 };// get adress for BL adding one to current address, reads next byte
190 | 76: oUop = { `grvmem, `gnull, `gnull, `gnull }; // save in vmem data
191 | 77: oUop = { `gwrr, `bl, `vmem_data, `gnull };//save in BL for low byte
192 | 78: oUop = { `gwfbuffer, `gnull,`gnull, `gnull};// BH and BL go through bg pallete which work for window and result gets saved in framebuffer
193 | ///Update win tile index
194 | 79: oUop = {`gaddl, `r5, 12'd1};// add 1 to r5, take in account this has to be changed for r5 its actually used in most logic..dedicate a reg
195 | 80: oUop = { `gaddl, `WinTile, 12'd1 }; //set up WinTile register for next iteration
196 | 81: oUop = { `gsubl, `WinTile, 12'd255 }; // are we going out off screen boundaries
197 | 82: oUop = { `gjnz, `skip_the_window };
198 | 83: oUop = { `gwrl, `Window_render, 12'd0 };
199 | //////////////////////////////end of window ucode//////////////////////////////////////////////////
200 | //defines loop for getting the same row for the next tile//
201 | //skip_the_window
202 | 84: oUop = {`ginfbaddr, `gnull, `gnull, `gnull}; //Increment the framebuffer write pointer
203 | 85: oUop = {`gwrl, `sl, 12'd0};
204 | 86: oUop = {`gwrl, `sh, 12'd0};
205 | 87: oUop = { `gsubl, `r1, 12'd8191}; //limit 0x1FFF or d 8191
206 | 88: oUop = { `gsub, `r1, `fbuffer_addr, `r8191}; //Did we painted all of the 32x32 tiles?
207 | 89: oUop = { `gjz, 18'h2}; //Yes, ok restart the loop for next frame
208 | 90: oUop = { `gaddl, `r5, 12'd0 }; //increment window tile
209 | 91: oUop = { `gwrl,`sprite_current_row_offset, 12'd0}; //Reset the sprite roww offset to zero since we will start with a fresh tile now
210 | 92: oUop = { `gaddl, `cur_tile, 12'd1 }; //Time to take care of the next tile
211 | 93: oUop = { `gsubl, `r2, 12'd1 }; //Is this tile the last of the 2 tiles in a tile row?
212 | 94: oUop = { `gjnz , 18'd6}; //No, Keep rendering the remaining rows of the current tile line
213 | 95: oUop = { `gaddl, `tile_row, 12'd2 };
214 | 96: oUop = { `gaddl , `ly, 12'd1 };
215 | 97: oUop = { `gwrr, `r1, `tile_row, `gnull };
216 | 98: oUop = { `gsubl, `r1, 12'h10 };
217 | 99: oUop = { `gjz , 18'd4 }; //Move to next tile row 0
218 |
219 | //defines jump to next row of pixels
220 | 100: oUop = { `gsubl, `r5, 12'd32 };
221 | 101: oUop = { `gsubl, `cur_tile, 12'd32 }; //Reset the tile index to the first tile index in the row of tiles, this is because we always start a a row of tiles from left to right (like a typewritting machine)
222 | 102: oUop = { `ggoto, 18'd5 }; //Move down one row
223 |
224 | endcase
225 | end
226 |
227 | endmodule
228 |
--------------------------------------------------------------------------------