OpenCores
URL https://opencores.org/ocsvn/fpz8/fpz8/trunk

Subversion Repositories fpz8

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/CPU.bdf
21,7 → 21,7
(header "graphic" (version "1.3"))
(pin
(input)
(rect 64 96 232 112)
(rect 40 64 208 80)
(text "INPUT" (rect 133 0 161 10)(font "Arial" (font_size 6)))
(text "CLOCK" (rect 9 0 46 12)(font "Arial" ))
(pt 168 8)
34,11 → 34,11
(line (pt 117 12)(pt 121 8)(line_width 1))
)
(text "VCC" (rect 136 7 156 17)(font "Arial" (font_size 6)))
(annotation_block (location)(rect 16 112 64 128))
(annotation_block (location)(rect -8 64 40 80))
)
(pin
(input)
(rect 64 112 232 128)
(rect 40 80 208 96)
(text "INPUT" (rect 133 0 161 10)(font "Arial" (font_size 6)))
(text "RESET" (rect 9 0 44 12)(font "Arial" ))
(pt 168 8)
51,11 → 51,11
(line (pt 117 12)(pt 121 8)(line_width 1))
)
(text "VCC" (rect 136 7 156 17)(font "Arial" (font_size 6)))
(annotation_block (location)(rect 16 128 64 144))
(annotation_block (location)(rect -8 80 40 96))
)
(pin
(input)
(rect 64 160 232 176)
(rect 40 176 208 192)
(text "INPUT" (rect 133 0 161 10)(font "Arial" (font_size 6)))
(text "DBG_RX" (rect 5 0 48 12)(font "Arial" ))
(pt 168 8)
68,11 → 68,11
(line (pt 117 12)(pt 121 8)(line_width 1))
)
(text "VCC" (rect 136 7 156 17)(font "Arial" (font_size 6)))
(annotation_block (location)(rect 16 176 64 192))
(annotation_block (location)(rect -8 176 40 192))
)
(pin
(output)
(rect 40 400 216 416)
(rect 40 464 216 480)
(text "OUTPUT" (rect 137 0 175 10)(font "Arial" (font_size 6)))
(text "PAOUT[7..0]" (rect 5 0 67 12)(font "Arial" ))
(pt 176 8)
86,11 → 86,11
(line (pt 98 12)(pt 94 8)(line_width 1))
)
(flipy)
(annotation_block (location)(rect 216 416 264 528))
(annotation_block (location)(rect 48 480 96 592))
)
(pin
(output)
(rect 56 176 232 192)
(rect 40 160 216 176)
(text "OUTPUT" (rect 137 6 175 16)(font "Arial" (font_size 6)))
(text "DBG_TX" (rect 5 4 46 16)(font "Arial" ))
(pt 176 8)
104,323 → 104,338
(line (pt 98 4)(pt 94 8)(line_width 1))
)
(rotate180)
(annotation_block (location)(rect 232 192 280 208))
(annotation_block (location)(rect -8 160 40 176))
)
(symbol
(rect 968 88 1032 136)
(text "AND2" (rect 39 38 63 48)(font "Arial" (font_size 6)))
(text "inst8" (rect 38 -1 61 11)(font "Arial" ))
(rect 608 -24 864 88)
(text "altsyncram2" (rect 168 0 251 16)(font "Arial" (font_size 10)))
(text "Program_Memory" (rect 8 100 95 112)(font "Arial" ))
(port
(pt 64 32)
(pt 0 80)
(input)
(text "IN1" (rect 2 7 19 19)(font "Courier New" (bold))(invisible))
(text "IN1" (rect 45 29 62 41)(font "Courier New" (bold))(invisible))
(line (pt 64 32)(pt 50 32)(line_width 1))
(text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 4 79 57 93)(font "Arial" (font_size 8)))
(line (pt 0 80)(pt 112 80)(line_width 3))
)
(port
(pt 64 16)
(pt 0 64)
(input)
(text "IN2" (rect 2 23 19 35)(font "Courier New" (bold))(invisible))
(text "IN2" (rect 45 13 62 25)(font "Courier New" (bold))(invisible))
(line (pt 64 16)(pt 50 16)(line_width 1))
(text "address[13..0]" (rect 0 0 82 14)(font "Arial" (font_size 8)))
(text "address[13..0]" (rect 4 63 86 77)(font "Arial" (font_size 8)))
(line (pt 0 64)(pt 112 64)(line_width 3))
)
(port
(pt 0 48)
(input)
(text "wren" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "wren" (rect 4 47 34 61)(font "Arial" (font_size 8)))
(line (pt 0 48)(pt 112 48)(line_width 1))
)
(port
(pt 0 24)
(input)
(text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))
(text "clock" (rect 4 23 33 37)(font "Arial" (font_size 8)))
(line (pt 0 24)(pt 104 24)(line_width 1))
)
(port
(pt 256 80)
(output)
(text "OUT" (rect 48 15 65 27)(font "Courier New" (bold))(invisible))
(text "OUT" (rect -1 21 16 33)(font "Courier New" (bold))(invisible))
(line (pt 22 24)(pt 0 24)(line_width 1))
(text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 223 79 258 93)(font "Arial" (font_size 8)))
(line (pt 256 80)(pt 168 80)(line_width 3))
)
(drawing
(line (pt 50 36)(pt 34 36)(line_width 1))
(line (pt 50 11)(pt 33 11)(line_width 1))
(line (pt 50 36)(pt 50 11)(line_width 1))
(arc (pt 33 11)(pt 34 36)(rect 21 11 46 36)(line_width 1))
(text "16384 Word(s)" (rect 136 20 148 91)(font "Arial" )(vertical))
(text "RAM" (rect 149 47 161 70)(font "Arial" )(vertical))
(text "Block Type: AUTO" (rect 41 8 133 20)(font "Arial" ))
(line (pt 128 88)(pt 168 88)(line_width 1))
(line (pt 168 88)(pt 168 32)(line_width 1))
(line (pt 168 32)(pt 128 32)(line_width 1))
(line (pt 128 32)(pt 128 88)(line_width 1))
(line (pt 112 85)(pt 120 85)(line_width 1))
(line (pt 120 85)(pt 120 73)(line_width 1))
(line (pt 120 73)(pt 112 73)(line_width 1))
(line (pt 112 73)(pt 112 85)(line_width 1))
(line (pt 112 78)(pt 114 76)(line_width 1))
(line (pt 114 76)(pt 112 74)(line_width 1))
(line (pt 104 76)(pt 112 76)(line_width 1))
(line (pt 120 80)(pt 128 80)(line_width 3))
(line (pt 112 69)(pt 120 69)(line_width 1))
(line (pt 120 69)(pt 120 57)(line_width 1))
(line (pt 120 57)(pt 112 57)(line_width 1))
(line (pt 112 57)(pt 112 69)(line_width 1))
(line (pt 112 62)(pt 114 60)(line_width 1))
(line (pt 114 60)(pt 112 58)(line_width 1))
(line (pt 104 60)(pt 112 60)(line_width 1))
(line (pt 120 64)(pt 128 64)(line_width 3))
(line (pt 112 53)(pt 120 53)(line_width 1))
(line (pt 120 53)(pt 120 41)(line_width 1))
(line (pt 120 41)(pt 112 41)(line_width 1))
(line (pt 112 41)(pt 112 53)(line_width 1))
(line (pt 112 46)(pt 114 44)(line_width 1))
(line (pt 114 44)(pt 112 42)(line_width 1))
(line (pt 104 44)(pt 112 44)(line_width 1))
(line (pt 120 48)(pt 128 48)(line_width 1))
(line (pt 104 76)(pt 104 23)(line_width 1))
)
(rotate180)
(flipx)
)
(symbol
(rect 280 40 448 440)
(rect 280 40 480 512)
(text "fpz8_cpu_v1" (rect 5 0 68 12)(font "Arial" ))
(text "inst" (rect 0 384 17 396)(font "Arial" ))
(text "inst" (rect 8 456 25 468)(font "Arial" ))
(port
(pt 168 64)
(pt 200 80)
(input)
(text "IDB[7..0]" (rect 0 0 44 12)(font "Arial" ))
(text "IDB[7..0]" (rect 100 56 144 68)(font "Arial" ))
(line (pt 152 64)(pt 168 64)(line_width 3))
(text "IDB[7..0]" (rect 132 72 176 84)(font "Arial" ))
(line (pt 184 80)(pt 200 80)(line_width 3))
)
(port
(pt 168 144)
(pt 200 160)
(input)
(text "MIDB[7..0]" (rect 0 0 53 12)(font "Arial" ))
(text "MIDB[7..0]" (rect 96 136 149 148)(font "Arial" ))
(line (pt 152 144)(pt 168 144)(line_width 3))
(text "FRIDB[7..0]" (rect 0 0 60 12)(font "Arial" ))
(text "FRIDB[7..0]" (rect 116 152 176 164)(font "Arial" ))
(line (pt 184 160)(pt 200 160)(line_width 3))
)
(port
(pt 168 176)
(pt 200 224)
(input)
(text "RIDB[7..0]" (rect 0 0 53 12)(font "Arial" ))
(text "RIDB[7..0]" (rect 96 168 149 180)(font "Arial" ))
(line (pt 152 176)(pt 168 176)(line_width 3))
(text "RIDB[7..0]" (rect 123 216 176 228)(font "Arial" ))
(line (pt 184 224)(pt 200 224)(line_width 3))
)
(port
(pt 168 368)
(pt 200 432)
(input)
(text "INT0" (rect 0 0 23 12)(font "Arial" ))
(text "INT0" (rect 121 360 144 372)(font "Arial" ))
(line (pt 152 368)(pt 168 368)(line_width 1))
(text "INT0" (rect 153 424 176 436)(font "Arial" ))
(line (pt 184 432)(pt 200 432)(line_width 1))
)
(port
(pt 168 352)
(pt 200 416)
(input)
(text "INT1" (rect 0 0 23 12)(font "Arial" ))
(text "INT1" (rect 121 344 144 356)(font "Arial" ))
(line (pt 152 352)(pt 168 352)(line_width 1))
(text "INT1" (rect 153 408 176 420)(font "Arial" ))
(line (pt 184 416)(pt 200 416)(line_width 1))
)
(port
(pt 168 336)
(pt 200 400)
(input)
(text "INT2" (rect 0 0 23 12)(font "Arial" ))
(text "INT2" (rect 121 328 144 340)(font "Arial" ))
(line (pt 152 336)(pt 168 336)(line_width 1))
(text "INT2" (rect 153 392 176 404)(font "Arial" ))
(line (pt 184 400)(pt 200 400)(line_width 1))
)
(port
(pt 168 320)
(pt 200 384)
(input)
(text "INT3" (rect 0 0 23 12)(font "Arial" ))
(text "INT3" (rect 121 312 144 324)(font "Arial" ))
(line (pt 152 320)(pt 168 320)(line_width 1))
(text "INT3" (rect 153 376 176 388)(font "Arial" ))
(line (pt 184 384)(pt 200 384)(line_width 1))
)
(port
(pt 168 304)
(pt 200 368)
(input)
(text "INT4" (rect 0 0 23 12)(font "Arial" ))
(text "INT4" (rect 121 296 144 308)(font "Arial" ))
(line (pt 152 304)(pt 168 304)(line_width 1))
(text "INT4" (rect 153 360 176 372)(font "Arial" ))
(line (pt 184 368)(pt 200 368)(line_width 1))
)
(port
(pt 168 288)
(pt 200 352)
(input)
(text "INT5" (rect 0 0 23 12)(font "Arial" ))
(text "INT5" (rect 121 280 144 292)(font "Arial" ))
(line (pt 152 288)(pt 168 288)(line_width 1))
(text "INT5" (rect 153 344 176 356)(font "Arial" ))
(line (pt 184 352)(pt 200 352)(line_width 1))
)
(port
(pt 168 272)
(pt 200 336)
(input)
(text "INT6" (rect 0 0 23 12)(font "Arial" ))
(text "INT6" (rect 121 264 144 276)(font "Arial" ))
(line (pt 152 272)(pt 168 272)(line_width 1))
(text "INT6" (rect 153 328 176 340)(font "Arial" ))
(line (pt 184 336)(pt 200 336)(line_width 1))
)
(port
(pt 0 128)
(pt 200 320)
(input)
(text "INT7" (rect 0 0 23 12)(font "Arial" ))
(text "INT7" (rect 153 312 176 324)(font "Arial" ))
(line (pt 184 320)(pt 200 320)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "DBG_RX" (rect 0 0 43 12)(font "Arial" ))
(text "DBG_RX" (rect 21 123 64 135)(font "Arial" ))
(line (pt 0 128)(pt 16 128)(line_width 1))
(text "DBG_RX" (rect 21 139 64 151)(font "Arial" ))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 0 352)
(pt 0 416)
(input)
(text "PAIN[7..0]" (rect 0 0 51 12)(font "Arial" ))
(text "PAIN[7..0]" (rect 21 347 72 359)(font "Arial" ))
(line (pt 0 352)(pt 16 352)(line_width 3))
(text "PAIN[7..0]" (rect 21 411 72 423)(font "Arial" ))
(line (pt 0 416)(pt 16 416)(line_width 3))
)
(port
(pt 0 64)
(pt 0 32)
(input)
(text "CLK" (rect 0 0 21 12)(font "Arial" ))
(text "CLK" (rect 21 59 42 71)(font "Arial" ))
(line (pt 0 64)(pt 16 64)(line_width 1))
(text "CLK" (rect 21 27 42 39)(font "Arial" ))
(line (pt 0 32)(pt 16 32)(line_width 1))
)
(port
(pt 0 80)
(pt 0 48)
(input)
(text "RESET" (rect 0 0 35 12)(font "Arial" ))
(text "RESET" (rect 21 75 56 87)(font "Arial" ))
(line (pt 0 80)(pt 16 80)(line_width 1))
(text "RESET" (rect 21 43 56 55)(font "Arial" ))
(line (pt 0 48)(pt 16 48)(line_width 1))
)
(port
(pt 168 32)
(pt 200 48)
(output)
(text "IAB[15..0]" (rect 0 0 49 12)(font "Arial" ))
(text "IAB[15..0]" (rect 98 27 147 39)(font "Arial" ))
(line (pt 168 32)(pt 152 32)(line_width 3))
(text "IAB[15..0]" (rect 24 0 73 12)(font "Arial" ))
(text "IAB[15..0]" (rect 127 40 176 52)(font "Arial" ))
(line (pt 200 48)(pt 184 48)(line_width 3))
)
(port
(pt 168 48)
(pt 200 64)
(output)
(text "PWDB[7..0]" (rect 0 0 59 12)(font "Arial" ))
(text "PWDB[7..0]" (rect 83 40 142 52)(font "Arial" ))
(line (pt 168 48)(pt 152 48)(line_width 3))
(text "IWDB[7..0]" (rect 24 0 79 12)(font "Arial" ))
(text "IWDB[7..0]" (rect 121 56 176 68)(font "Arial" ))
(line (pt 200 64)(pt 184 64)(line_width 3))
)
(port
(pt 168 112)
(pt 200 128)
(output)
(text "MAB[11..0]" (rect 0 0 54 12)(font "Arial" ))
(text "MAB[11..0]" (rect 96 104 150 116)(font "Arial" ))
(line (pt 168 112)(pt 152 112)(line_width 3))
(text "FRAB[11..0]" (rect 24 0 85 12)(font "Arial" ))
(text "FRAB[11..0]" (rect 115 120 176 132)(font "Arial" ))
(line (pt 200 128)(pt 184 128)(line_width 3))
)
(port
(pt 168 128)
(pt 200 144)
(output)
(text "MODB[7..0]" (rect 0 0 57 12)(font "Arial" ))
(text "MODB[7..0]" (rect 96 120 153 132)(font "Arial" ))
(line (pt 168 128)(pt 152 128)(line_width 3))
(text "FRODB[7..0]" (rect 24 0 88 12)(font "Arial" ))
(text "FRODB[7..0]" (rect 112 136 176 148)(font "Arial" ))
(line (pt 200 144)(pt 184 144)(line_width 3))
)
(port
(pt 168 160)
(pt 200 208)
(output)
(text "RODB[7..0]" (rect 0 0 57 12)(font "Arial" ))
(text "RODB[7..0]" (rect 96 152 153 164)(font "Arial" ))
(line (pt 168 160)(pt 152 160)(line_width 3))
(text "RODB[7..0]" (rect 24 0 81 12)(font "Arial" ))
(text "RODB[7..0]" (rect 119 200 176 212)(font "Arial" ))
(line (pt 200 208)(pt 184 208)(line_width 3))
)
(port
(pt 168 80)
(pt 200 96)
(output)
(text "PGM_WR" (rect 0 0 48 12)(font "Arial" ))
(text "PGM_WR" (rect 94 72 142 84)(font "Arial" ))
(line (pt 168 80)(pt 152 80)(line_width 1))
(text "PGM_WR" (rect 24 0 72 12)(font "Arial" ))
(text "PGM_WR" (rect 128 88 176 100)(font "Arial" ))
(line (pt 200 96)(pt 184 96)(line_width 1))
)
(port
(pt 168 208)
(pt 200 192)
(output)
(text "WR" (rect 0 0 18 12)(font "Arial" ))
(text "WR" (rect 124 200 142 212)(font "Arial" ))
(line (pt 168 208)(pt 152 208)(line_width 1))
(text "WR" (rect 24 0 42 12)(font "Arial" ))
(text "WR" (rect 158 184 176 196)(font "Arial" ))
(line (pt 200 192)(pt 184 192)(line_width 1))
)
(port
(pt 168 240)
(pt 200 240)
(output)
(text "REG_SEL" (rect 0 0 49 12)(font "Arial" ))
(text "REG_SEL" (rect 93 232 142 244)(font "Arial" ))
(line (pt 168 240)(pt 152 240)(line_width 1))
(text "REG_SEL" (rect 24 0 73 12)(font "Arial" ))
(text "REG_SEL" (rect 127 232 176 244)(font "Arial" ))
(line (pt 200 240)(pt 184 240)(line_width 1))
)
(port
(pt 168 224)
(pt 200 176)
(output)
(text "MEM_SEL" (rect 0 0 49 12)(font "Arial" ))
(text "MEM_SEL" (rect 93 216 142 228)(font "Arial" ))
(line (pt 168 224)(pt 152 224)(line_width 1))
(text "MEM_SEL" (rect 24 0 73 12)(font "Arial" ))
(text "MEM_SEL" (rect 127 168 176 180)(font "Arial" ))
(line (pt 200 176)(pt 184 176)(line_width 1))
)
(port
(pt 0 144)
(pt 0 128)
(output)
(text "DBG_TX" (rect 0 0 41 12)(font "Arial" ))
(text "DBG_TX" (rect 24 136 65 148)(font "Arial" ))
(line (pt 16 144)(pt 0 144)(line_width 1))
(text "DBG_TX" (rect 24 0 65 12)(font "Arial" ))
(text "DBG_TX" (rect 24 120 65 132)(font "Arial" ))
(line (pt 16 128)(pt 0 128)(line_width 1))
)
(port
(pt 0 368)
(pt 0 432)
(output)
(text "PAOUT[7..0]" (rect 0 0 62 12)(font "Arial" ))
(text "PAOUT[7..0]" (rect 24 360 86 372)(font "Arial" ))
(line (pt 16 368)(pt 0 368)(line_width 3))
(text "PAOUT[7..0]" (rect 24 0 86 12)(font "Arial" ))
(text "PAOUT[7..0]" (rect 24 424 86 436)(font "Arial" ))
(line (pt 16 432)(pt 0 432)(line_width 3))
)
(port
(pt 0 48)
(pt 200 256)
(output)
(text "CLK_OUT" (rect 0 0 49 12)(font "Arial" ))
(text "CLK_OUT" (rect 24 40 73 52)(font "Arial" ))
(line (pt 16 48)(pt 0 48)(line_width 1))
(text "CLK_OUT" (rect 24 0 73 12)(font "Arial" ))
(text "CLK_OUT" (rect 127 248 176 260)(font "Arial" ))
(line (pt 200 256)(pt 184 256)(line_width 1))
)
(port
(pt 0 32)
(pt 200 32)
(output)
(text "CLK_OUTN" (rect 0 0 57 12)(font "Arial" ))
(text "CLK_OUTN" (rect 24 24 81 36)(font "Arial" ))
(line (pt 16 32)(pt 0 32)(line_width 1))
(text "CLK_OUTN" (rect 24 0 81 12)(font "Arial" ))
(text "CLK_OUTN" (rect 119 24 176 36)(font "Arial" ))
(line (pt 200 32)(pt 184 32)(line_width 1))
)
(port
(pt 0 96)
(pt 200 288)
(output)
(text "STOP" (rect 0 0 28 12)(font "Arial" ))
(text "STOP" (rect 24 88 52 100)(font "Arial" ))
(line (pt 16 96)(pt 0 96)(line_width 1))
(text "STOP" (rect 24 0 52 12)(font "Arial" ))
(text "STOP" (rect 148 280 176 292)(font "Arial" ))
(line (pt 200 288)(pt 184 288)(line_width 1))
)
(port
(pt 200 272)
(output)
(text "RESET_OUT" (rect 24 0 87 12)(font "Arial" ))
(text "RESET_OUT" (rect 113 264 176 276)(font "Arial" ))
(line (pt 200 272)(pt 184 272)(line_width 1))
)
(drawing
(rectangle (rect 16 16 152 384)(line_width 1))
(rectangle (rect 16 16 184 448)(line_width 1))
)
)
(symbol
(rect 1000 -24 1256 88)
(text "altsyncram1" (rect 93 1 176 17)(font "Arial" (font_size 10)))
(text "File_Registers" (rect 8 96 78 108)(font "Arial" ))
(rect 888 48 936 112)
(text "AND2" (rect 0 39 10 63)(font "Arial" (font_size 6))(vertical))
(text "inst8" (rect 37 38 49 61)(font "Arial" )(vertical))
(port
(pt 0 32)
(pt 16 64)
(input)
(text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 4 19 57 33)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 112 32)(line_width 3))
(text "IN1" (rect 2 7 19 19)(font "Courier New" (bold))(invisible))
(text "IN1" (rect 7 45 19 62)(font "Courier New" (bold))(vertical)(invisible))
(line (pt 16 64)(pt 16 50)(line_width 1))
)
(port
(pt 0 48)
(pt 32 64)
(input)
(text "address[10..0]" (rect 0 0 82 14)(font "Arial" (font_size 8)))
(text "address[10..0]" (rect 4 35 86 49)(font "Arial" (font_size 8)))
(line (pt 0 48)(pt 112 48)(line_width 3))
(text "IN2" (rect 2 23 19 35)(font "Courier New" (bold))(invisible))
(text "IN2" (rect 23 45 35 62)(font "Courier New" (bold))(vertical)(invisible))
(line (pt 32 64)(pt 32 50)(line_width 1))
)
(port
(pt 0 64)
(input)
(text "wren" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "wren" (rect 4 51 34 65)(font "Arial" (font_size 8)))
(line (pt 0 64)(pt 112 64)(line_width 1))
)
(port
(pt 0 88)
(input)
(text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))
(text "clock" (rect 4 75 33 89)(font "Arial" (font_size 8)))
(line (pt 0 88)(pt 104 88)(line_width 1))
)
(port
(pt 256 32)
(pt 24 0)
(output)
(text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 223 19 258 33)(font "Arial" (font_size 8)))
(line (pt 256 32)(pt 168 32)(line_width 3))
(text "OUT" (rect 48 15 65 27)(font "Courier New" (bold))(invisible))
(text "OUT" (rect 15 -1 27 16)(font "Courier New" (bold))(vertical)(invisible))
(line (pt 24 22)(pt 24 0)(line_width 1))
)
(drawing
(text "2048 Word(s)" (rect 136 24 148 90)(font "Arial" )(vertical))
(text "RAM" (rect 149 42 161 65)(font "Arial" )(vertical))
(text "Block Type: AUTO" (rect 41 92 133 104)(font "Arial" ))
(line (pt 128 24)(pt 168 24)(line_width 1))
(line (pt 168 24)(pt 168 80)(line_width 1))
(line (pt 168 80)(pt 128 80)(line_width 1))
(line (pt 128 80)(pt 128 24)(line_width 1))
(line (pt 112 27)(pt 120 27)(line_width 1))
(line (pt 120 27)(pt 120 39)(line_width 1))
(line (pt 120 39)(pt 112 39)(line_width 1))
(line (pt 112 39)(pt 112 27)(line_width 1))
(line (pt 112 34)(pt 114 36)(line_width 1))
(line (pt 114 36)(pt 112 38)(line_width 1))
(line (pt 104 36)(pt 112 36)(line_width 1))
(line (pt 120 32)(pt 128 32)(line_width 3))
(line (pt 112 43)(pt 120 43)(line_width 1))
(line (pt 120 43)(pt 120 55)(line_width 1))
(line (pt 120 55)(pt 112 55)(line_width 1))
(line (pt 112 55)(pt 112 43)(line_width 1))
(line (pt 112 50)(pt 114 52)(line_width 1))
(line (pt 114 52)(pt 112 54)(line_width 1))
(line (pt 104 52)(pt 112 52)(line_width 1))
(line (pt 120 48)(pt 128 48)(line_width 3))
(line (pt 112 59)(pt 120 59)(line_width 1))
(line (pt 120 59)(pt 120 71)(line_width 1))
(line (pt 120 71)(pt 112 71)(line_width 1))
(line (pt 112 71)(pt 112 59)(line_width 1))
(line (pt 112 66)(pt 114 68)(line_width 1))
(line (pt 114 68)(pt 112 70)(line_width 1))
(line (pt 104 68)(pt 112 68)(line_width 1))
(line (pt 120 64)(pt 128 64)(line_width 1))
(line (pt 104 36)(pt 104 89)(line_width 1))
(line (pt 12 50)(pt 12 34)(line_width 1))
(line (pt 37 50)(pt 37 33)(line_width 1))
(line (pt 12 50)(pt 37 50)(line_width 1))
(arc (pt 37 33)(pt 12 34)(rect 12 21 37 46)(line_width 1))
)
(rotate90)
)
(symbol
(rect 608 -24 864 88)
(text "altsyncram2" (rect 168 0 251 16)(font "Arial" (font_size 10)))
(text "Program_Memory" (rect 8 100 95 112)(font "Arial" ))
(rect 1000 -24 1256 88)
(text "altsyncram1" (rect 168 0 251 16)(font "Arial" (font_size 10)))
(text "File_Registers" (rect 8 100 78 112)(font "Arial" ))
(port
(pt 0 80)
(input)
431,8 → 446,8
(port
(pt 0 64)
(input)
(text "address[13..0]" (rect 0 0 82 14)(font "Arial" (font_size 8)))
(text "address[13..0]" (rect 4 63 86 77)(font "Arial" (font_size 8)))
(text "address[10..0]" (rect 0 0 82 14)(font "Arial" (font_size 8)))
(text "address[10..0]" (rect 4 63 86 77)(font "Arial" (font_size 8)))
(line (pt 0 64)(pt 112 64)(line_width 3))
)
(port
457,7 → 472,7
(line (pt 256 80)(pt 168 80)(line_width 3))
)
(drawing
(text "16384 Word(s)" (rect 136 20 148 91)(font "Arial" )(vertical))
(text "2048 Word(s)" (rect 136 22 148 88)(font "Arial" )(vertical))
(text "RAM" (rect 149 47 161 70)(font "Arial" )(vertical))
(text "Block Type: AUTO" (rect 41 8 133 20)(font "Arial" ))
(line (pt 128 88)(pt 168 88)(line_width 1))
492,199 → 507,424
)
(flipx)
)
(symbol
(rect 984 240 1160 496)
(text "fpz8_timer" (rect 5 0 56 12)(font "Arial" ))
(text "inst3" (rect 8 240 31 252)(font "Arial" ))
(port
(pt 0 48)
(input)
(text "RAB[11..0]" (rect 0 0 54 12)(font "Arial" ))
(text "RAB[11..0]" (rect 21 40 75 52)(font "Arial" ))
(line (pt 0 48)(pt 16 48)(line_width 3))
)
(port
(pt 0 64)
(input)
(text "RIDB[7..0]" (rect 0 0 53 12)(font "Arial" ))
(text "RIDB[7..0]" (rect 21 56 74 68)(font "Arial" ))
(line (pt 0 64)(pt 16 64)(line_width 3))
)
(port
(pt 176 80)
(input)
(text "SIDB[7..0]" (rect 0 0 51 12)(font "Arial" ))
(text "SIDB[7..0]" (rect 101 72 152 84)(font "Arial" ))
(line (pt 160 80)(pt 176 80)(line_width 3))
)
(port
(pt 0 96)
(input)
(text "REG_SEL" (rect 0 0 49 12)(font "Arial" ))
(text "REG_SEL" (rect 21 88 70 100)(font "Arial" ))
(line (pt 0 96)(pt 16 96)(line_width 1))
)
(port
(pt 0 32)
(input)
(text "WR" (rect 0 0 18 12)(font "Arial" ))
(text "WR" (rect 21 24 39 36)(font "Arial" ))
(line (pt 0 32)(pt 16 32)(line_width 1))
)
(port
(pt 0 112)
(input)
(text "CLK_IN" (rect 0 0 38 12)(font "Arial" ))
(text "CLK_IN" (rect 21 104 59 116)(font "Arial" ))
(line (pt 0 112)(pt 16 112)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "STOP" (rect 0 0 28 12)(font "Arial" ))
(text "STOP" (rect 21 136 49 148)(font "Arial" ))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 176 216)
(input)
(text "TMR_IN" (rect 0 0 40 12)(font "Arial" ))
(text "TMR_IN" (rect 112 208 152 220)(font "Arial" ))
(line (pt 160 216)(pt 176 216)(line_width 1))
)
(port
(pt 176 32)
(input)
(text "TMR_ID[1..0]" (rect 0 0 66 12)(font "Arial" ))
(text "TMR_ID[1..0]" (rect 86 24 152 36)(font "Arial" ))
(line (pt 160 32)(pt 176 32)(line_width 3))
)
(port
(pt 0 128)
(input)
(text "RESET" (rect 0 0 35 12)(font "Arial" ))
(text "RESET" (rect 21 120 56 132)(font "Arial" ))
(line (pt 0 128)(pt 16 128)(line_width 1))
)
(port
(pt 0 80)
(output)
(text "RODB[7..0]" (rect 0 0 57 12)(font "Arial" ))
(text "RODB[7..0]" (rect 24 72 81 84)(font "Arial" ))
(line (pt 16 80)(pt 0 80)(line_width 3))
)
(port
(pt 0 216)
(output)
(text "INT" (rect 0 0 17 12)(font "Arial" ))
(text "INT" (rect 24 208 41 220)(font "Arial" ))
(line (pt 16 216)(pt 0 216)(line_width 1))
)
(port
(pt 176 200)
(output)
(text "TMR_OUT" (rect 0 0 50 12)(font "Arial" ))
(text "TMR_OUT" (rect 105 195 155 207)(font "Arial" ))
(line (pt 176 200)(pt 160 200)(line_width 1))
)
(drawing
(rectangle (rect 16 16 160 232)(line_width 1))
)
)
(symbol
(rect 1184 280 1216 312)
(text "GND" (rect 8 16 29 26)(font "Arial" (font_size 6)))
(text "inst4" (rect 3 21 26 33)(font "Arial" )(invisible))
(port
(pt 16 0)
(output)
(text "1" (rect 18 0 23 12)(font "Courier New" (bold))(invisible))
(text "1" (rect 18 0 23 12)(font "Courier New" (bold))(invisible))
(line (pt 16 8)(pt 16 0)(line_width 1))
)
(drawing
(line (pt 8 8)(pt 16 16)(line_width 1))
(line (pt 16 16)(pt 24 8)(line_width 1))
(line (pt 8 8)(pt 24 8)(line_width 1))
)
)
(connector
(pt 280 72)
(pt 208 72)
)
(connector
(pt 280 88)
(pt 208 88)
)
(connector
(pt 216 472)
(pt 280 472)
(bus)
)
(connector
(pt 280 168)
(pt 216 168)
)
(connector
(pt 280 184)
(pt 208 184)
)
(connector
(pt 1000 0)
(pt 984 0)
)
(connector
(pt 984 0)
(pt 984 -48)
)
(connector
(pt 984 -48)
(pt 504 -48)
)
(connector
(pt 504 72)
(pt 480 72)
)
(connector
(pt 608 0)
(pt 504 0)
)
(connector
(pt 504 -48)
(pt 504 0)
)
(connector
(pt 504 0)
(pt 504 72)
)
(connector
(pt 480 120)
(pt 880 120)
(bus)
)
(connector
(pt 880 120)
(pt 880 56)
(bus)
)
(connector
(pt 880 56)
(pt 864 56)
(bus)
)
(connector
(pt 584 -40)
(pt 888 -40)
(pt 480 136)
(pt 584 136)
)
(connector
(pt 584 -40)
(pt 584 0)
(pt 584 136)
(pt 584 24)
)
(connector
(pt 968 112)
(pt 928 112)
(pt 608 24)
(pt 584 24)
)
(connector
(pt 888 -40)
(pt 888 64)
(pt 480 104)
(pt 552 104)
(bus)
)
(connector
(pt 928 112)
(pt 928 40)
(pt 552 104)
(pt 552 56)
(bus)
)
(connector
(pt 1328 8)
(pt 1256 8)
(pt 608 56)
(pt 552 56)
(bus)
)
(connector
(pt 904 8)
(pt 904 168)
(pt 536 88)
(pt 536 40)
(bus)
)
(connector
(pt 904 8)
(pt 1000 8)
(text "IAB[15..0]" (rect 480 72 529 84)(font "Arial" ))
(pt 480 88)
(pt 536 88)
(bus)
)
(connector
(text "MAB[10..0]" (rect 936 8 990 20)(font "Arial" ))
(pt 920 24)
(pt 1000 24)
(text "IAB[13..0]" (rect 530 24 579 36)(font "Arial" ))
(pt 608 40)
(pt 536 40)
(bus)
)
(connector
(pt 928 40)
(pt 1000 40)
(pt 480 216)
(pt 904 216)
)
(connector
(pt 888 64)
(pt 1000 64)
(pt 904 216)
(pt 904 112)
)
(connector
(pt 232 120)
(pt 280 120)
(pt 480 232)
(pt 920 232)
)
(connector
(pt 256 0)
(pt 584 0)
(pt 1000 24)
(pt 912 24)
)
(connector
(pt 584 0)
(pt 608 0)
(pt 912 24)
(pt 912 48)
)
(connector
(pt 448 104)
(pt 880 104)
(pt 480 184)
(pt 992 184)
(bus)
)
(connector
(pt 880 104)
(pt 880 56)
(pt 992 184)
(pt 992 56)
(bus)
)
(connector
(pt 448 88)
(pt 592 88)
(pt 992 56)
(pt 1000 56)
(bus)
)
(connector
(pt 592 88)
(pt 592 56)
(text "FRAB[10..0]" (rect 930 24 991 36)(font "Arial" ))
(pt 1000 40)
(pt 976 40)
(bus)
)
(connector
(pt 592 56)
(pt 608 56)
(pt 976 40)
(pt 976 168)
(bus)
)
(connector
(pt 504 40)
(pt 504 72)
(pt 480 200)
(pt 1272 200)
(bus)
)
(connector
(pt 448 120)
(pt 568 120)
(pt 1272 200)
(pt 1272 56)
(bus)
)
(connector
(pt 568 120)
(pt 568 24)
(pt 1272 56)
(pt 1256 56)
(bus)
)
(connector
(pt 568 24)
(pt 608 24)
(pt 480 248)
(pt 872 248)
(bus)
)
(connector
(text "IAB[13..0]" (rect 514 24 563 36)(font "Arial" ))
(pt 608 40)
(pt 504 40)
(pt 480 264)
(pt 856 264)
(bus)
)
(connector
(pt 1032 120)
(pt 1048 120)
(pt 480 280)
(pt 840 280)
)
(connector
(pt 448 248)
(pt 1048 248)
(pt 480 296)
(pt 824 296)
)
(connector
(pt 1328 8)
(pt 1328 184)
(pt 480 312)
(pt 808 312)
)
(connector
(pt 480 328)
(pt 792 328)
)
(connector
(pt 776 360)
(pt 480 360)
)
(connector
(pt 888 168)
(pt 888 288)
(bus)
)
(connector
(pt 920 24)
(pt 920 152)
(pt 872 248)
(pt 872 304)
(bus)
)
(connector
(pt 448 168)
(pt 904 168)
(pt 856 264)
(pt 856 320)
(bus)
)
(connector
(pt 448 184)
(pt 1328 184)
(pt 840 280)
(pt 840 336)
)
(connector
(pt 824 296)
(pt 824 352)
)
(connector
(pt 808 312)
(pt 808 368)
)
(connector
(pt 792 328)
(pt 792 384)
)
(connector
(pt 920 112)
(pt 920 232)
)
(connector
(pt 920 232)
(pt 920 272)
)
(connector
(text "FRAB[11..0]" (rect 490 152 551 164)(font "Arial" ))
(pt 480 168)
(pt 888 168)
(bus)
)
(connector
(pt 1032 104)
(pt 1064 104)
(pt 888 168)
(pt 976 168)
(bus)
)
(connector
(pt 448 264)
(pt 1064 264)
(pt 888 288)
(pt 984 288)
(bus)
)
(connector
(pt 216 408)
(pt 280 408)
(pt 872 304)
(pt 984 304)
(bus)
)
(connector
(pt 232 168)
(pt 280 168)
(pt 840 336)
(pt 984 336)
)
(connector
(pt 232 184)
(pt 280 184)
(pt 920 272)
(pt 984 272)
)
(connector
(pt 232 104)
(pt 280 104)
(pt 824 352)
(pt 984 352)
)
(connector
(pt 280 72)
(pt 256 72)
(pt 792 384)
(pt 984 384)
)
(connector
(pt 256 72)
(pt 256 0)
(pt 808 368)
(pt 984 368)
)
(connector
(pt 1048 120)
(pt 1048 248)
(pt 856 320)
(pt 984 320)
(bus)
)
(connector
(pt 1064 104)
(pt 1064 264)
(pt 984 456)
(pt 776 456)
)
(connector
(text "MAB[11..0]" (rect 458 136 512 148)(font "Arial" ))
(pt 448 152)
(pt 920 152)
(pt 776 360)
(pt 776 456)
)
(connector
(pt 1200 272)
(pt 1160 272)
(bus)
)
(connector
(text "IAB[15..0]" (rect 458 56 507 68)(font "Arial" ))
(pt 504 72)
(pt 448 72)
(pt 1200 272)
(pt 1200 280)
(bus)
)
(junction (pt 584 0))
(junction (pt 504 0))
(junction (pt 920 232))
(junction (pt 888 168))
/FPz8.qpf
18,12 → 18,12
#
# Quartus II
# Version 9.1 Build 350 03/24/2010 Service Pack 2 SJ Web Edition
# Date created = 09:51:04 November 11, 2016
# Date created = 18:30:06 November 12, 2016
#
# -------------------------------------------------------------------------- #
 
QUARTUS_VERSION = "9.1"
DATE = "09:51:04 November 11, 2016"
DATE = "18:30:06 November 12, 2016"
 
# Revisions
 
/FPz8_Cyclone_IV.asm.rpt
1,5 → 1,5
Assembler report for FPz8_Cyclone_IV
Fri Nov 11 10:25:02 2016
Fri Nov 25 10:11:56 2016
Quartus II Version 9.1 Build 350 03/24/2010 Service Pack 2 SJ Web Edition
 
 
38,7 → 38,7
+---------------------------------------------------------------+
; Assembler Summary ;
+-----------------------+---------------------------------------+
; Assembler Status ; Successful - Fri Nov 11 10:25:02 2016 ;
; Assembler Status ; Successful - Fri Nov 25 10:11:56 2016 ;
; Revision Name ; FPz8_Cyclone_IV ;
; Top-level Entity Name ; CPU ;
; Family ; Cyclone IV E ;
95,7 → 95,7
+----------------+-------------------------------------------+
; Device ; EP4CE6E22C8 ;
; JTAG usercode ; 0xFFFFFFFF ;
; Checksum ; 0x003E6EEA ;
; Checksum ; 0x00400465 ;
+----------------+-------------------------------------------+
 
 
106,7 → 106,7
+--------------------+---------------------------------------+
; Device ; EPCS4 ;
; JTAG usercode ; 0x00000000 ;
; Checksum ; 0x06290CB3 ;
; Checksum ; 0x061C943C ;
; Compression Ratio ; 2 ;
+--------------------+---------------------------------------+
 
117,14 → 117,14
Info: *******************************************************************
Info: Running Quartus II Assembler
Info: Version 9.1 Build 350 03/24/2010 Service Pack 2 SJ Web Edition
Info: Processing started: Fri Nov 11 10:25:00 2016
Info: Processing started: Fri Nov 25 10:11:52 2016
Info: Command: quartus_asm --read_settings_files=off --write_settings_files=off FPz8 -c FPz8_Cyclone_IV
Info: Writing out detailed assembly data for power analysis
Info: Assembler is generating device programming files
Info: Quartus II Assembler was successful. 0 errors, 0 warnings
Info: Peak virtual memory: 202 megabytes
Info: Processing ended: Fri Nov 11 10:25:02 2016
Info: Elapsed time: 00:00:02
Info: Total CPU time (on all processors): 00:00:02
Info: Processing ended: Fri Nov 25 10:11:56 2016
Info: Elapsed time: 00:00:04
Info: Total CPU time (on all processors): 00:00:03
 
 
/FPz8_Cyclone_IV.done
1,14 → 117,14
Fri Nov 11 10:25:15 2016
Fri Nov 25 10:12:13 2016
/FPz8_Cyclone_IV.flow.rpt
1,5 → 1,5
Flow report for FPz8_Cyclone_IV
Fri Nov 11 10:25:14 2016
Fri Nov 25 10:12:12 2016
Quartus II Version 9.1 Build 350 03/24/2010 Service Pack 2 SJ Web Edition
 
 
38,7 → 38,7
+-----------------------------------------------------------------------------------+
; Flow Summary ;
+------------------------------------+----------------------------------------------+
; Flow Status ; Successful - Fri Nov 11 10:25:02 2016 ;
; Flow Status ; Successful - Fri Nov 25 10:11:56 2016 ;
; Quartus II Version ; 9.1 Build 350 03/24/2010 SP 2 SJ Web Edition ;
; Revision Name ; FPz8_Cyclone_IV ;
; Top-level Entity Name ; CPU ;
46,10 → 46,10
; Device ; EP4CE6E22C8 ;
; Timing Models ; Preliminary ;
; Met timing requirements ; N/A ;
; Total logic elements ; 4,884 / 6,272 ( 78 % ) ;
; Total combinational functions ; 4,854 / 6,272 ( 77 % ) ;
; Dedicated logic registers ; 494 / 6,272 ( 8 % ) ;
; Total registers ; 494 ;
; Total logic elements ; 5,009 / 6,272 ( 80 % ) ;
; Total combinational functions ; 4,952 / 6,272 ( 79 % ) ;
; Dedicated logic registers ; 584 / 6,272 ( 9 % ) ;
; Total registers ; 584 ;
; Total pins ; 12 / 92 ( 13 % ) ;
; Total virtual pins ; 0 ;
; Total memory bits ; 147,456 / 276,480 ( 53 % ) ;
63,7 → 63,7
+-------------------+---------------------+
; Option ; Setting ;
+-------------------+---------------------+
; Start date & time ; 11/11/2016 10:21:52 ;
; Start date & time ; 11/25/2016 10:08:19 ;
; Main task ; Compilation ;
; Revision Name ; FPz8_Cyclone_IV ;
+-------------------+---------------------+
75,7 → 75,7
; Assignment Name ; Value ; Default Value ; Entity Name ; Section Id ;
+------------------------------------+------------------------------------------------------------------+------------------------------+-------------+----------------+
; ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ; On ; Off ; -- ; -- ;
; COMPILER_SIGNATURE_ID ; 8796753254599.147886691203264 ; -- ; -- ; -- ;
; COMPILER_SIGNATURE_ID ; 8796753254599.148007569904036 ; -- ; -- ; -- ;
; FITTER_EFFORT ; Standard Fit ; Auto Fit ; -- ; -- ;
; INCREMENTAL_COMPILATION ; Off ; FULL_INCREMENTAL_COMPILATION ; -- ; -- ;
; IP_TOOL_NAME ; ALTSYNCRAM ; -- ; -- ; -- ;
108,11 → 108,11
+---------------------------+--------------+-------------------------+---------------------+------------------------------------+
; Module Name ; Elapsed Time ; Average Processors Used ; Peak Virtual Memory ; Total CPU Time (on all processors) ;
+---------------------------+--------------+-------------------------+---------------------+------------------------------------+
; Analysis & Synthesis ; 00:02:22 ; 1.0 ; 266 MB ; 00:02:19 ;
; Fitter ; 00:00:42 ; 1.0 ; 310 MB ; 00:00:41 ;
; TimeQuest Timing Analyzer ; 00:00:15 ; 1.0 ; 258 MB ; 00:00:11 ;
; Assembler ; 00:00:03 ; 1.0 ; 202 MB ; 00:00:02 ;
; Total ; 00:03:19 ; -- ; -- ; 00:03:11 ;
; Analysis & Synthesis ; 00:02:34 ; 1.0 ; 267 MB ; 00:02:30 ;
; Fitter ; 00:00:55 ; 1.0 ; 311 MB ; 00:00:54 ;
; TimeQuest Timing Analyzer ; 00:00:20 ; 1.0 ; 259 MB ; 00:00:16 ;
; Assembler ; 00:00:04 ; 1.0 ; 202 MB ; 00:00:03 ;
; Total ; 00:03:49 ; -- ; -- ; 00:03:40 ;
+---------------------------+--------------+-------------------------+---------------------+------------------------------------+
 
 
/FPz8_Cyclone_IV.map.summary
1,12 → 1,12
Analysis & Synthesis Status : Successful - Fri Nov 11 10:24:13 2016
Analysis & Synthesis Status : Successful - Fri Nov 25 10:10:51 2016
Quartus II Version : 9.1 Build 350 03/24/2010 SP 2 SJ Web Edition
Revision Name : FPz8_Cyclone_IV
Top-level Entity Name : CPU
Family : Cyclone IV E
Total logic elements : 4,886
Total combinational functions : 4,854
Dedicated logic registers : 494
Total registers : 494
Total logic elements : 5,021
Total combinational functions : 4,952
Dedicated logic registers : 584
Total registers : 584
Total pins : 12
Total virtual pins : 0
Total memory bits : 147,456
/FPz8_Cyclone_IV.pof Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/FPz8_Cyclone_IV.qsf
84,4 → 84,5
set_global_assignment -name SOURCE_FILE altsyncram1.cmp
set_global_assignment -name VHDL_FILE altsyncram1.vhd
set_global_assignment -name SOURCE_FILE altsyncram2.cmp
set_global_assignment -name VHDL_FILE altsyncram2.vhd
set_global_assignment -name VHDL_FILE altsyncram2.vhd
set_global_assignment -name VHDL_FILE fpz8_timer.vhd
/FPz8_Cyclone_IV.sof Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/README.md
1,21 → 1,27
# FPz8 - An open-source VHDL implementation of the Zilog Z8 encore
 
FPz8 is a softcore 100% object code compatible with the Z8 encore microcontroller line. Current implementation includes 2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority, full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
FPz8 mk1 v0.99
 
It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA board used on the project).
Version: 0.99 Nov, 24th, 2016 (changed LDWX instruction, interrupts, condition code function, debugger command processor)
Version: 0.91 Nov, 15th, 2016
Version: 0.9 Nov, 11th, 2016
 
FPz8 is a softcore almost 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes
2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority,
full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera
Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA
board used on the project).
In a near future I plan to add some more features to the device (such as a timer and maybe other peripherals).
The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using these technologies). I also
believe FPz8 can be a very interesting tool for learning/teaching VHDL, computing and microprocessors/microcontrollers
programming.
 
The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using those technologies). I also believe the FPz8 can be a very interesting tool for learning/teaching about VHDL, computing and microprocessors/microcontrollers programming.
 
You are free to use and to modify the FPz8 to fit your needs, except for comercial use (I don't expect anyone would do that anyway). If you want to contribute to the project, contact me and share your thoughts.
 
You are free to use and to modify FPz8 to fit your needs, except for comercial use (I don't expect anyone would do that anyway).
If you want to contribute to the project, contact me and share your thoughts.
Don't forget to credit the author!
 
Fábio Pereira
 
Note: currently there are only a few SFRs physically implemented, they are:
 
0xFC0 - IRQ0
0xFC1 - IRQ0ENH
0xFC2 - IRQ0ENL
28,5 → 34,12
0xFFE - SPH
0xFFF - SPL
 
What else is missing from the original architecture?
A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes,
no data memory related debug commands, no CRC debug command, no ID bytes
 
FPz8 was tested on an EP4CE6 mini board (50MHz clock)
http://www.ebay.com/itm/EP4CE6-Mini-Board-USB-Blaster-Altera-Cyclone-IV-FPGA-CPLD-Nano-Size-
 
This work is licensed under the Creative Commons Attribution 4.0 International License.
To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.
/altsyncram1.bsf
20,14 → 20,14
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 256 112)
(text "altsyncram1" (rect 93 1 176 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 96 25 108)(font "Arial" ))
(rect 64 64 320 176)
(text "altsyncram1" (rect 168 96 251 112)(font "Arial" (font_size 10)))
(text "inst" (rect 8 0 25 12)(font "Arial" ))
(port
(pt 0 32)
(input)
(text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 4 19 49 32)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 4 19 57 33)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 112 32)(line_width 3))
)
(port
34,7 → 34,7
(pt 0 48)
(input)
(text "address[10..0]" (rect 0 0 82 14)(font "Arial" (font_size 8)))
(text "address[10..0]" (rect 4 35 69 48)(font "Arial" (font_size 8)))
(text "address[10..0]" (rect 4 35 86 49)(font "Arial" (font_size 8)))
(line (pt 0 48)(pt 112 48)(line_width 3))
)
(port
41,7 → 41,7
(pt 0 64)
(input)
(text "wren" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "wren" (rect 4 51 26 64)(font "Arial" (font_size 8)))
(text "wren" (rect 4 51 34 65)(font "Arial" (font_size 8)))
(line (pt 0 64)(pt 112 64)(line_width 1))
)
(port
48,7 → 48,7
(pt 0 88)
(input)
(text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))
(text "clock" (rect 4 75 27 88)(font "Arial" (font_size 8)))
(text "clock" (rect 4 75 33 89)(font "Arial" (font_size 8)))
(line (pt 0 88)(pt 104 88)(line_width 1))
)
(port
55,13 → 55,13
(pt 256 32)
(output)
(text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 223 19 253 32)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 223 19 258 33)(font "Arial" (font_size 8)))
(line (pt 256 32)(pt 168 32)(line_width 3))
)
(drawing
(text "2048 Word(s)" (rect 136 24 148 80)(font "Arial" )(vertical))
(text "RAM" (rect 149 42 161 62)(font "Arial" )(vertical))
(text "Block Type: AUTO" (rect 41 92 119 104)(font "Arial" ))
(text "2048 Word(s)" (rect 136 24 148 90)(font "Arial" )(vertical))
(text "RAM" (rect 149 42 161 65)(font "Arial" )(vertical))
(text "Block Type: AUTO" (rect 41 92 133 104)(font "Arial" ))
(line (pt 128 24)(pt 168 24)(line_width 1))
(line (pt 168 24)(pt 168 80)(line_width 1))
(line (pt 168 80)(pt 128 80)(line_width 1))
/fpz8_cpu_v1.bsf
0,0 → 1,239
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2010 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 64 64 264 536)
(text "fpz8_cpu_v1" (rect 5 0 68 12)(font "Arial" ))
(text "inst" (rect 8 456 25 468)(font "Arial" ))
(port
(pt 200 80)
(input)
(text "IDB[7..0]" (rect 0 0 44 12)(font "Arial" ))
(text "IDB[7..0]" (rect 132 72 176 84)(font "Arial" ))
(line (pt 184 80)(pt 200 80)(line_width 3))
)
(port
(pt 200 160)
(input)
(text "FRIDB[7..0]" (rect 0 0 60 12)(font "Arial" ))
(text "FRIDB[7..0]" (rect 116 152 176 164)(font "Arial" ))
(line (pt 184 160)(pt 200 160)(line_width 3))
)
(port
(pt 200 224)
(input)
(text "RIDB[7..0]" (rect 0 0 53 12)(font "Arial" ))
(text "RIDB[7..0]" (rect 123 216 176 228)(font "Arial" ))
(line (pt 184 224)(pt 200 224)(line_width 3))
)
(port
(pt 200 432)
(input)
(text "INT0" (rect 0 0 23 12)(font "Arial" ))
(text "INT0" (rect 153 424 176 436)(font "Arial" ))
(line (pt 184 432)(pt 200 432)(line_width 1))
)
(port
(pt 200 416)
(input)
(text "INT1" (rect 0 0 23 12)(font "Arial" ))
(text "INT1" (rect 153 408 176 420)(font "Arial" ))
(line (pt 184 416)(pt 200 416)(line_width 1))
)
(port
(pt 200 400)
(input)
(text "INT2" (rect 0 0 23 12)(font "Arial" ))
(text "INT2" (rect 153 392 176 404)(font "Arial" ))
(line (pt 184 400)(pt 200 400)(line_width 1))
)
(port
(pt 200 384)
(input)
(text "INT3" (rect 0 0 23 12)(font "Arial" ))
(text "INT3" (rect 153 376 176 388)(font "Arial" ))
(line (pt 184 384)(pt 200 384)(line_width 1))
)
(port
(pt 200 368)
(input)
(text "INT4" (rect 0 0 23 12)(font "Arial" ))
(text "INT4" (rect 153 360 176 372)(font "Arial" ))
(line (pt 184 368)(pt 200 368)(line_width 1))
)
(port
(pt 200 352)
(input)
(text "INT5" (rect 0 0 23 12)(font "Arial" ))
(text "INT5" (rect 153 344 176 356)(font "Arial" ))
(line (pt 184 352)(pt 200 352)(line_width 1))
)
(port
(pt 200 336)
(input)
(text "INT6" (rect 0 0 23 12)(font "Arial" ))
(text "INT6" (rect 153 328 176 340)(font "Arial" ))
(line (pt 184 336)(pt 200 336)(line_width 1))
)
(port
(pt 200 320)
(input)
(text "INT7" (rect 0 0 23 12)(font "Arial" ))
(text "INT7" (rect 153 312 176 324)(font "Arial" ))
(line (pt 184 320)(pt 200 320)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "DBG_RX" (rect 0 0 43 12)(font "Arial" ))
(text "DBG_RX" (rect 21 139 64 151)(font "Arial" ))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 0 416)
(input)
(text "PAIN[7..0]" (rect 0 0 51 12)(font "Arial" ))
(text "PAIN[7..0]" (rect 21 411 72 423)(font "Arial" ))
(line (pt 0 416)(pt 16 416)(line_width 3))
)
(port
(pt 0 32)
(input)
(text "CLK" (rect 0 0 21 12)(font "Arial" ))
(text "CLK" (rect 21 27 42 39)(font "Arial" ))
(line (pt 0 32)(pt 16 32)(line_width 1))
)
(port
(pt 0 48)
(input)
(text "RESET" (rect 0 0 35 12)(font "Arial" ))
(text "RESET" (rect 21 43 56 55)(font "Arial" ))
(line (pt 0 48)(pt 16 48)(line_width 1))
)
(port
(pt 200 48)
(output)
(text "IAB[15..0]" (rect 24 0 73 12)(font "Arial" ))
(text "IAB[15..0]" (rect 127 40 176 52)(font "Arial" ))
(line (pt 200 48)(pt 184 48)(line_width 3))
)
(port
(pt 200 64)
(output)
(text "IWDB[7..0]" (rect 24 0 79 12)(font "Arial" ))
(text "IWDB[7..0]" (rect 121 56 176 68)(font "Arial" ))
(line (pt 200 64)(pt 184 64)(line_width 3))
)
(port
(pt 200 128)
(output)
(text "FRAB[11..0]" (rect 24 0 85 12)(font "Arial" ))
(text "FRAB[11..0]" (rect 115 120 176 132)(font "Arial" ))
(line (pt 200 128)(pt 184 128)(line_width 3))
)
(port
(pt 200 144)
(output)
(text "FRODB[7..0]" (rect 24 0 88 12)(font "Arial" ))
(text "FRODB[7..0]" (rect 112 136 176 148)(font "Arial" ))
(line (pt 200 144)(pt 184 144)(line_width 3))
)
(port
(pt 200 208)
(output)
(text "RODB[7..0]" (rect 24 0 81 12)(font "Arial" ))
(text "RODB[7..0]" (rect 119 200 176 212)(font "Arial" ))
(line (pt 200 208)(pt 184 208)(line_width 3))
)
(port
(pt 200 96)
(output)
(text "PGM_WR" (rect 24 0 72 12)(font "Arial" ))
(text "PGM_WR" (rect 128 88 176 100)(font "Arial" ))
(line (pt 200 96)(pt 184 96)(line_width 1))
)
(port
(pt 200 192)
(output)
(text "WR" (rect 24 0 42 12)(font "Arial" ))
(text "WR" (rect 158 184 176 196)(font "Arial" ))
(line (pt 200 192)(pt 184 192)(line_width 1))
)
(port
(pt 200 240)
(output)
(text "REG_SEL" (rect 24 0 73 12)(font "Arial" ))
(text "REG_SEL" (rect 127 232 176 244)(font "Arial" ))
(line (pt 200 240)(pt 184 240)(line_width 1))
)
(port
(pt 200 176)
(output)
(text "MEM_SEL" (rect 24 0 73 12)(font "Arial" ))
(text "MEM_SEL" (rect 127 168 176 180)(font "Arial" ))
(line (pt 200 176)(pt 184 176)(line_width 1))
)
(port
(pt 0 128)
(output)
(text "DBG_TX" (rect 24 0 65 12)(font "Arial" ))
(text "DBG_TX" (rect 24 120 65 132)(font "Arial" ))
(line (pt 16 128)(pt 0 128)(line_width 1))
)
(port
(pt 0 432)
(output)
(text "PAOUT[7..0]" (rect 24 0 86 12)(font "Arial" ))
(text "PAOUT[7..0]" (rect 24 424 86 436)(font "Arial" ))
(line (pt 16 432)(pt 0 432)(line_width 3))
)
(port
(pt 200 256)
(output)
(text "CLK_OUT" (rect 24 0 73 12)(font "Arial" ))
(text "CLK_OUT" (rect 127 248 176 260)(font "Arial" ))
(line (pt 200 256)(pt 184 256)(line_width 1))
)
(port
(pt 200 32)
(output)
(text "CLK_OUTN" (rect 24 0 81 12)(font "Arial" ))
(text "CLK_OUTN" (rect 119 24 176 36)(font "Arial" ))
(line (pt 200 32)(pt 184 32)(line_width 1))
)
(port
(pt 200 288)
(output)
(text "STOP" (rect 24 0 52 12)(font "Arial" ))
(text "STOP" (rect 148 280 176 292)(font "Arial" ))
(line (pt 200 288)(pt 184 288)(line_width 1))
)
(port
(pt 200 272)
(output)
(text "RESET_OUT" (rect 24 0 87 12)(font "Arial" ))
(text "RESET_OUT" (rect 113 264 176 276)(font "Arial" ))
(line (pt 200 272)(pt 184 272)(line_width 1))
)
(drawing
(rectangle (rect 16 16 184 448)(line_width 1))
)
)
/fpz8_cpu_v1.vhd
1,9 → 1,11
-- FPz8 mk1
-- FPz8 mk1 v0.99
-- Zilog Z8 Encore! 100% compatible softcore
 
-- Version: 0.99 Nov, 24th, 2016 (changed LDWX instruction, interrupts, condition code function, debugger command processor)
-- Version: 0.91 Nov, 15th, 2016
-- Version: 0.9 Nov, 11th, 2016
 
-- FPz8 is a softcore 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes
-- FPz8 is a softcore almost 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes
-- 2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority,
-- full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
-- It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera
10,8 → 12,8
-- Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA
-- board used on the project).
-- In a near future I plan to add some more features to the device (such as a timer and maybe other peripherals).
-- The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using those technologies). I also
-- believe the FPz8 can be a very interesting tool for learning/teaching about VHDL, computing and microprocessors/microcontrollers
-- The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using these technologies). I also
-- believe FPz8 can be a very interesting tool for learning/teaching VHDL, computing and microprocessors/microcontrollers
-- programming.
 
-- You are free to use and to modify FPz8 to fit your needs, except for comercial use (I don't expect anyone would do that anyway).
30,12 → 32,12
-- 0xFFD - RP
-- 0xFFE - SPH
-- 0xFFF - SPL
-- Also notice INT7 is not physically present as it is planned to be used with the coming timer peripheral
 
-- What else is missing from the original architecture?
-- A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes
-- A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes,
-- no data memory related debug commands, no CRC debug command, no ID bytes
 
-- FPz8 was tested on a EP4CE6 mini board (50MHz clock)
-- FPz8 was tested on an EP4CE6 mini board (50MHz clock)
-- http://www.ebay.com/itm/EP4CE6-Mini-Board-USB-Blaster-Altera-Cyclone-IV-FPGA-CPLD-Nano-Size-
 
-- This work is licensed under the Creative Commons Attribution 4.0 International License.
51,10 → 53,10
(
IAB : buffer std_logic_vector(15 downto 0); -- instruction address bus (16 bits)
IDB : in std_logic_vector(7 downto 0); -- instruction data bus (8 bits)
PWDB : out std_logic_vector(7 downto 0); -- program write data bus (8 bits)
MAB : buffer std_logic_vector(11 downto 0); -- memory address bus (12 bits)
MIDB : in std_logic_vector(7 downto 0); -- memory input data bus (8 bits)
MODB : out std_logic_vector(7 downto 0); -- memory output data bus (8 bits)
IWDB : out std_logic_vector(7 downto 0); -- instruction write data bus (8 bits)
FRAB : buffer std_logic_vector(11 downto 0); -- file register address bus (12 bits)
FRIDB : in std_logic_vector(7 downto 0); -- memory input data bus (8 bits)
FRODB : out std_logic_vector(7 downto 0); -- memory output data bus (8 bits)
RIDB : in std_logic_vector(7 downto 0); -- register input data bus (8 bits)
RODB : out std_logic_vector(7 downto 0); -- register output data bus (8 bits)
PGM_WR : out std_logic; -- program memory write enable
68,14 → 70,16
INT4 : in std_logic; -- interrupt 4 input (vector 0x000E)
INT5 : in std_logic; -- interrupt 5 input (vector 0x000C)
INT6 : in std_logic; -- interrupt 6 input (vector 0x000A)
INT7 : in std_logic; -- interrupt 7 input (vector 0x0008)
DBG_RX : in std_logic; -- debugger receive input
DBG_TX : buffer std_logic; -- debugger transmit output
PAOUT : out std_logic_vector(7 downto 0); -- port A output data
PAIN : in std_logic_vector(7 downto 0); -- port A input data
CLK : in std_logic; -- main clock
CLK_OUT : out std_logic; -- main gated-clock output
CLK_OUTN : out std_logic; -- main inverted-gated-clock output
CLK_OUT : buffer std_logic; -- main clock output
CLK_OUTN : out std_logic; -- main inverted clock output
STOP : buffer std_logic; -- stop output
RESET_OUT : out std_logic; -- reset output
RESET : in std_logic -- CPU reset
);
end fpz8_cpu_v1;
88,9 → 92,7
end record;
shared variable CPU_FLAGS, ALU_FLAGS : Tflags;
shared variable ALU_NOUPDATE : std_logic;
shared variable INT7 : std_logic;
shared variable IRQE : std_logic;
shared variable HALT : std_logic;
shared variable IRQ0 : std_logic_vector(7 downto 0); -- interrupts 0-7 flags
shared variable IRQ0ENH,IRQ0ENL : std_logic_vector(7 downto 0); -- interrupts 0-7 enable high and low
shared variable SP : std_logic_vector(11 downto 0); -- stack pointer
101,6 → 103,8
ATTRIBUTE preserve : boolean;
ATTRIBUTE preserve OF RXSYNC1 : signal IS true;
ATTRIBUTE preserve OF RXSYNC2 : signal IS true;
signal IRQ0_LATCH : std_logic_vector(7 downto 0); -- current state of IRQ inputs
attribute preserve of IRQ0_LATCH : signal is true;
 
constant ALU_ADD : std_logic_vector(3 downto 0):=x"0"; -- CZSVH D=0
constant ALU_ADC : std_logic_vector(3 downto 0):=x"1"; -- CZSVH D=0
178,13 → 182,13
elsif (ADDRESS=x"FD3") then ---------------------------------------------------- PAOUT register
PAOUT <= DATA;
PAOUT_BUFFER := DATA;
else
REG_SEL <= '1';
RODB <= DATA;
else -- if it is not an internal SFR but ADDRESS>=0xF00 then it is an external register
REG_SEL <= '1'; -- enable external register select
RODB <= DATA; -- output data on register output data bus
end if;
else
MEM_SEL <= '1';
MODB <= DATA;
else -- if ADDRESS < 0xF00 then it is a RAM register
MEM_SEL <= '1'; -- enable external memory select
FRODB <= DATA; -- output data on file register output data bus
end if;
end datawrite;
 
213,7 → 217,7
end if;
else
MEM_SEL <= '1';
return MIDB;
return FRIDB;
end if;
end DATAREAD;
 
225,35 → 229,35
when x"0" =>
return '0';
when x"1" =>
return ALU_FLAGS.S xor ALU_FLAGS.V;
return CPU_FLAGS.S xor CPU_FLAGS.V;
when x"2" =>
return ALU_FLAGS.Z or (ALU_FLAGS.S xor ALU_FLAGS.V);
return CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V);
when x"3" =>
return ALU_FLAGS.C or ALU_FLAGS.Z;
return CPU_FLAGS.C or CPU_FLAGS.Z;
when x"4" =>
return ALU_FLAGS.V;
return CPU_FLAGS.V;
when x"5" =>
return ALU_FLAGS.S;
return CPU_FLAGS.S;
when x"6" =>
return ALU_FLAGS.Z;
return CPU_FLAGS.Z;
when x"7" =>
return ALU_FLAGS.C;
return CPU_FLAGS.C;
when x"8" =>
return '1';
when x"9" =>
return NOT (ALU_FLAGS.S xor ALU_FLAGS.V);
return NOT (CPU_FLAGS.S xor CPU_FLAGS.V);
when x"A" =>
return NOT (ALU_FLAGS.Z or (ALU_FLAGS.S xor ALU_FLAGS.V));
return NOT (CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V));
when x"B" =>
return (NOT ALU_FLAGS.C) AND (NOT ALU_FLAGS.Z);
return (NOT CPU_FLAGS.C) AND (NOT CPU_FLAGS.Z);
when x"C" =>
return NOT ALU_FLAGS.V;
return NOT CPU_FLAGS.V;
when x"D" =>
return NOT ALU_FLAGS.S;
return NOT CPU_FLAGS.S;
when x"E" =>
return NOT ALU_FLAGS.Z;
return NOT CPU_FLAGS.Z;
when others =>
return NOT ALU_FLAGS.C;
return NOT CPU_FLAGS.C;
end case;
end CONDITIONCODE;
279,7 → 283,7
end if;
end ADDRESSER8;
 
-- ADDRESSER12 generates a 12-bit address from a 4-bit address (using RP register)
-- ADDRESSER4 generates a 12-bit address from a 4-bit address (using RP register)
function ADDRESSER4
( ADDR : in std_logic_vector(3 downto 0)) return std_logic_vector is
begin
464,25 → 468,37
end ADDER16;
 
begin
clock_out: process(CLK)
clock_out: process(CLK,RESET)
variable CKDIVIDER : integer range 0 to 2;
begin
CLK_OUTN <= not CLK;
CLK_OUT <= CLK;
end process;
if (RESET='1') then
CKDIVIDER := 0;
CLK_OUTN <= '1';
CLK_OUT <= '0';
elsif (rising_edge(CLK)) then
CLK_OUTN <= '1';
CLK_OUT <= '0';
CKDIVIDER := CKDIVIDER + 1;
if (CKDIVIDER=0) then -- main clock (50MHz) is divided by 3, resulting in a 16.66MHz system clock
CLK_OUT <= '1';
CLK_OUTN <= '0';
end if;
end if;
end process; -- clock_out process
-- main process controls debugging and instruction fetching and decoding along
main: process (CLK,RESET,DBG_RX)
main: process (CLK_OUT,RESET,DBG_RX)
-- CPU state machine
type Tcpu_state is (
CPU_DECOD,
CPU_INDRR,
CPU_MUL, CPU_MUL1, CPU_MUL2,
CPU_XADTOM,
CPU_MTOXAD, CPU_MTOXAD2,
CPU_XRTOM,
CPU_XRRTORR, CPU_XRRTORR2,
CPU_INDRR, -- indirect rr mode
CPU_MUL, CPU_MUL1, CPU_MUL2, -- MUL instruction
CPU_XADTOM, -- address with offset to memory
CPU_MTOXAD, CPU_MTOXAD2, -- memory to address with offset
CPU_XRTOM, -- register with offset to memory
CPU_XRRTORR, CPU_XRRTORR2, -- register pair with offset to register pair
CPU_XRRTORR3, CPU_XRRTORR4,
CPU_IMTOIRR, CPU_MTOIRR, -- indirect and direct to indirect register pair addressing mode
CPU_IRRS, CPU_IRRS2,
CPU_IRRS, CPU_IRRS2, -- indirect register pair as source
CPU_XRRD, CPU_XRRD2, CPU_XRRD3, -- indexed rr pair as destination
CPU_XRRS, CPU_XRRS2, CPU_XRRS3, -- indexed rr pair as source
CPU_IND1, CPU_IND2, -- indirect memory access
491,26 → 507,26
CPU_OMA, -- One memory access instructions (immediate to/with register)
CPU_OMA2, -- One memory access instructions (immediate to/with register) logic unit related
CPU_DMAB, -- Decrement address bus (for word access)
CPU_LDW, CPU_LDW2,
CPU_LDPTOIM, CPU_LDPTOIM2,
CPU_LDPTOM, CPU_LDPTOM2,
CPU_LDPTOM3, CPU_LDPTOM4,
CPU_LDMTOP, CPU_LDMTOP2,
CPU_BIT,
CPU_IBTJ, CPU_BTJ,
CPU_DJNZ,
CPU_INDJUMP, CPU_INDJUMP2,
CPU_TRAP, CPU_TRAP2,
CPU_INDSTACK, CPU_INDSTACK2,
CPU_STACK, CPU_STACK1,
CPU_LDW, CPU_LDW2, CPU_LDW3, -- load word instruction
CPU_LDW4, CPU_LDW5,
CPU_LDPTOIM, CPU_LDPTOIM2, -- load program to indirect memory
CPU_LDPTOM, CPU_LDPTOM2, -- load program to memory
CPU_LDPTOM3, CPU_LDPTOM4,
CPU_LDMTOP, CPU_LDMTOP2, -- load memory to program
CPU_BIT, -- BIT instruction
CPU_IBTJ, CPU_BTJ, -- BTJ instruction
CPU_DJNZ, -- DJNZ instruction
CPU_INDJUMP, CPU_INDJUMP2, -- indirect JP
CPU_TRAP, CPU_TRAP2, -- TRAP instruction
CPU_INDSTACK, CPU_INDSTACK2, -- indirect stacking
CPU_STACK, CPU_STACK1, -- stacking operations
CPU_STACK2, CPU_STACK3,
CPU_UNSTACK, CPU_UNSTACK2,
CPU_UNSTACK3,
CPU_UNSTACK, CPU_UNSTACK2, -- unstacking operations
CPU_UNSTACK3,
CPU_STORE, -- store results, no change to the flags
CPU_VECTOR, CPU_VECTOR2,
CPU_HALTED,
CPU_RESET,
CPU_ILLEGAL
CPU_VECTOR, CPU_VECTOR2, -- vectoring stages
CPU_RESET, -- reset state
CPU_ILLEGAL -- illegal state
);
type Tfetch_state is (
F_ADDR, -- instruction queue is initializing, reset pointers and empty queue
578,19 → 594,20
variable DBG_CMD : Tdbg_command;
variable CAN_FETCH : std_logic; -- controls whether the instruction queue can actually fetch opcodes
variable LU_INSTRUCTION : std_logic; -- indicates a LU2-related instruction
variable INT_FLAG : std_logic; -- indicates an interrupt
variable WORD_DATA : std_logic; -- indicates a 16-bit data instruction
variable HALT : std_logic; -- indicates the CPU is halted
variable PC : std_logic_vector(15 downto 0); -- program counter
variable FETCH_ADDR : std_logic_vector(15 downto 0); -- next address to be fetched
variable DEST_ADDR16 : std_logic_vector(15 downto 0); -- temporary 16-bit destination address
variable DEST_ADDR : std_logic_vector(11 downto 0); -- temporary 12-bit destination address
variable TEMP_DATA : std_logic_vector(7 downto 0); -- temporary 8-bit data
variable OLD_IRQ0 : std_logic_vector(7 downto 0); -- previous state of IRQs
variable OLD_IRQ0 : std_logic_vector(7 downto 0); -- previous state of IRQ inputs
variable INTVECT : std_logic_vector(7 downto 0); -- current interrupt vector (lower 8-bits)
variable RESULT : std_logic_vector(7 downto 0); -- temporary 8-bit result
variable TEMP_OP : std_logic_vector(3 downto 0); -- ALU/LU2 operation code
variable ATM_COUNTER : integer range 0 to 3; -- temporary interrupt disable counter (ATM instruction)
variable NUM_BYTES : integer range 0 to 5; -- number of bytes decoded
variable CKDIVIDER : integer range 0 to 2;
type Tinstructionqueue is record
WRPOS : integer range 0 to 7; -- instruction queue write pointer
RDPOS : integer range 0 to 7; -- instruction queue read pointer
614,10 → 631,11
variable OCD : Tocdflags;
begin
if (reset='1') then -- reset operations
RESET_OUT <= RESET or OCDCR.RST;
if (RESET='1') then -- reset operations
IAB <= x"0002";
MAB <= x"000";
PWDB <= x"00";
FRAB <= x"000";
IWDB <= x"00";
SP := x"000";
RP := x"00";
WR <= '0';
643,266 → 661,277
IRQ0ENH := x"00";
IRQ0ENL := x"00";
ATM_COUNTER := 0;
CKDIVIDER := 0;
CPU_STATE := CPU_VECTOR;
elsif (rising_edge(clk)) then
if (OLD_IRQ0(0)='0' and INT0='1') then IRQ0(0) := '1'; end if;
if (OLD_IRQ0(1)='0' and INT1='1') then IRQ0(1) := '1'; end if;
if (OLD_IRQ0(2)='0' and INT2='1') then IRQ0(2) := '1'; end if;
if (OLD_IRQ0(3)='0' and INT3='1') then IRQ0(3) := '1'; end if;
if (OLD_IRQ0(4)='0' and INT4='1') then IRQ0(4) := '1'; end if;
if (OLD_IRQ0(5)='0' and INT5='1') then IRQ0(5) := '1'; end if;
if (OLD_IRQ0(6)='0' and INT6='1') then IRQ0(6) := '1'; end if;
OLD_IRQ0 := INT7&INT6&INT5&INT4&INT3&INT2&INT1&INT0;
CKDIVIDER := CKDIVIDER + 1;
if (CKDIVIDER=0) then -- main clock (50MHz) is divided by 3, resulting in a 16.66MHz system clock
WR <= '0';
PGM_WR <= '0';
-- This is the instruction queue FSM
if (CAN_FETCH='1') then
if (IQUEUE.FETCH_STATE=F_ADDR) then
FETCH_ADDR := PC;
IAB <= PC;
IQUEUE.WRPOS := 0;
IQUEUE.RDPOS := 0;
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_READ;
else
if (IQUEUE.FULL='0') then
IQUEUE.QUEUE(IQUEUE.WRPOS) := IDB;
FETCH_ADDR := FETCH_ADDR + 1;
IAB <= FETCH_ADDR;
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
IQUEUE.CNT := IQUEUE.CNT + 1;
end if;
elsif (rising_edge(CLK_OUT)) then
IRQ0_LATCH <= INT7&INT6&INT5&INT4&INT3&INT2&INT1&INT0;
if (OLD_IRQ0(0)/=IRQ0_LATCH(0)) then IRQ0(0) := '1'; end if;
if (OLD_IRQ0(1)/=IRQ0_LATCH(1)) then IRQ0(1) := '1'; end if;
if (OLD_IRQ0(2)/=IRQ0_LATCH(2)) then IRQ0(2) := '1'; end if;
if (OLD_IRQ0(3)/=IRQ0_LATCH(3)) then IRQ0(3) := '1'; end if;
if (OLD_IRQ0(4)/=IRQ0_LATCH(4)) then IRQ0(4) := '1'; end if;
if (OLD_IRQ0(5)/=IRQ0_LATCH(5)) then IRQ0(5) := '1'; end if;
if (OLD_IRQ0(6)/=IRQ0_LATCH(6)) then IRQ0(6) := '1'; end if;
if (OLD_IRQ0(7)/=IRQ0_LATCH(7)) then IRQ0(7) := '1'; end if;
OLD_IRQ0 := IRQ0_LATCH;
WR <= '0';
PGM_WR <= '0';
-- start of instruction queue FSM
if (CAN_FETCH='1') then
if (IQUEUE.FETCH_STATE=F_ADDR) then
FETCH_ADDR := PC;
IAB <= PC;
IQUEUE.WRPOS := 0;
IQUEUE.RDPOS := 0;
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_READ;
else
if (IQUEUE.FULL='0') then
IQUEUE.QUEUE(IQUEUE.WRPOS) := IDB;
FETCH_ADDR := FETCH_ADDR + 1;
IAB <= FETCH_ADDR;
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
IQUEUE.CNT := IQUEUE.CNT + 1;
end if;
end if;
if (IQUEUE.CNT=7) then IQUEUE.FULL:='1'; else IQUEUE.FULL:='0';
end if;
-- This is the end of instruction queue FSM
-- These are the Debugger FSMs
DBG_UART.BAUDPRE := DBG_UART.BAUDPRE+1;
if (DBG_UART.BAUDPRE=0) then
DBG_UART.BAUDCNTRX := DBG_UART.BAUDCNTRX+1;
DBG_UART.BAUDCNTTX := DBG_UART.BAUDCNTTX+1;
end if;
RXSYNC2 <= DBG_RX;
RXSYNC1 <= RXSYNC2;
case DBG_UART.RX_STATE is
when DBGST_NOSYNC =>
DBG_UART.DBG_SYNC := '0';
DBG_UART.RX_DONE := '0';
DBG_CMD := DBG_WAIT_CMD;
DBG_UART.RX_STATE := DBGST_WAITSTART;
when DBGST_WAITSTART =>
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then
DBG_UART.RX_STATE := DBGST_MEASURING;
DBG_UART.BAUDCNTRX := x"000";
end if;
if (IQUEUE.CNT=7) then IQUEUE.FULL:='1'; else IQUEUE.FULL:='0';
end if;
-- end of instruction queue FSM
-- start of debugger UART
DBG_UART.BAUDPRE := DBG_UART.BAUDPRE+1; -- baudrate prescaler
if (DBG_UART.BAUDPRE=0) then
DBG_UART.BAUDCNTRX := DBG_UART.BAUDCNTRX+1;
DBG_UART.BAUDCNTTX := DBG_UART.BAUDCNTTX+1;
end if;
RXSYNC2 <= DBG_RX; -- DBG_RX input synchronization
RXSYNC1 <= RXSYNC2; -- RXSYNC1 is a synchronized DBG_RX signal
case DBG_UART.RX_STATE is
when DBGST_NOSYNC =>
DBG_UART.DBG_SYNC := '0';
DBG_UART.RX_DONE := '0';
DBG_CMD := DBG_WAIT_CMD;
DBG_UART.RX_STATE := DBGST_WAITSTART;
when DBGST_WAITSTART =>
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then
DBG_UART.RX_STATE := DBGST_MEASURING;
DBG_UART.BAUDCNTRX := x"000";
end if;
when DBGST_MEASURING =>
if (DBG_UART.BAUDCNTRX/=x"FFF") then
if (RXSYNC1='1') then
DBG_UART.DBG_SYNC := '1';
DBG_UART.RX_STATE := DBGST_IDLE;
DBG_UART.BITTIMERX := "0000"&DBG_UART.BAUDCNTRX(11 downto 4);
DBG_UART.BITTIMETX := "000"&DBG_UART.BAUDCNTRX(11 downto 3);
end if;
when DBGST_MEASURING =>
if (DBG_UART.BAUDCNTRX/=x"FFF") then
if (RXSYNC1='1') then
DBG_UART.DBG_SYNC := '1';
DBG_UART.RX_STATE := DBGST_IDLE;
DBG_UART.BITTIMERX := "0000"&DBG_UART.BAUDCNTRX(11 downto 4);
DBG_UART.BITTIMETX := "000"&DBG_UART.BAUDCNTRX(11 downto 3);
end if;
else
DBG_UART.RX_STATE := DBGST_NOSYNC;
end if;
when DBGST_IDLE =>
DBG_UART.BAUDCNTRX:=x"000";
DBG_UART.RXCNT:=0;
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then -- it's a start bit
DBG_UART.RX_STATE := DBGST_START;
end if;
when DBGST_START =>
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMERX) then
DBG_UART.BAUDCNTRX:=x"000";
if (RXSYNC1='0') then
DBG_UART.RX_STATE := DBGST_RECEIVING;
else
DBG_UART.RX_STATE := DBGST_NOSYNC;
DBG_UART.RX_STATE := DBGST_ERROR;
DBG_UART.TX_STATE := DBGTX_BREAK;
end if;
when DBGST_IDLE =>
end if;
when DBGST_RECEIVING =>
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTRX:=x"000";
DBG_UART.RXCNT:=0;
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then -- it's a start bit
DBG_UART.RX_STATE := DBGST_START;
end if;
when DBGST_START =>
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMERX) then
DBG_UART.BAUDCNTRX:=x"000";
if (RXSYNC1='0') then
DBG_UART.RX_STATE := DBGST_RECEIVING;
-- one bit time elapsed, sample RX input
DBG_UART.RXSHIFTREG := RXSYNC1 & DBG_UART.RXSHIFTREG(8 downto 1);
DBG_UART.RXCNT := DBG_UART.RXCNT + 1;
if (DBG_UART.RXCNT=9) then
if (RXSYNC1='1') then
-- if the stop bit is 1, rx is completed ok
DBG_UART.RX_DATA := DBG_UART.RXSHIFTREG(7 downto 0);
DBG_UART.RX_DONE := '1';
DBG_UART.RX_STATE := DBGST_IDLE;
else
-- if the stop bit is 0, it is a break char, reset receiver
DBG_UART.RX_STATE := DBGST_ERROR;
DBG_UART.TX_STATE := DBGTX_BREAK;
end if;
end if;
when DBGST_RECEIVING =>
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTRX:=x"000";
-- one bit time elapsed, sample RX input
DBG_UART.RXSHIFTREG := RXSYNC1 & DBG_UART.RXSHIFTREG(8 downto 1);
DBG_UART.RXCNT := DBG_UART.RXCNT + 1;
if (DBG_UART.RXCNT=9) then
if (RXSYNC1='1') then
-- if the stop bit is 1, rx is completed ok
DBG_UART.RX_DATA := DBG_UART.RXSHIFTREG(7 downto 0);
DBG_UART.RX_DONE := '1';
DBG_UART.RX_STATE := DBGST_IDLE;
else
-- if the stop bit is 0, it is a break char, reset receiver
DBG_UART.RX_STATE := DBGST_ERROR;
DBG_UART.TX_STATE := DBGTX_BREAK;
end if;
end if;
end if;
when others =>
end case;
DBG_UART.LAST_SMP := RXSYNC1;
case DBG_UART.TX_STATE is
when DBGTX_INIT =>
DBG_UART.TX_EMPTY := '1';
DBG_UART.TX_STATE:=DBGTX_IDLE;
when DBGTX_IDLE => -- UART is idle and not transmitting
DBG_TX <= '1';
if (DBG_UART.TX_EMPTY='0' and DBG_UART.DBG_SYNC='1') then -- there is new data in TX_DATA register
DBG_UART.BAUDCNTTX:=x"000";
DBG_UART.TX_STATE := DBGTX_START;
end if;
when DBGTX_START =>
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTTX:=x"000";
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TX_DATA;
DBG_UART.TXCNT := 10;
DBG_UART.TX_STATE := DBGTX_TRASMITTING;
DBG_TX <= '0';
end if;
when DBGTX_TRASMITTING => -- UART is shifting data
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTTX:=x"000";
DBG_TX <= DBG_UART.TXSHIFTREG(0);
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TXSHIFTREG(8 downto 1);
DBG_UART.TXCNT :=DBG_UART.TXCNT - 1;
if (DBG_UART.TXCNT=0) then
DBG_UART.TX_STATE:=DBGTX_IDLE;
DBG_UART.TX_EMPTY := '1';
end if;
end if;
when DBGTX_BREAK =>
end if;
when others =>
end case;
DBG_UART.LAST_SMP := RXSYNC1;
case DBG_UART.TX_STATE is
when DBGTX_INIT =>
DBG_UART.TX_EMPTY := '1';
DBG_UART.TX_STATE:=DBGTX_IDLE;
when DBGTX_IDLE => -- UART is idle and not transmitting
DBG_TX <= '1';
if (DBG_UART.TX_EMPTY='0' and DBG_UART.DBG_SYNC='1') then -- there is new data in TX_DATA register
DBG_UART.BAUDCNTTX:=x"000";
DBG_UART.TX_STATE:=DBGTX_BREAK2;
when DBGTX_BREAK2 =>
DBG_UART.TX_STATE := DBGTX_START;
end if;
when DBGTX_START =>
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTTX:=x"000";
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TX_DATA;
DBG_UART.TXCNT := 10;
DBG_UART.TX_STATE := DBGTX_TRASMITTING;
DBG_TX <= '0';
DBG_UART.RX_STATE := DBGST_NOSYNC;
if (DBG_UART.BAUDCNTTX=x"FFF") then
DBG_UART.TX_STATE:=DBGTX_INIT;
end if;
when DBGTX_TRASMITTING => -- UART is shifting data
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
DBG_UART.BAUDCNTTX:=x"000";
DBG_TX <= DBG_UART.TXSHIFTREG(0);
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TXSHIFTREG(8 downto 1);
DBG_UART.TXCNT :=DBG_UART.TXCNT - 1;
if (DBG_UART.TXCNT=0) then
DBG_UART.TX_STATE:=DBGTX_IDLE;
DBG_UART.TX_EMPTY := '1';
end if;
end case;
if (RXSYNC1='0') then DBG_TX <='0';
end if;
case DBG_CMD is
when DBG_WAIT_CMD =>
if (DBG_UART.RX_DONE='1') then
case DBG_UART.RX_DATA is
when DBGCMD_READ_REV => DBG_CMD := DBG_SEND_REV;
when DBGCMD_READ_STATUS => DBG_CMD := DBG_SEND_STATUS;
when DBGCMD_WRITE_CTRL => DBG_CMD := DBG_WRITE_CTRL;
when DBGCMD_READ_CTRL => DBG_CMD := DBG_SEND_CTRL;
when DBGCMD_WRITE_PC => DBG_CMD := DBG_WRITE_PC;
when DBGCMD_READ_PC => DBG_CMD := DBG_SEND_PC;
when DBGCMD_WRITE_REG => DBG_CMD := DBG_WRITE_REG;
when DBGCMD_READ_REG => DBG_CMD := DBG_READ_REG;
when DBGCMD_WRITE_PROGRAM=> DBG_CMD := DBG_WRITE_PROGMEM;
when DBGCMD_READ_PROGRAM=> DBG_CMD := DBG_READ_PROGMEM;
when DBGCMD_STEP => DBG_CMD := DBG_STEP;
when DBGCMD_STUFF => DBG_CMD := DBG_STUFF;
when DBGCMD_EXEC => DBG_CMD := DBG_EXEC;
when others =>
end case;
DBG_UART.RX_DONE:='0';
end if;
when DBG_SEND_REV =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"01";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_SEND_REV2;
end if;
when DBG_SEND_REV2 =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"00";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_STATUS =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=OCDCR.DBGMODE&HALT&"000000";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_CTRL =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.RX_DONE:='0';
OCDCR.DBGMODE := DBG_UART.RX_DATA(7);
OCDCR.BRKEN := DBG_UART.RX_DATA(6);
OCDCR.DBGACK := DBG_UART.RX_DATA(5);
OCDCR.BRKLOOP := DBG_UART.RX_DATA(4);
OCDCR.RST := DBG_UART.RX_DATA(0);
if (OCDCR.RST='1') then CPU_STATE:=CPU_RESET;
end if;
when DBGTX_BREAK =>
DBG_UART.BAUDCNTTX:=x"000";
DBG_UART.TX_STATE:=DBGTX_BREAK2;
when DBGTX_BREAK2 =>
DBG_TX <= '0';
DBG_UART.RX_STATE := DBGST_NOSYNC;
if (DBG_UART.BAUDCNTTX=x"FFF") then
DBG_UART.TX_STATE:=DBGTX_INIT;
end if;
end case;
if (RXSYNC1='0') then DBG_TX <='0'; -- this mimics open-collector feature of OCD communication
end if;
-- end of the debugger UART
-- This is the instruction decoder
case CPU_STATE IS
when CPU_DECOD =>
TEMP_OP := ALU_LD; -- default ALU operation is load
LU_INSTRUCTION := '0'; -- default is ALU operation (instead of LU2)
INT_FLAG := '0'; -- reset temporary interrupt flag
WORD_DATA := '0'; -- default is 8-bit operation
INTVECT := x"00"; -- default vector is 0x00
NUM_BYTES := 0; -- default instruction length is 0 bytes
-- start of debugger command processor
case DBG_CMD is
when DBG_WAIT_CMD =>
if (DBG_UART.RX_DONE='1') then
case DBG_UART.RX_DATA is
when DBGCMD_READ_REV => DBG_CMD := DBG_SEND_REV;
when DBGCMD_READ_STATUS => DBG_CMD := DBG_SEND_STATUS;
when DBGCMD_WRITE_CTRL => DBG_CMD := DBG_WRITE_CTRL;
when DBGCMD_READ_CTRL => DBG_CMD := DBG_SEND_CTRL;
when DBGCMD_WRITE_PC => DBG_CMD := DBG_WRITE_PC;
when DBGCMD_READ_PC => DBG_CMD := DBG_SEND_PC;
when DBGCMD_WRITE_REG => DBG_CMD := DBG_WRITE_REG;
when DBGCMD_READ_REG => DBG_CMD := DBG_READ_REG;
when DBGCMD_WRITE_PROGRAM=> DBG_CMD := DBG_WRITE_PROGMEM;
when DBGCMD_READ_PROGRAM=> DBG_CMD := DBG_READ_PROGMEM;
when DBGCMD_STEP => DBG_CMD := DBG_STEP;
when DBGCMD_STUFF => DBG_CMD := DBG_STUFF;
when DBGCMD_EXEC => DBG_CMD := DBG_EXEC;
when others =>
end case;
DBG_UART.RX_DONE:='0';
end if;
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_CTRL =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=OCDCR.DBGMODE&OCDCR.BRKEN&OCDCR.DBGACK&OCDCR.BRKLOOP&"000"&OCDCR.RST;
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_PC =>
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
DBG_UART.RX_DONE:='0';
CAN_FETCH := '0';
PC(15 downto 8) := DBG_UART.RX_DATA;
DBG_CMD := DBG_WRITE_PC2;
end if;
when DBG_WRITE_PC2 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.RX_DONE:='0';
PC(7 downto 0) := DBG_UART.RX_DATA;
IQUEUE.FETCH_STATE := F_ADDR;
IQUEUE.CNT := 0;
CAN_FETCH := '1';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_PC =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=PC(15 downto 8);
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_SEND_PC2;
end if;
when DBG_SEND_PC2 =>
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=PC(7 downto 0);
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_REG =>
DBG_UART.WRT := '1';
DBG_CMD := DBG_REG;
when DBG_READ_REG =>
DBG_UART.WRT := '0';
DBG_CMD := DBG_REG;
when DBG_REG =>
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
CAN_FETCH := '0';
MAB(11 downto 8) <= DBG_UART.RX_DATA(3 downto 0);
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG2;
end if;
when DBG_REG2 =>
if (DBG_UART.RX_DONE='1') then
MAB(7 downto 0) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG3;
end if;
when DBG_REG3 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE := x"00"&DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG4;
end if;
when DBG_REG4 =>
if (OCDCR.DBGMODE='1') then
when DBG_SEND_REV => -- read revision first byte
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"01";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_SEND_REV2;
end if;
when DBG_SEND_REV2 => -- read revision second byte
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"00";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_STATUS => -- read OCD status
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=OCDCR.DBGMODE&HALT&"000000";
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_CTRL => -- write OCD control register
if (DBG_UART.RX_DONE='1') then
DBG_UART.RX_DONE:='0';
OCDCR.DBGMODE := DBG_UART.RX_DATA(7);
OCDCR.BRKEN := DBG_UART.RX_DATA(6);
OCDCR.DBGACK := DBG_UART.RX_DATA(5);
OCDCR.BRKLOOP := DBG_UART.RX_DATA(4);
OCDCR.RST := DBG_UART.RX_DATA(0);
if (OCDCR.RST='1') then CPU_STATE:=CPU_RESET;
end if;
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_CTRL => -- read OCD control register
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=OCDCR.DBGMODE&OCDCR.BRKEN&OCDCR.DBGACK&OCDCR.BRKLOOP&"000"&OCDCR.RST;
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_PC => -- write PC high byte
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
DBG_UART.RX_DONE:='0';
CAN_FETCH := '0';
PC(15 downto 8) := DBG_UART.RX_DATA;
DBG_CMD := DBG_WRITE_PC2;
end if;
when DBG_WRITE_PC2 => -- write PC low byte
if (DBG_UART.RX_DONE='1') then
DBG_UART.RX_DONE:='0';
PC(7 downto 0) := DBG_UART.RX_DATA;
IQUEUE.FETCH_STATE := F_ADDR;
IQUEUE.CNT := 0;
CAN_FETCH := '1';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_SEND_PC => -- read PC high byte
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=PC(15 downto 8);
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_SEND_PC2;
end if;
when DBG_SEND_PC2 => -- read PC high byte
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=PC(7 downto 0);
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_WAIT_CMD;
end if;
when DBG_WRITE_REG => -- write to SFR/user registers
DBG_UART.WRT := '1';
DBG_CMD := DBG_REG;
when DBG_READ_REG => -- read SFR/user registers
DBG_UART.WRT := '0';
DBG_CMD := DBG_REG;
when DBG_REG => -- proceed with register read/write
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
FRAB(11 downto 8) <= DBG_UART.RX_DATA(3 downto 0);
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG2;
end if;
when DBG_REG2 =>
if (DBG_UART.RX_DONE='1') then
FRAB(7 downto 0) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG3;
end if;
when DBG_REG3 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE := x"00"&DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_REG4;
end if;
when DBG_REG4 =>
if (DBG_UART.WRT='1') then
if (DBG_UART.RX_DONE='1') then
CPU_STATE := CPU_OMA;
912,129 → 941,116
end if;
else
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=DATAREAD(MAB);
DBG_UART.TX_DATA:=DATAREAD(FRAB);
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_REG5;
end if;
end if;
end if;
when DBG_REG5 =>
if (CPU_STATE=CPU_DECOD) then
MAB <= MAB + 1;
when DBG_REG5 =>
FRAB <= FRAB + 1;
DBG_UART.SIZE := DBG_UART.SIZE - 1;
if (DBG_UART.SIZE=x"0000") then
DBG_CMD := DBG_WAIT_CMD;
CAN_FETCH := '1';
else DBG_CMD := DBG_REG4;
end if;
end if;
when DBG_WRITE_PROGMEM =>
DBG_UART.WRT := '1';
DBG_CMD := DBG_PROGMEM;
when DBG_READ_PROGMEM =>
DBG_UART.WRT := '0';
DBG_CMD := DBG_PROGMEM;
when DBG_PROGMEM =>
if (DBG_UART.RX_DONE='1') then
CAN_FETCH := '0';
IAB(15 downto 8) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM2;
end if;
when DBG_PROGMEM2 =>
if (DBG_UART.RX_DONE='1') then
IAB(7 downto 0) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM3;
end if;
when DBG_PROGMEM3 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE(15 downto 8) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM4;
end if;
when DBG_PROGMEM4 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE(7 downto 0) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM5;
end if;
when DBG_PROGMEM5 =>
if (DBG_UART.WRT='1') then
when DBG_WRITE_PROGMEM =>
DBG_UART.WRT := '1';
DBG_CMD := DBG_PROGMEM;
when DBG_READ_PROGMEM =>
DBG_UART.WRT := '0';
DBG_CMD := DBG_PROGMEM;
when DBG_PROGMEM =>
if (DBG_UART.RX_DONE='1') then
PWDB <= DBG_UART.RX_DATA;
CAN_FETCH := '0';
IAB(15 downto 8) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
PGM_WR <= '1';
DBG_CMD := DBG_PROGMEM6;
DBG_CMD := DBG_PROGMEM2;
end if;
else
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=IDB;
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_PROGMEM6;
when DBG_PROGMEM2 =>
if (DBG_UART.RX_DONE='1') then
IAB(7 downto 0) <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM3;
end if;
when DBG_PROGMEM3 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE(15 downto 8) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM4;
end if;
when DBG_PROGMEM4 =>
if (DBG_UART.RX_DONE='1') then
DBG_UART.SIZE(7 downto 0) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_PROGMEM5;
end if;
end if;
when DBG_PROGMEM6 =>
IAB <= IAB + 1;
DBG_UART.SIZE := DBG_UART.SIZE - 1;
if (DBG_UART.SIZE=x"0000") then
DBG_CMD := DBG_WAIT_CMD;
CAN_FETCH := '1';
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_ADDR;
else DBG_CMD := DBG_PROGMEM5;
end if;
when DBG_STEP =>
OCD.SINGLESTEP:='1';
IQUEUE.FETCH_STATE := F_ADDR;
DBG_CMD := DBG_WAIT_CMD;
when DBG_STUFF =>
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
IQUEUE.QUEUE(IQUEUE.RDPOS) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
DBG_CMD := DBG_STEP;
end if;
when DBG_EXEC =>
if (OCDCR.DBGMODE='1') then
when DBG_PROGMEM5 =>
if (DBG_UART.WRT='1') then
if (DBG_UART.RX_DONE='1') then
IWDB <= DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
PGM_WR <= '1';
DBG_CMD := DBG_PROGMEM6;
end if;
else
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=IDB;
DBG_UART.TX_EMPTY:='0';
DBG_CMD := DBG_PROGMEM6;
end if;
end if;
when DBG_PROGMEM6 =>
IAB <= IAB + 1;
DBG_UART.SIZE := DBG_UART.SIZE - 1;
if (DBG_UART.SIZE=x"0000") then
DBG_CMD := DBG_WAIT_CMD;
CAN_FETCH := '1';
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_ADDR;
else DBG_CMD := DBG_PROGMEM5;
end if;
when DBG_STEP =>
OCD.SINGLESTEP:='1';
CAN_FETCH:='0';
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_ADDR;
end if;
DBG_CMD := DBG_EXEC2;
when DBG_EXEC2 =>
if (DBG_UART.RX_DONE='1') then
if (OCDCR.DBGMODE='0') then DBG_CMD := DBG_WAIT_CMD;
else
IQUEUE.QUEUE(IQUEUE.WRPOS) := DBG_UART.RX_DATA;
DBG_CMD := DBG_WAIT_CMD;
when DBG_STUFF =>
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
IQUEUE.QUEUE(IQUEUE.RDPOS) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
IQUEUE.CNT := IQUEUE.CNT + 1;
DBG_CMD := DBG_EXEC3;
DBG_CMD := DBG_STEP;
end if;
end if;
when DBG_EXEC3 =>
if (OCD.SINGLESTEP='1') then DBG_CMD := DBG_EXEC2; else
DBG_CMD := DBG_WAIT_CMD;
CAN_FETCH:='0';
IQUEUE.FETCH_STATE := F_ADDR;
end if;
when others =>
end case;
-- This is the end of the debugger code
-- This is the main instruction decoder
case CPU_STATE IS
when CPU_DECOD =>
TEMP_OP := ALU_LD; -- default ALU operation is load
LU_INSTRUCTION := '0'; -- default is ALU operation (instead of LU2)
WORD_DATA := '0'; -- default is 8-bit operation
INTVECT := x"00"; -- default vector is 0x00
NUM_BYTES := 0; -- default instruction length is 0 bytes
when DBG_EXEC =>
if (OCDCR.DBGMODE='1') then
OCD.SINGLESTEP:='1';
CAN_FETCH:='0';
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE := F_ADDR;
end if;
DBG_CMD := DBG_EXEC2;
when DBG_EXEC2 =>
if (DBG_UART.RX_DONE='1') then
if (OCDCR.DBGMODE='0') then DBG_CMD := DBG_WAIT_CMD;
else
IQUEUE.QUEUE(IQUEUE.WRPOS) := DBG_UART.RX_DATA;
DBG_UART.RX_DONE:='0';
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
IQUEUE.CNT := IQUEUE.CNT + 1;
DBG_CMD := DBG_EXEC3;
end if;
end if;
when DBG_EXEC3 =>
if (OCD.SINGLESTEP='1') then DBG_CMD := DBG_EXEC2; else
DBG_CMD := DBG_WAIT_CMD;
IQUEUE.FETCH_STATE := F_ADDR;
end if;
when others =>
end case;
-- end of debugger command processor
if (ATM_COUNTER/=3) then ATM_COUNTER := ATM_COUNTER+1;
else -- interrupt processing *****************************************************************************
if (IRQE='1') then -- if interrupts are enabled
-- first the highest priority interrupts
-- first the highest priority level interrupts
if ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='1') then
INTVECT:=x"08";
IRQ0(7):='0';
1111,744 → 1127,748
IRQ0(0):='0';
end if;
if (INTVECT/=x"00") then
DEST_ADDR16 := PC;
IAB <= x"00"&INTVECT; -- build the address of the interrupt vector
SP := SP - 1; -- prepare stack pointer by decrementing it
MAB <= SP; -- put SP on MAB
CAN_FETCH := '0'; -- disable instruction fetching
IQUEUE.CNT := 0; -- empty instruction queue
STOP <= '0'; -- disable stop bit
LU_INSTRUCTION := '1'; -- the stacking uses this bit to flag it is an interrupt stacking operation
CPU_STATE := CPU_STACK;
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
DEST_ADDR16 := PC;
IAB <= x"00"&INTVECT; -- build the interrupt vector address
SP := SP - 1; -- prepare stack pointer by decrementing it
FRAB <= SP; -- put SP on FRAB
CAN_FETCH := '0'; -- disable instruction fetching
OCD.SINGLESTEP := '0'; -- disable stepping
IQUEUE.CNT := 0; -- set queue empty
STOP <= '0'; -- disable stop bit
HALT := '0'; -- disable halt mode
INT_FLAG := '1'; -- signal it is an interrupt stacking operation
CPU_STATE := CPU_VECTOR;
end if;
end if;
end if;
end if;
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 5-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=5) then
---------------------------------------------------------------------------------------------------- 2nd page instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
---------------------------------------------------------------------------------------------- CPC ER2,ER1 instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A8") then
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
TEMP_OP := ALU_CPC;
NUM_BYTES := 5;
CPU_STATE := CPU_TMA;
---------------------------------------------------------------------------------------------- CPC IMM,ER1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A9") then
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := ALU_CPC;
NUM_BYTES := 5;
CPU_STATE := CPU_OMA;
--------------------------------------------------------------------------------------------- LDWX ER1,ER2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"E8") then
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
NUM_BYTES := 5;
CPU_STATE := CPU_LDW;
end if; -- if IRQE=1
end if; -- if ATM_COUNTER...
if (STOP='0' and HALT='0') then
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 5-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=5) then -- 5-byte instructions
---------------------------------------------------------------------------------------------------- 2nd page instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
---------------------------------------------------------------------------------------------- CPC ER2,ER1 instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A8") then
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
TEMP_OP := ALU_CPC;
NUM_BYTES := 5;
CPU_STATE := CPU_TMA;
---------------------------------------------------------------------------------------------- CPC IMM,ER1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A9") then
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := ALU_CPC;
NUM_BYTES := 5;
CPU_STATE := CPU_OMA;
--------------------------------------------------------------------------------------------- LDWX ER1,ER2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"E8") then
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
NUM_BYTES := 5;
CPU_STATE := CPU_LDW;
end if;
end if;
end if;
end if;
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 4-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=4) then
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then ------------------------------------------------ column 9 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX rr1,r2,X instruction
when x"9" => ------------------------------------------------------------------------ LEA rr1,rr2,X instruction
when x"C" =>
CPU_STATE := CPU_ILLEGAL;
when x"D" =>
CPU_STATE := CPU_ILLEGAL;
when x"F" =>
CPU_STATE := CPU_ILLEGAL;
when others => -------------------------------------------------------------- IM,ER1 addressing mode instructions
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 4-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=4) then -- 4-byte instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then ------------------------------------------------ column 9 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX rr1,r2,X instruction
when x"9" => ------------------------------------------------------------------------ LEA rr1,rr2,X instruction
when x"C" =>
CPU_STATE := CPU_ILLEGAL;
when x"D" =>
CPU_STATE := CPU_ILLEGAL;
when x"F" =>
CPU_STATE := CPU_ILLEGAL;
when others => -------------------------------------------------------------- IM,ER1 addressing mode instructions
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 4;
CPU_STATE := CPU_OMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX r1,rr2,X instruction
when x"9" => -------------------------------------------------------------------------- LEA r1,r2,X instruction
when x"C" => -------------------------------------------------------------------------------- PUSHX instruction
when x"D" => --------------------------------------------------------------------------------- POPX instruction
when x"F" =>
CPU_STATE := CPU_ILLEGAL;
when others => ------------------------------------------------------------- ER2,ER1 addressing mode instructions
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+1)) & IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 4;
CPU_STATE := CPU_TMA;
end case;
---------------------------------------------------------------------------------------------------- 2nd page instructions
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
------------------------------------------------------------------------------------------------ CPC R2,R1 instruction
TEMP_OP := ALU_CPC;
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A4") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 4;
CPU_STATE := CPU_OMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX r1,rr2,X instruction
when x"9" => -------------------------------------------------------------------------- LEA r1,r2,X instruction
when x"C" => -------------------------------------------------------------------------------- PUSHX instruction
when x"D" => --------------------------------------------------------------------------------- POPX instruction
when x"F" =>
CPU_STATE := CPU_ILLEGAL;
when others => ------------------------------------------------------------- ER2,ER1 addressing mode instructions
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+1)) & IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
CPU_STATE := CPU_TMA;
----------------------------------------------------------------------------------------------- CPC IR2,R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A5") then
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 4;
CPU_STATE := CPU_TMA;
end case;
---------------------------------------------------------------------------------------------------- 2nd page instructions
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
------------------------------------------------------------------------------------------------ CPC R2,R1 instruction
TEMP_OP := ALU_CPC;
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A4") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 4;
CPU_STATE := CPU_TMA;
----------------------------------------------------------------------------------------------- CPC IR2,R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A5") then
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 4;
CPU_STATE := CPU_ISMD1;
----------------------------------------------------------------------------------------------- CPC R1,IMM instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A6") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
NUM_BYTES := 4;
CPU_STATE := CPU_OMA;
---------------------------------------------------------------------------------------------- CPC IR1,IMM instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A7") then
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
NUM_BYTES := 4;
CPU_STATE := CPU_IND1;
CPU_STATE := CPU_ISMD1;
----------------------------------------------------------------------------------------------- CPC R1,IMM instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A6") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
NUM_BYTES := 4;
CPU_STATE := CPU_OMA;
---------------------------------------------------------------------------------------------- CPC IR1,IMM instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A7") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
NUM_BYTES := 4;
CPU_STATE := CPU_IND1;
end if;
end if;
end if;
end if;
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 3-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=3) then
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"D") then -------------------------------------------------- JP cc,DirectAddress
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
IQUEUE.FETCH_STATE := F_ADDR;
else
NUM_BYTES := 3;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then -------------------------------------------- column 9 instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX rr1,r2,X instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
NUM_BYTES := 3;
CPU_STATE := CPU_XRRD;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then ------------------------------------ LEA rr1,rr2,X instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_XRRTORR;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX r1,rr2,X instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
NUM_BYTES := 3;
CPU_STATE := CPU_XRRS;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then -------------------------------------- LEA r1,r2,X instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_XRTOM;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"C") then ---------------------------------------- PUSHX ER2 instruction
SP := SP - 1;
MAB <= ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
DEST_ADDR := SP;
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"D") then ----------------------------------------- POPX ER2 instruction
MAB <= SP;
DEST_ADDR := ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
SP := SP + 1;
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"7") then -------------------------------------------- column 7 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX IRR2,IR1 instruction
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 3-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=3) then -- 3-byte instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"D") then -------------------------------------------------- JP cc,DirectAddress
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
IQUEUE.FETCH_STATE := F_ADDR;
else
NUM_BYTES := 3;
CPU_STATE := CPU_IRRS;
when x"9" => ------------------------------------------------------------------------- LDX IR2,IRR1 instruction
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then -------------------------------------------- column 9 instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX rr1,r2,X instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
NUM_BYTES := 3;
CPU_STATE := CPU_IMTOIRR;
when x"C" => --------------------------------------------------------------------------- LD r1,r2,X instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
CPU_STATE := CPU_XRRD;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then ------------------------------------ LEA rr1,rr2,X instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_XRRTORR;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX r1,rr2,X instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
NUM_BYTES := 3;
CPU_STATE := CPU_XADTOM;
when x"D" => --------------------------------------------------------------------------- LD r2,r1,X instruction
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
CPU_STATE := CPU_XRRS;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then -------------------------------------- LEA r1,r2,X instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_MTOXAD;
when x"F" => ------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
when others => ----------------------------------------------------------------------------- IR1,imm instructions
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
CPU_STATE := CPU_XRTOM;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"C") then ---------------------------------------- PUSHX ER2 instruction
SP := SP - 1;
FRAB <= ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
DEST_ADDR := SP;
NUM_BYTES := 3;
CPU_STATE := CPU_IND1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"6") then -------------------------------------------- column 6 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDX IRR2,R1 instruction
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
CPU_STATE := CPU_TMA;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"D") then ----------------------------------------- POPX ER2 instruction
FRAB <= SP;
DEST_ADDR := ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
SP := SP + 1;
NUM_BYTES := 3;
LU_INSTRUCTION := '1'; -- in this mode this flag is used to signal the direct register addressing mode
CPU_STATE := CPU_IRRS;
when x"9" => -------------------------------------------------------------------------- LDX R2,IRR1 instruction
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_MTOIRR;
when x"C" => -- illegal, decoded at 1-byte decoder
--CPU_STATE := CPU_ILLEGAL; -- uncommenting this adds +400 LEs to the design!!!
when x"D" => ------------------------------------------------------------------------------ CALL DA instruction
when x"F" => ------------------------------------------------------------------------- BTJ p,b,r1,X instruction
when others => ------------------------------------------------------------------------------ R1,imm instructions
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
CPU_STATE := CPU_TMA;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"7") then -------------------------------------------- column 7 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------- LDX IRR2,IR1 instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 3;
CPU_STATE := CPU_IRRS;
when x"9" => ------------------------------------------------------------------------- LDX IR2,IRR1 instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 3;
CPU_STATE := CPU_IMTOIRR;
when x"C" => --------------------------------------------------------------------------- LD r1,r2,X instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
NUM_BYTES := 3;
CPU_STATE := CPU_XADTOM;
when x"D" => --------------------------------------------------------------------------- LD r2,r1,X instruction
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_MTOXAD;
when x"F" => ------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
when others => ----------------------------------------------------------------------------- IR1,imm instructions
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_IND1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"6") then -------------------------------------------- column 6 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDX IRR2,R1 instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 3;
LU_INSTRUCTION := '1'; -- in this mode this flag is used to signal the direct register addressing mode
CPU_STATE := CPU_IRRS;
when x"9" => -------------------------------------------------------------------------- LDX R2,IRR1 instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 3;
CPU_STATE := CPU_MTOIRR;
when x"C" => -- illegal, decoded at 1-byte decoder
--CPU_STATE := CPU_ILLEGAL; -- uncommenting this adds +400 LEs to the design!!!
when x"D" => ------------------------------------------------------------------------------ CALL DA instruction
when x"F" => ------------------------------------------------------------------------- BTJ p,b,r1,X instruction
when others => ------------------------------------------------------------------------------ R1,imm instructions
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_OMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"5") then -------------------------------------------- column 5 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDX Ir1,ER2 instruction
FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
NUM_BYTES := 3;
CPU_STATE := CPU_IND2;
when x"9" => -------------------------------------------------------------------------- LDX Ir2,ER1 instruction
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_ISMD1;
when x"C" => ------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
when x"D" => ----------------------------------------------------------------------------- BSWAP R1 instruction
when x"F" => ---------------------------------------------------------------------------- LD R2,IR1 instruction
when others => ------------------------------------------------------------------------------ IR2,R1 instructions
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_ISMD1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"4") then -------------------------------------------- column 4 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => --------------------------------------------------------------------------- LDX r1,ER2 instruction
FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
when x"9" => --------------------------------------------------------------------------- LDX r2,ER1 instruction
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
when x"C" => ------------------------------------------------------------------------------ JP Irr1 instruction
when x"D" => ---------------------------------------------------------------------------- CALL Irr1 instruction
when x"F" => ----------------------------------------------------------------------------- MULT RR1 instruction
when others => ------------------------------------------------------------------------------- R2,R1 instructions
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
end case;
end if;
------------------------------------------------------------------------------------------------- BTJ p,b,r1,X instruction
------------------------------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F6" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F7") then
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
NUM_BYTES := 3;
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(0)='0') then CPU_STATE := CPU_BTJ; else CPU_STATE := CPU_IBTJ;
end if;
---------------------------------------------------------------------------------------------------- LD R2,IR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F5") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
NUM_BYTES := 3;
CPU_STATE := CPU_IND2;
------------------------------------------------------------------------------------------------------ CALL DA instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D6") then
DEST_ADDR16 := PC + 3;
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
SP := SP - 1;
FRAB <= SP;
LU_INSTRUCTION := '0'; -- this is used to indicate wether the stacking is due to a CALL or INT, 0 for a CALL
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_STACK;
---------------------------------------------------------------------------------------------------- 2nd page instructions
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
-------------------------------------------------------------------------------------------------- PUSH IM instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"70") then
SP := SP - 1;
FRAB <= SP;
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_OMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"5") then -------------------------------------------- column 5 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDX Ir1,ER2 instruction
MAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
CPU_STATE := CPU_OMA;
------------------------------------------------------------------------------------------------ CPC r1,r2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A2") then
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
TEMP_OP := ALU_CPC;
NUM_BYTES := 3;
CPU_STATE := CPU_IND2;
when x"9" => -------------------------------------------------------------------------- LDX Ir2,ER1 instruction
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
CPU_STATE := CPU_TMA;
----------------------------------------------------------------------------------------------- CPC r1,Ir2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A3") then
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
TEMP_OP := ALU_CPC;
NUM_BYTES := 3;
CPU_STATE := CPU_ISMD1;
when x"C" => ------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
when x"D" => ----------------------------------------------------------------------------- BSWAP R1 instruction
when x"F" => ---------------------------------------------------------------------------- LD R2,IR1 instruction
when others => ------------------------------------------------------------------------------ IR2,R1 instructions
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
CPU_STATE := CPU_ISMD1;
--------------------------------------------------------------------------------------------------- SRL R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C0") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_OP := LU2_SRL;
NUM_BYTES := 3;
CPU_STATE := CPU_ISMD1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"4") then -------------------------------------------- column 4 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => --------------------------------------------------------------------------- LDX r1,ER2 instruction
MAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
CPU_STATE := CPU_OMA2;
-------------------------------------------------------------------------------------------------- SRL IR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C1") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_OP := LU2_SRL;
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
when x"9" => --------------------------------------------------------------------------- LDX r2,ER1 instruction
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
when x"C" => ------------------------------------------------------------------------------ JP Irr1 instruction
when x"D" => ---------------------------------------------------------------------------- CALL Irr1 instruction
when x"F" => ----------------------------------------------------------------------------- MULT RR1 instruction
when others => ------------------------------------------------------------------------------- R2,R1 instructions
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
end case;
end if;
------------------------------------------------------------------------------------------------- BTJ p,b,r1,X instruction
------------------------------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F6" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F7") then
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
NUM_BYTES := 3;
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(0)='0') then CPU_STATE := CPU_BTJ; else CPU_STATE := CPU_IBTJ;
CPU_STATE := CPU_IND1;
LU_INSTRUCTION := '1';
end if;
end if;
---------------------------------------------------------------------------------------------------- LD R2,IR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F5") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_IND2;
------------------------------------------------------------------------------------------------------ CALL DA instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D6") then
DEST_ADDR16 := PC + 3;
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
SP := SP - 1;
MAB <= SP;
LU_INSTRUCTION := '0'; -- this is used to indicate wether the stacking is due to a CALL or INT, 0 for a CALL
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_STACK;
---------------------------------------------------------------------------------------------------- 2nd page instructions
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
-------------------------------------------------------------------------------------------------- PUSH IM instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"70") then
SP := SP - 1;
MAB <= SP;
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
NUM_BYTES := 3;
CPU_STATE := CPU_OMA;
------------------------------------------------------------------------------------------------ CPC r1,r2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A2") then
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
TEMP_OP := ALU_CPC;
NUM_BYTES := 3;
CPU_STATE := CPU_TMA;
----------------------------------------------------------------------------------------------- CPC r1,Ir2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A3") then
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
TEMP_OP := ALU_CPC;
NUM_BYTES := 3;
CPU_STATE := CPU_ISMD1;
--------------------------------------------------------------------------------------------------- SRL R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C0") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
TEMP_OP := LU2_SRL;
NUM_BYTES := 3;
CPU_STATE := CPU_OMA2;
-------------------------------------------------------------------------------------------------- SRL IR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C1") then
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
TEMP_OP := LU2_SRL;
NUM_BYTES := 3;
CPU_STATE := CPU_IND1;
LU_INSTRUCTION := '1';
end if;
end if;
end if;
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 2-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=2) then
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"C") then ------------------------------------------------- LD r,IMM instruction
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
DATAWRITE(RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4),IQUEUE.QUEUE(IQUEUE.RDPOS+1));
NUM_BYTES := 2;
CPU_STATE := CPU_STORE;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"B") then -------------------------------------------- JR cc,RelativeAddress
PC := PC + 2;
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
PC := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 2-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=2) then -- 2-byte instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"C") then ------------------------------------------------- LD r,IMM instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
DATAWRITE(ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)),IQUEUE.QUEUE(IQUEUE.RDPOS+1));
NUM_BYTES := 2;
CPU_STATE := CPU_STORE;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"B") then -------------------------------------------- JR cc,RelativeAddress
PC := PC + 2;
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
PC := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
IQUEUE.FETCH_STATE := F_ADDR;
else
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
IQUEUE.CNT := IQUEUE.CNT - 2;
end if;
CPU_STATE := CPU_DECOD;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"A") then ------------------------------------------- DJNZ r,RelativeAddress
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
PC := PC + 2;
DEST_ADDR16 := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
IQUEUE.CNT := IQUEUE.CNT - 2;
IQUEUE.FETCH_STATE := F_ADDR;
else
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
IQUEUE.CNT := IQUEUE.CNT - 2;
CPU_STATE := CPU_DJNZ;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"3") then -------------------------------------------- column 3 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------ LDEI Ir1,Irr2 instruction
when x"9" => ------------------------------------------------------------------------ LDEI Ir2,Irr1 instruction
when x"C" => ------------------------------------------------------------------------ LDCI Ir1,Irr2 instruction
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0'; -- indicates it is a read from program memory
WORD_DATA := '1'; -- indicates it is a LDCI instruction
CPU_STATE := CPU_LDPTOIM;
when x"D" => ------------------------------------------------------------------------ LDCI Ir2,Irr1 instruction
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '1'; -- indicates it is a write onto program memory
WORD_DATA := '1'; -- indicates it is a LDCI instruction
CPU_STATE := CPU_LDPTOIM;
when x"F" => ---------------------------------------------------------------------------- LD Ir1,r2 instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CPU_STATE := CPU_IND2;
when others => --------------------------------------------------------------------------- Ir2 to r1 instructions
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_ISMD1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"2") then -------------------------------------------- column 2 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDE r1,Irr2 instruction
when x"9" => -------------------------------------------------------------------------- LDE r2,Irr1 instruction
when x"C" => -------------------------------------------------------------------------- LDC r1,Irr2 instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0';
CPU_STATE := CPU_LDPTOM;
when x"D" => -------------------------------------------------------------------------- LDC r2,Irr1 instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '1';
CPU_STATE := CPU_LDPTOM;
when x"E" => --------------------------------------------------------------------------- BIT p,b,r1 instruction
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
NUM_BYTES := 2;
CPU_STATE := CPU_BIT;
when x"F" => ----------------------------------------------------------------------------- TRAP imm instruction
FRAB <= "000" & IQUEUE.QUEUE(IQUEUE.RDPOS+1) & '0';
DEST_ADDR16 := PC + 2;
NUM_BYTES := 2;
CPU_STATE := CPU_TRAP;
when others => ---------------------------------------------------------------------------- r2 to r1 instructions
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"1") then -------------------------------------------- column 1 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ------------------------------------------------------------------------------ SRP IMM instruction
RP := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
NUM_BYTES := 2;
CPU_STATE := CPU_DECOD;
when x"5" => ------------------------------------------------------------------------------ POP IR1 instruction
FRAB <= SP;
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
SP := SP + 1;
NUM_BYTES := 2;
CPU_STATE := CPU_IND2;
when x"7" => ----------------------------------------------------------------------------- PUSH IR1 instruction
SP := SP - 1;
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := SP;
NUM_BYTES := 2;
CPU_STATE := CPU_ISMD1;
when x"8" => --------------------------------------------------------------------------------- DECW instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := LU2_DEC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_INDRR;
when x"A" => --------------------------------------------------------------------------------- INCW instruction
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := LU2_INC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_INDRR;
when others => --------------------------------------------------------------------------------- IR1 instructions
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_IND1;
LU_INSTRUCTION := '1';
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"0") then -------------------------------------------- column 0 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ---------------------------------------------------------------------------------- BRK instruction
-- do nothing, BRK decoding is done in 1-byte instruction section
when x"5" => ---------------------------------------------------------------------------------- POP instruction
FRAB <= SP;
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
SP := SP + 1;
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
when x"7" => --------------------------------------------------------------------------------- PUSH instruction
SP := SP - 1;
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := SP;
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
when x"8" => --------------------------------------------------------------------------------- DECW instruction
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
FRAB <= DEST_ADDR+1;
TEMP_OP := LU2_DEC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
when x"A" => --------------------------------------------------------------------------------- INCW instruction
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
FRAB <= DEST_ADDR+1;
TEMP_OP := LU2_INC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
when others => ---------------------------------------------------------------------------------- R1 instructions
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
end case;
end if;
---------------------------------------------------------------------------------------------------------- MUL instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F4") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
NUM_BYTES := 2;
CPU_STATE := CPU_MUL;
---------------------------------------------------------------------------------------------------- CALL IRR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D4") then
DEST_ADDR16 := PC + 2;
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_INDSTACK;
------------------------------------------------------------------------------------------------------ JP IRR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C4") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_INDJUMP;
----------------------------------------------------------------------------------------------------- BSWAP R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D5") then
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := ALU_BSWAP;
NUM_BYTES := 2;
CPU_STATE := CPU_OMA;
------------------------------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C5") then
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0';
CPU_STATE := CPU_LDPTOIM;
end if;
CPU_STATE := CPU_DECOD;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"A") then ------------------------------------------- DJNZ r,RelativeAddress
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
PC := PC + 2;
DEST_ADDR16 := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
IQUEUE.CNT := IQUEUE.CNT - 2;
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_DJNZ;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"3") then -------------------------------------------- column 3 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => ------------------------------------------------------------------------ LDEI Ir1,Irr2 instruction
when x"9" => ------------------------------------------------------------------------ LDEI Ir2,Irr1 instruction
when x"C" => ------------------------------------------------------------------------ LDCI Ir1,Irr2 instruction
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0'; -- indicates it is a read from program memory
WORD_DATA := '1'; -- indicates it is a LDCI instruction
CPU_STATE := CPU_LDPTOIM;
when x"D" => ------------------------------------------------------------------------ LDCI Ir2,Irr1 instruction
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '1'; -- indicates it is a write onto program memory
WORD_DATA := '1'; -- indicates it is a LDCI instruction
CPU_STATE := CPU_LDPTOIM;
when x"F" => ---------------------------------------------------------------------------- LD Ir1,r2 instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CPU_STATE := CPU_IND2;
when others => --------------------------------------------------------------------------- Ir2 to r1 instructions
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_ISMD1;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"2") then -------------------------------------------- column 2 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"8" => -------------------------------------------------------------------------- LDE r1,Irr2 instruction
when x"9" => -------------------------------------------------------------------------- LDE r2,Irr1 instruction
when x"C" => -------------------------------------------------------------------------- LDC r1,Irr2 instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0';
CPU_STATE := CPU_LDPTOM;
when x"D" => -------------------------------------------------------------------------- LDC r2,Irr1 instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '1';
CPU_STATE := CPU_LDPTOM;
when x"E" => --------------------------------------------------------------------------- BIT p,b,r1 instruction
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
NUM_BYTES := 2;
CPU_STATE := CPU_BIT;
when x"F" => ----------------------------------------------------------------------------- TRAP imm instruction
MAB <= "000" & IQUEUE.QUEUE(IQUEUE.RDPOS+1) & '0';
DEST_ADDR16 := PC + 2;
NUM_BYTES := 2;
CPU_STATE := CPU_TRAP;
when others => ---------------------------------------------------------------------------- r2 to r1 instructions
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"1") then -------------------------------------------- column 1 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ------------------------------------------------------------------------------ SRP IMM instruction
RP := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
NUM_BYTES := 2;
CPU_STATE := CPU_DECOD;
when x"5" => ------------------------------------------------------------------------------ POP IR1 instruction
MAB <= SP;
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
SP := SP + 1;
NUM_BYTES := 2;
CPU_STATE := CPU_IND2;
when x"7" => ----------------------------------------------------------------------------- PUSH IR1 instruction
SP := SP - 1;
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
DEST_ADDR := SP;
NUM_BYTES := 2;
CPU_STATE := CPU_ISMD1;
when x"8" => --------------------------------------------------------------------------------- DECW instruction
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := LU2_DEC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_INDRR;
when x"A" => --------------------------------------------------------------------------------- INCW instruction
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := LU2_INC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_INDRR;
when others => --------------------------------------------------------------------------------- IR1 instructions
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_IND1;
LU_INSTRUCTION := '1';
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"0") then -------------------------------------------- column 0 instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ---------------------------------------------------------------------------------- BRK instruction
-- do nothing, BRK decoding is done in 1-byte instruction section
when x"5" => ---------------------------------------------------------------------------------- POP instruction
MAB <= SP;
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
SP := SP + 1;
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
when x"7" => --------------------------------------------------------------------------------- PUSH instruction
SP := SP - 1;
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
DEST_ADDR := SP;
NUM_BYTES := 2;
CPU_STATE := CPU_TMA;
when x"8" => --------------------------------------------------------------------------------- DECW instruction
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
MAB <= DEST_ADDR+1;
TEMP_OP := LU2_DEC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
when x"A" => --------------------------------------------------------------------------------- INCW instruction
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
MAB <= DEST_ADDR+1;
TEMP_OP := LU2_INC;
WORD_DATA := '1';
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
when others => ---------------------------------------------------------------------------------- R1 instructions
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
NUM_BYTES := 2;
CPU_STATE := CPU_OMA2;
end case;
end if;
---------------------------------------------------------------------------------------------------------- MUL instruction
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F4") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
NUM_BYTES := 2;
CPU_STATE := CPU_MUL;
---------------------------------------------------------------------------------------------------- CALL IRR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D4") then
DEST_ADDR16 := PC + 2;
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_INDSTACK;
------------------------------------------------------------------------------------------------------ JP IRR1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C4") then
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_INDJUMP;
----------------------------------------------------------------------------------------------------- BSWAP R1 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D5") then
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
TEMP_OP := ALU_BSWAP;
NUM_BYTES := 2;
CPU_STATE := CPU_OMA;
------------------------------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C5") then
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
NUM_BYTES := 2;
CAN_FETCH := '0';
LU_INSTRUCTION := '0';
CPU_STATE := CPU_LDPTOIM;
end if;
end if;
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 1-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=1) then
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"F") then ------------------------------------------------ column F instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ---------------------------------------------------------------------------------- NOP instruction
NUM_BYTES := 1;
when x"1" => ------------------------------------------------------------------------------ page 2 instructions
when x"2" =>
ATM_COUNTER := 0;
NUM_BYTES := 1;
when x"3" =>
CPU_STATE := CPU_ILLEGAL;
when x"4" =>
CPU_STATE := CPU_ILLEGAL;
when x"5" => ---------------------------------------------------------------------------------- WDT instruction
NUM_BYTES := 1;
when x"6" => --------------------------------------------------------------------------------- STOP instruction
NUM_BYTES := 1;
CPU_STATE := CPU_HALTED;
STOP <= '1';
when x"7" => --------------------------------------------------------------------------------- HALT instruction
NUM_BYTES := 1;
CPU_STATE := CPU_HALTED;
when x"8" => ----------------------------------------------------------------------------------- DI instruction
IRQE := '0';
NUM_BYTES := 1;
when x"9" => ----------------------------------------------------------------------------------- EI instruction
IRQE := '1';
NUM_BYTES := 1;
when x"A" => ---------------------------------------------------------------------------------- RET instruction
NUM_BYTES := 1;
MAB <= SP;
CPU_STATE := CPU_UNSTACK;
when x"B" => --------------------------------------------------------------------------------- IRET instruction
NUM_BYTES := 1;
IRQE := '1';
MAB <= SP;
CPU_STATE := CPU_UNSTACK3;
when x"C" => ---------------------------------------------------------------------------------- RCF instruction
CPU_FLAGS.C := '0';
NUM_BYTES := 1;
when x"D" => ---------------------------------------------------------------------------------- SCF instruction
CPU_FLAGS.C := '1';
NUM_BYTES := 1;
when x"E" => ---------------------------------------------------------------------------------- CCF instruction
CPU_FLAGS.C := not CPU_FLAGS.C;
NUM_BYTES := 1;
when others => ---------------------------------------------------------------------------------- R1 instructions
CPU_STATE := CPU_ILLEGAL;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"E") then ------------------------------------------------ INC r instruction
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
TEMP_OP := LU2_INC;
NUM_BYTES := 1;
CPU_STATE := CPU_OMA2;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"00") then -------------------------------------------------------------- BRK instruction
if (OCDCR.BRKEN='1') then -- the BRK instruction is enabled
if (OCDCR.DBGACK='1') then
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"FF";
DBG_UART.TX_EMPTY:='0';
------------------------------------------------------------------------------------------------------------------------------
--**************************************************************************************************************************--
-- 1-byte instructions --
--**************************************************************************************************************************--
------------------------------------------------------------------------------------------------------------------------------
if (IQUEUE.CNT>=1) then -- 1-byte instructions
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"F") then ------------------------------------------------ column F instructions
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
when x"0" => ---------------------------------------------------------------------------------- NOP instruction
NUM_BYTES := 1;
when x"1" => ------------------------------------------------------------------------------ page 2 instructions
when x"2" =>
ATM_COUNTER := 0;
NUM_BYTES := 1;
when x"3" =>
CPU_STATE := CPU_ILLEGAL;
when x"4" =>
CPU_STATE := CPU_ILLEGAL;
when x"5" => ---------------------------------------------------------------------------------- WDT instruction
NUM_BYTES := 1;
when x"6" => --------------------------------------------------------------------------------- STOP instruction
NUM_BYTES := 1;
STOP <= '1';
when x"7" => --------------------------------------------------------------------------------- HALT instruction
NUM_BYTES := 1;
HALT := '1';
when x"8" => ----------------------------------------------------------------------------------- DI instruction
IRQE := '0';
NUM_BYTES := 1;
when x"9" => ----------------------------------------------------------------------------------- EI instruction
IRQE := '1';
NUM_BYTES := 1;
when x"A" => ---------------------------------------------------------------------------------- RET instruction
NUM_BYTES := 1;
FRAB <= SP;
CPU_STATE := CPU_UNSTACK2;
when x"B" => --------------------------------------------------------------------------------- IRET instruction
NUM_BYTES := 1;
IRQE := '1';
FRAB <= SP;
CPU_STATE := CPU_UNSTACK3;
when x"C" => ---------------------------------------------------------------------------------- RCF instruction
CPU_FLAGS.C := '0';
NUM_BYTES := 1;
when x"D" => ---------------------------------------------------------------------------------- SCF instruction
CPU_FLAGS.C := '1';
NUM_BYTES := 1;
when x"E" => ---------------------------------------------------------------------------------- CCF instruction
CPU_FLAGS.C := not CPU_FLAGS.C;
NUM_BYTES := 1;
when others => ---------------------------------------------------------------------------------- R1 instructions
CPU_STATE := CPU_ILLEGAL;
end case;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"E") then ------------------------------------------------ INC r instruction
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
TEMP_OP := LU2_INC;
NUM_BYTES := 1;
CPU_STATE := CPU_OMA2;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"00") then -------------------------------------------------------------- BRK instruction
if (OCDCR.BRKEN='1') then -- the BRK instruction is enabled
if (OCDCR.DBGACK='1') then
if (DBG_UART.TX_EMPTY='1') then
DBG_UART.TX_DATA:=x"FF";
DBG_UART.TX_EMPTY:='0';
end if;
end if;
if (OCDCR.BRKLOOP='0') then -- if loop on BRK is disabled
OCDCR.DBGMODE := '1'; -- set DBGMODE halting CPU
end if;
else
NUM_BYTES := 1; -- remove the instruction from queue (execute as a NOP)
end if;
if (OCDCR.BRKLOOP='0') then -- if loop on BRK is disabled
OCDCR.DBGMODE := '1'; -- set DBGMODE halting CPU
end if;
else
NUM_BYTES := 1; -- remove the instruction from queue (execute as a NOP)
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F9" or
IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F8" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C6") then --------------------------- illegal opcode
CPU_STATE:= CPU_ILLEGAL;
NUM_BYTES := 1;
end if;
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F9" or
IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F8" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C6") then --------------------------- illegal opcode
CPU_STATE:= CPU_ILLEGAL;
NUM_BYTES := 1;
end if;
end if; -- if DBGMODE=0...
end if; -- if not stopped or halted
PC := PC + NUM_BYTES; -- update PC after instruction
IQUEUE.RDPOS := IQUEUE.RDPOS + NUM_BYTES; -- update QUEUE read pointer
IQUEUE.CNT := IQUEUE.CNT - NUM_BYTES; -- update QUEUE available bytes
if (OCD.SINGLESTEP='1') then -- if we are stepping instructions
if (NUM_BYTES/=0 or IQUEUE.FETCH_STATE=F_ADDR) then OCD.SINGLESTEP:='0'; -- if a instruction was decoded, reset step flag
end if;
end if;
PC := PC + NUM_BYTES;
IQUEUE.RDPOS := IQUEUE.RDPOS + NUM_BYTES;
IQUEUE.CNT := IQUEUE.CNT - NUM_BYTES;
if (OCD.SINGLESTEP='1') then
if (NUM_BYTES/=0 or IQUEUE.FETCH_STATE=F_ADDR) then OCD.SINGLESTEP:='0';
end if;
end if;
when CPU_MUL => -- MUL ***********************************************************************************************************
TEMP_DATA := DATAREAD(MAB); -- read first operand
MAB <= MAB + 1; -- go to the next operand
TEMP_DATA := DATAREAD(FRAB); -- read first operand
FRAB <= FRAB + 1; -- go to the next operand
CPU_STATE := CPU_MUL1;
when CPU_MUL1 =>
DEST_ADDR16 := TEMP_DATA * DATAREAD(MAB); -- multiply previous operand by the second operand and store temporarily
DATAWRITE(MAB,DEST_ADDR16(7 downto 0)); -- write the lower byte in current memory address
DEST_ADDR16 := TEMP_DATA * DATAREAD(FRAB); -- multiply previous operand by the second operand and store temporarily
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- prepare to write the lower byte in current memory address
WR <= '1';
CPU_STATE := CPU_MUL2;
when CPU_MUL2 =>
MAB <= MAB - 1; -- decrement memory address (point to the first operand)
DATAWRITE(MAB,DEST_ADDR16(15 downto 8)); -- write the higher byte
FRAB <= FRAB - 1; -- decrement memory address (point to the first operand)
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8)); -- write the higher byte
CPU_STATE := CPU_STORE; -- complete store operation
when CPU_XRRTORR => -- LEA *******************************************************************************************************
TEMP_DATA := DATAREAD(MAB); -- read the operand and store it
MAB <= MAB + 1; -- go to the next memory address
TEMP_DATA := DATAREAD(FRAB); -- read the operand and store it
FRAB <= FRAB + 1; -- go to the next memory address
CPU_STATE := CPU_XRRTORR2;
when CPU_XRRTORR2 =>
-- read the next operand and perform a 16 bit add with the offset previously in result
DEST_ADDR16 := ADDER16(TEMP_DATA & DATAREAD(MAB),RESULT);
MAB <= DEST_ADDR; -- point to the destination address
DATAWRITE(MAB,DEST_ADDR16(15 downto 8)); -- store the higher byte of the 16-bit result
-- read next operand and perform a 16 bit add with the offset previously in result
DEST_ADDR16 := ADDER16(TEMP_DATA & DATAREAD(FRAB),RESULT);
FRAB <= DEST_ADDR; -- point to the destination address
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8)); -- store the higher byte of the 16-bit result
CPU_STATE := CPU_XRRTORR3;
when CPU_XRRTORR3 =>
WR <= '1';
CPU_STATE := CPU_XRRTORR4;
when CPU_XRRTORR4 =>
MAB <= MAB + 1; -- go to the next memory address
DATAWRITE(MAB,DEST_ADDR16(7 downto 0)); -- store the lower byte of the 16-bit result
FRAB <= FRAB + 1; -- go to the next memory address
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- store the lower byte of the 16-bit result
CPU_STATE := CPU_STORE; -- complete store operation
when CPU_MTOXAD => -- MEMORY TO INDEXED 8-BIT ADDRESS ***************************************************************************
TEMP_DATA := DATAREAD(MAB);
MAB <= DEST_ADDR;
TEMP_DATA := DATAREAD(FRAB); -- read operand from memory
FRAB <= DEST_ADDR; -- update address bus with destination address
CPU_STATE := CPU_MTOXAD2;
when CPU_MTOXAD2 =>
MAB <= RP(3 downto 0)&(DATAREAD(MAB) + RESULT);
DATAWRITE(MAB,TEMP_DATA);
CPU_STATE := CPU_STORE;
FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT); -- update address bus indexed result
DATAWRITE(FRAB,TEMP_DATA); -- prepare to write data on destination (indexed) address
CPU_STATE := CPU_STORE; -- perform store (WR=1)
when CPU_XADTOM => -- INDEXED 8-BIT ADDRESS TO MEMORY ***************************************************************************
MAB <= RP(3 downto 0)&(DATAREAD(MAB) + RESULT);
FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT);
CPU_STATE := CPU_TMA;
when CPU_XRTOM => -- LEA *******************************************************************************************************
TEMP_DATA := DATAREAD(MAB)+RESULT;
MAB <= DEST_ADDR;
DATAWRITE(MAB,TEMP_DATA);
TEMP_DATA := DATAREAD(FRAB)+RESULT;
FRAB <= DEST_ADDR;
DATAWRITE(FRAB,TEMP_DATA);
CPU_STATE := CPU_STORE;
when CPU_IMTOIRR => -- INDIRECT MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ***********************************************
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- source address is read from indirect register
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
CPU_STATE := CPU_MTOIRR;
when CPU_MTOIRR => -- MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ********************************************************
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
MAB <= DEST_ADDR; -- MAB points to the indirect destination register pair
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
FRAB <= DEST_ADDR; -- FRAB points to the indirect destination register pair
RESULT := x"00";
CPU_STATE := CPU_XRRD2; -- proceed as X indexed register pair destination
CPU_STATE := CPU_XRRD2; -- proceed as X indexed register pair destination
when CPU_IRRS => -- RR PAIR AS INDIRECT SOURCE ADDRESS ************************************************************************
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE := CPU_IRRS2;
when CPU_IRRS2 =>
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
MAB <= DEST_ADDR16(11 downto 0);
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
FRAB <= DEST_ADDR16(11 downto 0);
if (LU_INSTRUCTION='1') then
CPU_STATE:= CPU_TMA; -- if it is direct addressing mode, go to TMA
else
CPU_STATE := CPU_IND2; -- if it is indirect addressing mode, go to IND2
end if;
when CPU_XRRD =>
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
MAB <= DEST_ADDR;
when CPU_XRRD => -- RR PAIR PLUS OFFSET AS DESTINATION ADDRESS ****************************************************************
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
FRAB <= DEST_ADDR;
CPU_STATE := CPU_XRRD2;
when CPU_XRRD2 =>
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE := CPU_XRRD3;
when CPU_XRRD3 =>
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
MAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
DATAWRITE(MAB,TEMP_DATA);
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
DATAWRITE(FRAB,TEMP_DATA);
CPU_STATE := CPU_STORE;
when CPU_XRRS =>
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
when CPU_XRRS => -- RR PAIR PLUS OFFSET AS SOURCE ADDRESS *********************************************************************
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE := CPU_XRRS2;
when CPU_XRRS2 =>
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
MAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
CPU_STATE := CPU_XRRS3;
when CPU_XRRS3 =>
TEMP_DATA := DATAREAD(MAB);
MAB <= DEST_ADDR;
DATAWRITE(MAB,TEMP_DATA);
TEMP_DATA := DATAREAD(FRAB);
FRAB <= DEST_ADDR;
DATAWRITE(FRAB,TEMP_DATA);
CPU_STATE := CPU_STORE;
when CPU_INDRR => -- INDIRECT DESTINATION ADDRESS FOR WORD INSTRUCTIONS (DECW AND INCW) ****************************************
MAB <= (RP(3 downto 0) & DATAREAD(MAB))+1; -- the destination address is given by indirect address
FRAB <= (RP(3 downto 0) & DATAREAD(FRAB))+1; -- the destination address is given by indirect address
CPU_STATE := CPU_OMA2;
when CPU_ISMD1 => -- INDIRECT SOURCE ADDRESS ***********************************************************************************
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- source address is read from indirect register
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
CPU_STATE := CPU_TMA;
when CPU_IND2 => -- READS REGISTER AND PERFORM OPERATION ON AN INDIRECT DESTINATION *******************************************
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
MAB <= DEST_ADDR; -- place the address of the indirect register on MAB
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
FRAB <= DEST_ADDR; -- place the address of the indirect register on FRAB
CPU_STATE := CPU_IND1; -- proceed to the indirect
when CPU_IND1 => -- INDIRECT DESTINATION ADDRESS ******************************************************************************
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- the destination address is given by indirect address
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- the destination address is given by indirect address
if (LU_INSTRUCTION='0') then CPU_STATE := CPU_OMA; -- proceed with one memory access
else CPU_STATE := CPU_OMA2; -- proceed with one memory access (logic unit related)
end if;
when CPU_TMA => -- TWO MEMORY ACCESS, READS SOURCE OPERAND FROM MEMORY *******************************************************
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
MAB <= DEST_ADDR; -- place the destination address (DEST_ADDR) on the memory address bus (MAB)
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
FRAB <= DEST_ADDR; -- place destination address (DEST_ADDR) on memory address bus (FRAB)
CPU_STATE := CPU_OMA; -- proceed to the last stage
when CPU_OMA => -- ONE MEMORY ACCESS stage ***********************************************************************************
-- this stage performs the TEMP_OP operation between TEMP_DATA and data read from current (MAB) address (destination)
RESULT := ALU(TEMP_OP,DATAREAD(MAB),TEMP_DATA,CPU_FLAGS.C);
-- this stage performs TEMP_OP operation between TEMP_DATA and data read from current (FRAB) address (destination)
RESULT := ALU(TEMP_OP,DATAREAD(FRAB),TEMP_DATA,CPU_FLAGS.C);
if (TEMP_OP<ALU_OR) then
CPU_FLAGS.C := ALU_FLAGS.C;
CPU_FLAGS.V := ALU_FLAGS.V;
1867,7 → 1887,7
CPU_FLAGS.V := '0';
end if;
if (ALU_NOUPDATE='0') then
DATAWRITE(MAB,RESULT);
DATAWRITE(FRAB,RESULT);
WR <= '1';
end if;
CPU_STATE := CPU_DECOD;
1875,8 → 1895,8
CPU_STATE := CPU_LDW;
end if;
when CPU_OMA2 => -- ONE MEMORY ACCESS stage logic unit related ****************************************************************
-- this stage performs the TEMP_OP LU2 operation on data read from current (MAB) address
RESULT := LU2(TEMP_OP,DATAREAD(MAB),CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.C);
-- this stage performs TEMP_OP LU2 operation on data read from current (FRAB) address
RESULT := LU2(TEMP_OP,DATAREAD(FRAB),CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.C);
if (TEMP_OP=LU2_DEC or TEMP_OP=LU2_INC) then
CPU_FLAGS.V := ALU_FLAGS.V;
CPU_FLAGS.Z := ALU_FLAGS.Z;
1902,7 → 1922,7
CPU_FLAGS.Z := ALU_FLAGS.Z;
CPU_FLAGS.S := ALU_FLAGS.S;
end if;
DATAWRITE(MAB,RESULT);
DATAWRITE(FRAB,RESULT);
WR <= '1';
if (WORD_DATA='1') then
WORD_DATA := '0';
1911,52 → 1931,54
CPU_STATE := CPU_DMAB;
else CPU_STATE := CPU_DECOD;
end if;
when CPU_DMAB => -- DECREMENT MEMORY ADDRESS BUS *****************************************************************************
MAB <= MAB - 1;
when CPU_DMAB => -- DECREMENT MEMORY ADDRESS BUS ******************************************************************************
FRAB <= FRAB - 1;
CPU_STATE := CPU_OMA2;
when CPU_LDW =>
if (WORD_DATA='0') then
TEMP_DATA := DATAREAD(MAB);
MAB <= MAB + 1;
else
DATAWRITE(MAB,TEMP_DATA);
WR <= '1';
end if;
when CPU_LDW => -- LOAD WORD INSTRUCTION *************************************************************************************
-- read higher byte from source operand
TEMP_DATA := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE := CPU_LDW2;
when CPU_LDW2 =>
if (WORD_DATA='0') then
RESULT := DATAREAD(MAB);
MAB <= DEST_ADDR;
WORD_DATA := '1';
CPU_STATE := CPU_LDW;
else
MAB <= MAB + 1;
DATAWRITE(MAB,RESULT);
CPU_STATE := CPU_STORE;
end if;
-- read lower byte from source operand
RESULT := DATAREAD(FRAB);
FRAB <= DEST_ADDR;
CPU_STATE := CPU_LDW3;
when CPU_LDW3 =>
-- write higher byte to destination operand
DATAWRITE(FRAB,TEMP_DATA);
WR <= '1';
CPU_STATE := CPU_LDW4;
when CPU_LDW4 =>
-- points FRAB to lower byte of destination address
FRAB <= FRAB + 1;
CPU_STATE := CPU_LDW5;
when CPU_LDW5 =>
DATAWRITE(FRAB,RESULT);
CPU_STATE := CPU_STORE;
when CPU_LDPTOIM => -- LOAD PROGRAM TO INDIRECT MEMORY **************************************************************************
TEMP_DATA := DATAREAD(MAB);
TEMP_DATA := DATAREAD(FRAB);
DEST_ADDR := RP(3 downto 0) & TEMP_DATA; -- the destination address is read from the indirect address
if (WORD_DATA='1') then
-- it is a LDCI instruction, so we have to increment the indirect address after the operation
DATAWRITE(MAB,TEMP_DATA+1);
DATAWRITE(FRAB,TEMP_DATA+1);
WR <= '1';
CPU_STATE := CPU_LDPTOIM2;
else
-- it is a LDC instruction, proceed the load instruction
MAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
FRAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
CPU_STATE := CPU_LDPTOM;
end if;
when CPU_LDPTOIM2 =>
MAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
FRAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
CPU_STATE := CPU_LDPTOM;
when CPU_LDPTOM => -- LOAD PROGRAM TO MEMORY ***********************************************************************************
IAB(15 downto 8) <= DATAREAD(MAB); -- read the high address from the first register
MAB <= MAB + 1;
IAB(15 downto 8) <= DATAREAD(FRAB); -- read the high address from the first register
FRAB <= FRAB + 1;
CPU_STATE := CPU_LDPTOM2;
when CPU_LDPTOM2 =>
IAB(7 downto 0) <= DATAREAD(MAB); -- read the low address from the second register
MAB <= DEST_ADDR;
IAB(7 downto 0) <= DATAREAD(FRAB); -- read the low address from the second register
FRAB <= DEST_ADDR;
if (LU_INSTRUCTION='0') then
CPU_STATE := CPU_LDPTOM3; -- if it is a read from program memory
else
1963,7 → 1985,7
CPU_STATE := CPU_LDMTOP; -- if it is a write onto program memory
end if;
when CPU_LDPTOM3 => -- READ PROGRAM MEMORY AND STORE INTO RAM *******************************************************************
DATAWRITE(MAB,IDB);
DATAWRITE(FRAB,IDB);
WR <= '1';
CAN_FETCH := '1'; -- re-enable fetching
FETCH_ADDR := PC;
1974,11 → 1996,11
end if;
when CPU_LDPTOM4 =>
DEST_ADDR := ADDRESSER4(RESULT(3 downto 0));
MAB <= DEST_ADDR+1;
FRAB <= DEST_ADDR+1;
TEMP_OP := LU2_INC;
CPU_STATE := CPU_OMA2;
when CPU_LDMTOP => -- READ RAM AND STORE ONTO PROGRAM MEMORY *******************************************************************
PWDB <= DATAREAD(MAB); -- PWDB receive the content of RAM
IWDB <= DATAREAD(FRAB); -- IWDB receive the content of RAM
PGM_WR <= '1'; -- enable program memory write signal
CPU_STATE := CPU_LDMTOP2;
when CPU_LDMTOP2 =>
1989,96 → 2011,95
if (WORD_DATA='1') then
CPU_STATE := CPU_LDPTOM4;
end if;
when CPU_BIT =>
TEMP_DATA := DATAREAD(MAB);
when CPU_BIT => -- BIT INSTRUCTION *******************************************************************************************
TEMP_DATA := DATAREAD(FRAB);
TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0)))):=TEMP_OP(3);
DATAWRITE(MAB,TEMP_DATA);
DATAWRITE(FRAB,TEMP_DATA);
WR <= '1';
CPU_STATE := CPU_DECOD;
when CPU_IBTJ =>
MAB <= RP(3 downto 0) & DATAREAD(MAB);
when CPU_IBTJ => -- INDIRECT BIT TEST JUMP INSTRUCTION ************************************************************************
FRAB <= RP(3 downto 0) & DATAREAD(FRAB);
CPU_STATE := CPU_BTJ;
when CPU_BTJ =>
TEMP_DATA := DATAREAD(MAB);
when CPU_BTJ => -- BIT TEST JUMP INSTRUCTION *********************************************************************************
TEMP_DATA := DATAREAD(FRAB);
if (TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0))))=TEMP_OP(3)) then
PC := ADDER16(PC,RESULT);
IQUEUE.FETCH_STATE := F_ADDR;
end if;
CPU_STATE := CPU_DECOD;
when CPU_DJNZ =>
RESULT := LU2(LU2_DEC,DATAREAD(MAB),'0','0','0');
when CPU_DJNZ => -- DECREMENT AND JUMP IF NOT ZERO INSTRUCTION ****************************************************************
RESULT := LU2(LU2_DEC,DATAREAD(FRAB),'0','0','0');
if (ALU_FLAGS.Z='0') then -- result is not zero, then jump relative
PC := DEST_ADDR16;
IQUEUE.FETCH_STATE := F_ADDR;
end if;
DATAWRITE(MAB,RESULT);
DATAWRITE(FRAB,RESULT);
WR <= '1';
CPU_STATE := CPU_DECOD;
when CPU_INDJUMP =>
PC(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
when CPU_INDJUMP => -- INDIRECT JUMP INSTRUCTION *********************************************************************************
PC(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE:= CPU_INDJUMP2;
when CPU_INDJUMP2 =>
PC(7 downto 0) := DATAREAD(MAB);
PC(7 downto 0) := DATAREAD(FRAB);
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_DECOD;
when CPU_TRAP =>
PC(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
when CPU_TRAP => -- TRAP INSTRUCTION ******************************************************************************************
PC(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE:= CPU_TRAP2;
when CPU_TRAP2 =>
PC(7 downto 0) := DATAREAD(MAB);
PC(7 downto 0) := DATAREAD(FRAB);
SP := SP - 1;
MAB <= SP;
FRAB <= SP;
IQUEUE.FETCH_STATE := F_ADDR;
LU_INSTRUCTION := '1';
CPU_STATE := CPU_STACK;
when CPU_INDSTACK =>
PC(15 downto 8) := DATAREAD(MAB);
MAB <= MAB + 1;
when CPU_INDSTACK => -- INDIRECT CALL INSTRUCTION *****************************************************************************
PC(15 downto 8) := DATAREAD(FRAB);
FRAB <= FRAB + 1;
CPU_STATE:= CPU_INDSTACK2;
when CPU_INDSTACK2 =>
PC(7 downto 0) := DATAREAD(MAB);
PC(7 downto 0) := DATAREAD(FRAB);
SP := SP - 1;
MAB <= SP;
FRAB <= SP;
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_STACK;
when CPU_VECTOR =>
PC(15 downto 8) := IDB;
when CPU_VECTOR => -- LOAD PC WITH ADDRESS STORED IN PROGRAM MEMORY *********************************************************
PC(15 downto 8) := IDB; -- read high byte of destination address
IAB <= IAB + 1;
CPU_STATE := CPU_VECTOR2;
when CPU_VECTOR2 =>
PC(7 downto 0) := IDB;
IQUEUE.FETCH_STATE := F_ADDR;
CAN_FETCH := '1';
if (LU_INSTRUCTION='1') then CPU_STATE := CPU_STACK;
PC(7 downto 0) := IDB; -- read low byte of destination address
IQUEUE.FETCH_STATE := F_ADDR; -- reset queue FSM
CAN_FETCH := '1'; -- restart fetching
if (INT_FLAG='1') then CPU_STATE := CPU_STACK;
else CPU_STATE := CPU_DECOD;
end if;
when CPU_STACK => -- PUSH PC 7:0 INTO THE STACK *******************************************************************************
DATAWRITE(MAB,DEST_ADDR16(7 downto 0));
when CPU_STACK => -- PUSH PC 7:0 INTO THE STACK ********************************************************************************
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0));
WR <= '1';
CPU_STATE := CPU_STACK1;
when CPU_STACK1 =>
SP := SP - 1;
MAB <= SP;
FRAB <= SP;
CPU_STATE := CPU_STACK2;
when CPU_STACK2 =>
DATAWRITE(MAB,DEST_ADDR16(15 downto 8));
when CPU_STACK2 => -- PUSH PC 15:8 INTO THE STACK *******************************************************************************
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8));
WR <= '1';
if (LU_INSTRUCTION='1') then
if (INT_FLAG='1') then
CPU_STATE := CPU_STACK3;
else
CPU_STATE := CPU_DECOD;
end if;
when CPU_STACK3 => -- PUSH FLAGS INTO THE STACK *******************************************************************************
when CPU_STACK3 => -- PUSH FLAGS INTO THE STACK *********************************************************************************
SP := SP - 1;
MAB <= SP;
DATAWRITE(MAB,CPU_FLAGS.C&CPU_FLAGS.Z&CPU_FLAGS.S&CPU_FLAGS.V&CPU_FLAGS.D&CPU_FLAGS.H&CPU_FLAGS.F2&CPU_FLAGS.F1);
WR <= '1';
FRAB <= SP;
DATAWRITE(FRAB,CPU_FLAGS.C&CPU_FLAGS.Z&CPU_FLAGS.S&CPU_FLAGS.V&CPU_FLAGS.D&CPU_FLAGS.H&CPU_FLAGS.F2&CPU_FLAGS.F1);
IRQE := '0';
CPU_STATE := CPU_DECOD;
when CPU_UNSTACK3 =>
TEMP_DATA := DATAREAD(MAB);
CPU_STATE := CPU_STORE;
when CPU_UNSTACK3 => -- POP FLAGS FROM STACK **********************************************************************************
TEMP_DATA := DATAREAD(FRAB);
CPU_FLAGS.C := TEMP_DATA(7);
CPU_FLAGS.Z := TEMP_DATA(6);
CPU_FLAGS.S := TEMP_DATA(5);
2088,28 → 2109,27
CPU_FLAGS.F2 := TEMP_DATA(1);
CPU_FLAGS.F1 := TEMP_DATA(0);
SP := SP + 1;
MAB <= SP;
CPU_STATE := CPU_UNSTACK;
when CPU_UNSTACK =>
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
FRAB <= SP;
CPU_STATE := CPU_UNSTACK2;
when CPU_UNSTACK2 => -- POP PC(15:8) FROM STACK *******************************************************************************
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
SP := SP + 1;
MAB <= SP;
CPU_STATE := CPU_UNSTACK2;
when CPU_UNSTACK2 =>
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
FRAB <= SP;
CPU_STATE := CPU_UNSTACK;
when CPU_UNSTACK => -- POP PC(7:0) FROM STACK ********************************************************************************
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
SP := SP + 1;
PC := DEST_ADDR16;
IQUEUE.FETCH_STATE := F_ADDR;
CPU_STATE := CPU_DECOD;
when CPU_STORE =>
WR <= '1';
CPU_STATE := CPU_DECOD;
when CPU_HALTED => -- HALT mode, wait for an interrupt or reset
when CPU_STORE => -- stores data into memory
WR <= '1'; -- enable write signal (it is automatically disabled on CPU_DECOD state)
CPU_STATE := CPU_DECOD; -- proceed to main decoding state
when CPU_ILLEGAL => -- An illegal opcode was fetched
when CPU_RESET =>
when CPU_RESET => -- SOFTWARE RESET (TRIGGERED BY OCD RESET BIT) ***********************************************************
IAB <= x"0002";
MAB <= x"000";
PWDB <= x"00";
FRAB <= x"000";
IWDB <= x"00";
SP := x"000";
RP := x"00";
WR <= '0';
2131,9 → 2151,8
CPU_STATE := CPU_VECTOR;
when others =>
CPU_STATE := CPU_DECOD;
end case;
-- end of the main decoder
end if; -- CKDIVIDER
end case;
-- end of the main decoder
end if;
end process;
end CPU;
/fpz8_timer.bsf
0,0 → 1,120
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2010 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 64 64 240 320)
(text "fpz8_timer" (rect 5 0 56 12)(font "Arial" ))
(text "inst" (rect 8 240 25 252)(font "Arial" ))
(port
(pt 0 48)
(input)
(text "RAB[11..0]" (rect 0 0 54 12)(font "Arial" ))
(text "RAB[11..0]" (rect 21 40 75 52)(font "Arial" ))
(line (pt 0 48)(pt 16 48)(line_width 3))
)
(port
(pt 0 64)
(input)
(text "RIDB[7..0]" (rect 0 0 53 12)(font "Arial" ))
(text "RIDB[7..0]" (rect 21 56 74 68)(font "Arial" ))
(line (pt 0 64)(pt 16 64)(line_width 3))
)
(port
(pt 176 80)
(input)
(text "SIDB[7..0]" (rect 0 0 51 12)(font "Arial" ))
(text "SIDB[7..0]" (rect 101 72 152 84)(font "Arial" ))
(line (pt 160 80)(pt 176 80)(line_width 3))
)
(port
(pt 0 96)
(input)
(text "REG_SEL" (rect 0 0 49 12)(font "Arial" ))
(text "REG_SEL" (rect 21 88 70 100)(font "Arial" ))
(line (pt 0 96)(pt 16 96)(line_width 1))
)
(port
(pt 0 32)
(input)
(text "WR" (rect 0 0 18 12)(font "Arial" ))
(text "WR" (rect 21 24 39 36)(font "Arial" ))
(line (pt 0 32)(pt 16 32)(line_width 1))
)
(port
(pt 0 112)
(input)
(text "CLK_IN" (rect 0 0 38 12)(font "Arial" ))
(text "CLK_IN" (rect 21 104 59 116)(font "Arial" ))
(line (pt 0 112)(pt 16 112)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "STOP" (rect 0 0 28 12)(font "Arial" ))
(text "STOP" (rect 21 136 49 148)(font "Arial" ))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 176 216)
(input)
(text "TMR_IN" (rect 0 0 40 12)(font "Arial" ))
(text "TMR_IN" (rect 112 208 152 220)(font "Arial" ))
(line (pt 160 216)(pt 176 216)(line_width 1))
)
(port
(pt 176 32)
(input)
(text "TMR_ID[1..0]" (rect 0 0 66 12)(font "Arial" ))
(text "TMR_ID[1..0]" (rect 86 24 152 36)(font "Arial" ))
(line (pt 160 32)(pt 176 32)(line_width 3))
)
(port
(pt 0 128)
(input)
(text "RESET" (rect 0 0 35 12)(font "Arial" ))
(text "RESET" (rect 21 120 56 132)(font "Arial" ))
(line (pt 0 128)(pt 16 128)(line_width 1))
)
(port
(pt 0 80)
(output)
(text "RODB[7..0]" (rect 0 0 57 12)(font "Arial" ))
(text "RODB[7..0]" (rect 24 72 81 84)(font "Arial" ))
(line (pt 16 80)(pt 0 80)(line_width 3))
)
(port
(pt 0 216)
(output)
(text "INT" (rect 0 0 17 12)(font "Arial" ))
(text "INT" (rect 24 208 41 220)(font "Arial" ))
(line (pt 16 216)(pt 0 216)(line_width 1))
)
(port
(pt 176 200)
(output)
(text "TMR_OUT" (rect 0 0 50 12)(font "Arial" ))
(text "TMR_OUT" (rect 105 195 155 207)(font "Arial" ))
(line (pt 176 200)(pt 160 200)(line_width 1))
)
(drawing
(rectangle (rect 16 16 160 232)(line_width 1))
)
)
/fpz8_timer.vhd
0,0 → 1,111
-- FPz8 simple timer
-- By Fabio Pereira
 
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all ;
 
entity fpz8_timer IS
port
(
RAB : in std_logic_vector(11 downto 0);
RIDB : in std_logic_vector(7 downto 0);
RODB : out std_logic_vector(7 downto 0);
SIDB : in std_logic_vector(7 downto 0);
REG_SEL : in std_logic;
WR : in std_logic;
CLK_IN : in std_logic;
STOP : in std_logic;
INT : out std_logic;
TMR_OUT : out std_logic;
TMR_IN : in std_logic;
TMR_ID : in std_logic_vector(1 downto 0);
RESET : in std_logic
);
end fpz8_timer;
 
architecture timer of fpz8_timer is
shared variable TMR_EN : std_logic;
shared variable TMR_CMP : std_logic_vector(15 downto 0);
shared variable TMR_TEMP : std_logic_vector(7 downto 0);
shared variable TMR_PRESEL : std_logic_vector(2 downto 0);
shared variable TMR_CNT : std_logic_vector(15 downto 0);
shared variable TMR_PRE : std_logic_vector(7 downto 0);
shared variable INT_OUT : std_logic;
shared variable BASE_ADDR : std_logic_vector(11 downto 0);
begin
control: process(CLK_IN,REG_SEL,RESET)
begin
INT <= INT_OUT;
case TMR_ID is
when "00" => BASE_ADDR := x"F00";
when "01" => BASE_ADDR := x"F08";
when "10" => BASE_ADDR := x"F10";
when "11" => BASE_ADDR := x"F18";
end case;
if (RESET='1') then
TMR_EN := '0';
TMR_CMP := x"0000";
TMR_TEMP := x"00";
elsif (rising_edge(CLK_IN) and REG_SEL='1') then
if (WR='0') then -- it is a reading operation
if (RAB=(BASE_ADDR+7)) then ------ register TMR_CTL
RODB<=TMR_EN&'0'&TMR_PRESEL&"000";
elsif (RAB=BASE_ADDR+2) then -- register TMR_CMPH
RODB<=TMR_CMP(15 downto 8);
elsif (RAB=BASE_ADDR+3) then -- register TMR_CMPL
RODB<=TMR_CMP(7 downto 0);
else RODB<=SIDB;
end if;
else -- it is a writing operation
if (RAB=BASE_ADDR+7) then ----- register TMR_CTL
TMR_EN:=RIDB(7);
TMR_PRESEL:=RIDB(5 downto 3);
elsif (RAB=BASE_ADDR+2) then -- register TMR_RLH
TMR_TEMP := RIDB;
elsif (RAB=BASE_ADDR+3) then -- register TMR_RLL
TMR_CMP(7 downto 0) := RIDB;
TMR_CMP(15 downto 8) := TMR_TEMP;
end if;
end if;
end if;
end process control; -- control process
counter: process(CLK_IN,RESET,STOP)
variable TMR_PRECP : std_logic_vector(7 downto 0);
begin
if (RESET='1') then
TMR_CNT := x"0000";
TMR_PRE := x"00";
TMR_PRECP := x"00";
INT_OUT := '0';
elsif (rising_edge(CLK_IN)) then
if (STOP='0') then
if (TMR_EN='1') then
case TMR_PRESEL is
when "000" => TMR_PRECP:=x"01"; -- prescaler divide by 1
when "001" => TMR_PRECP:=x"02"; -- prescaler divide by 2
when "010" => TMR_PRECP:=x"04"; -- prescaler divide by 4
when "011" => TMR_PRECP:=x"08"; -- prescaler divide by 8
when "100" => TMR_PRECP:=x"10"; -- prescaler divide by 16
when "101" => TMR_PRECP:=x"20"; -- prescaler divide by 32
when "110" => TMR_PRECP:=x"40"; -- prescaler divide by 64
when others => TMR_PRECP:=x"80"; -- prescaler divide by 128
end case;
TMR_PRE := TMR_PRE + 1;
if (TMR_PRE=TMR_PRECP) then
TMR_PRE:=x"00";
TMR_CNT:=TMR_CNT+1;
if (TMR_CNT=TMR_CMP) then
TMR_CNT:=x"0000";
INT_OUT := not INT_OUT;
end if;
end if;
else
TMR_CNT:=x"0000";
TMR_PRE:=x"00";
end if; -- if TMR_EN=1
end if; -- if STOP=0
end if; -- rising edge of CLK_IN
end process; -- counter process
end timer;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.