class ProgramCounter(Component): def __init__(self, n): super().__init__("pc " + n) self.v = 0 self.addr = Signal(self, "addr", 8) self.data = Signal(self, "data", 8) self.rst = NotifySignal(self, "rst", 1) self.inc = NotifySignal(self, "inc", 1) self.we = NotifySignal(self, "we", 1) self.co = Signal(self, "co", 1) def update(self, signal): if self.rst.value() == 1: self.v = 0 elif self.we.value(): self.v = self.data.value() # print('Jump') elif self.inc.had_edge(0, 1): if self.v == 0xFF: self.v = 0 self.co <<= 1 else: self.v += 1 self.co <<= 0 self.addr <<= self.v
class ALU(Component): def __init__(self): super().__init__("alu") self.a = Signal(self, "a", 9) self.b = Signal(self, "b", 8) self.out = Signal(self, "out", 9) self.fn = Signal(self, "fn", 1) self.oe = NotifySignal(self, "oe", 1) self.we = NotifySignal(self, "we", 1) self.v = 0 def update(self, signal): if self.we.had_edge(0, 1): if self.fn.value() == 0: # nor trace("alu nor {} {}".format(self.a.value(), self.b.value()), end="") carry = self.a.value() & 0b100000000 value = self.a.value() & 0xFF self.v = carry | ((~(value | self.b.value())) & 0xFF) else: # add trace("alu add {} {}".format(self.a.value(), self.b.value()), end="") self.v = ((self.a.value() & 0xFF) + self.b.value()) & 0x1FF trace(" --> {}".format(self.v)) if self.oe.value() == 1: self.out <<= self.v else: self.out <<= None
class Decoder(Component): def __init__(self): super().__init__("decoder") self.clk = NotifySignal(self, "clk", 1) self.addr = Signal(self, "addr", 6) self.data = Signal(self, "data", 8) self.we = Signal(self, "we", 1) self.oe = Signal(self, "oe", 1) self.acc = 0 self.adreg = 0 self.pc = 0 self.states = 0 def reset(self): self.addr <<= 0 self.data <<= None self.oe <<= 1 self.we <<= 0 def update(self, signal): if self.clk.had_edge(0, 1): if self.states == 0b000: self.pc = self.adreg + 1 self.adreg = self.data.value() else: self.adreg = self.pc # ALU / Data Path if self.states == 0b010: # print(' add a {} + {}'.format(self.acc, self.data.value())) self.acc = ((self.acc & 0xFF) + self.data.value()) & 0x1FF # print(' = {}'.format(self.acc)) elif self.states == 0b011: # print(' nor a {} + {}'.format(self.acc, self.data.value())) carry = self.acc & 0b100000000 value = self.acc & 0xFF nor = (~(value | self.data.value())) & 0xFF self.acc = carry | nor # print(' = {}'.format(self.acc)) elif self.states == 0b101: # Clear carry self.acc = self.acc & 0xFF # State machine if self.states != 0b000: self.states = 0b000 elif (self.data.value() & 0b11000000) == 0b11000000 and self.acc & 0b100000000: self.states = 0b101 else: self.states = ~((self.data.value() >> 6) & 0b11) & 0b11 clk = self.clk.value() self.addr <<= self.adreg & 0x3F self.data <<= None if self.states != 0b001 else self.acc & 0xFF self.oe <<= (0 if (clk == 1 or self.states == 0b001 or self.states == 0b101) else 1) self.we <<= 0 if (clk == 1 or self.states != 0b001) else 1
class AccumulatorRegister(IORegister): def __init__(self): super().__init__("accumulator", width=9) self.z = Signal(self, "z", 1) self.cc = NotifySignal(self, "cc", 1) def update(self, signal): super().update(signal) self.z <<= 1 if self.v == 0 else 0 if self.cc.had_edge(0, 1): self.v = self.v & 0xFF
class InstructionRegister(Component): def __init__(self): super().__init__("ir") self.v = 0 self.data = Signal(self, "data", 8) self.instr = Signal(self, "instr", 8) self.imm = Signal(self, "imm", 8) self.we = NotifySignal(self, "we", 1) self.oe = NotifySignal(self, "oe", 1) def update(self, signal): if self.we.had_edge(0, 1): self.v = self.data.value() self.instr <<= self.v if self.oe.value(): imm = self.v & 0xF self.imm <<= imm | (imm << 4) else: self.imm <<= None
class Decoder(Component): def __init__(self): super().__init__("decoder") self.clk = NotifySignal(self, "clk", 1) self.ram_oe = Signal(self, "ram_oe", 1) self.ram_we = Signal(self, "ram_oe", 1) self.ar_oe = Signal(self, "ar_oe", 1) self.ar_we = Signal(self, "ar_we", 1) self.ir_oe = Signal(self, "ir_oe", 1) self.ir_we = Signal(self, "ir_we", 1) self.pc_we = Signal(self, "pc_we", 1) self.pc_oe = Signal(self, "pc_oe", 1) self.pc_inc = Signal(self, "pc_inc", 1) self.a_oe = Signal(self, "a_oe", 1) self.a_we = Signal(self, "a_we", 1) self.a_cc = Signal(self, "a_cc", 1) self.alu_oe = Signal(self, "alu_oe", 1) self.alu_we = Signal(self, "alu_we", 1) self.carry = Signal(self, "carry", 1) self.z = Signal(self, "z", 1) self.fn = Signal(self, "fn", 1) self.instr = Signal(self, "instr", 2) self.state = 0 def reset(self): self.ram_oe <<= 0 self.ram_we <<= 0 self.ar_oe <<= 0 self.ar_we <<= 0 self.ir_oe <<= 0 self.ir_we <<= 0 self.pc_we <<= 0 self.pc_oe <<= 0 self.pc_inc <<= 0 self.a_oe <<= 0 self.a_we <<= 0 self.a_cc <<= 0 self.alu_oe <<= 0 self.alu_we <<= 0 self.fn <<= 0 def update(self, signal): if self.clk.had_edge(0, 1): self.state = (self.state + 1) % 8 # print('state: {}: instr: {:02b}'.format(self.state, self.instr.value())) self.ram_oe <<= self.state <= 3 or ( self.instr.value() in ( 0b00, 0b01, ) and self.state <= 5 ) # not (self.instr.value() == 0b10 and self.state in (5, 6,)) # self.pc_oe <<= 0 # self.ir_oe <<= 0 # self.ar_oe <<= 0 # self.a_oe <<= 0 self.ar_oe <<= self.state > 3 self.ir_oe <<= self.state > 3 self.pc_oe <<= self.state <= 3 self.ir_we <<= self.state == 1 self.pc_inc <<= self.state in ( 2, 4, ) self.ar_we <<= self.state == 3 # alu self.alu_we <<= ( self.instr.value() in ( 0b00, 0b01, ) and self.state == 5 ) self.alu_oe <<= self.instr.value() in (0b00, 0b01,) and self.state in ( 5, 6, ) self.a_we <<= ( self.instr.value() in ( 0b00, 0b01, ) and self.state == 6 ) self.fn <<= self.instr.value() & 1 # sta self.a_oe <<= self.instr.value() == 0b10 and self.state in ( 5, 6, ) self.ram_we <<= self.instr.value() == 0b10 and self.state == 6 # jcc c=0 self.pc_we <<= ( self.instr.value() == 0b11 and self.carry.value() == 0 and self.state == 5 ) # jcc c=1 self.a_cc <<= ( self.instr.value() == 0b11 and self.carry.value() != 0 and self.state == 5 )
class Decoder(Component): def __init__(self): super().__init__("decoder") self.clk = NotifySignal(self, "clk", 1) self.addr = Signal(self, "addr", 5) self.data = Signal(self, "data", 8) self.we = Signal(self, "we", 1) self.oe = Signal(self, "oe", 1) self.acc = 0 self.x = 0 self.adreg = 0 self.pc = 0 self.states = 0 def reset(self): self.addr <<= 0 self.data <<= None self.oe <<= 1 self.we <<= 0 def update(self, signal): if self.clk.had_edge(0, 1): if self.states == 0b0000: self.pc = self.adreg + 1 self.adreg = self.data.value() else: self.adreg = self.pc # ALU / Data Path if self.states == 0b0110: # print(' add a {} + {}'.format(self.acc, self.data.value())) self.acc = ((self.acc & 0xFF) + self.data.value()) & 0x1FF # print(' = {}'.format(self.acc)) elif self.states == 0b0111: # print(' nor a {} + {}'.format(self.acc, self.data.value())) carry = self.acc & 0b100000000 value = self.acc & 0xFF nor = (~(value | self.data.value())) & 0xFF self.acc = carry | nor # print(' = {}'.format(self.acc)) elif self.states == 0b0010: # print(' add x {} + {}'.format(self.x, self.data.value())) self.x = ((self.x & 0xFF) + self.data.value()) & 0x1FF elif self.states == 0b0011: # print(' nor x {} + {}'.format(self.x, self.data.value())) carry = self.x & 0b100000000 value = self.x & 0xFF nor = (~(value | self.data.value())) & 0xFF self.x = carry | nor elif self.states == 0b1101: # Clear carry # print(' j not taken') self.acc = self.acc & 0xFF elif self.states == 0b0101: # print(' sta') pass elif self.states == 0b0001: # print(' stx') pass else: print(" unknown state") # State machine if self.states != 0b0000: self.states = 0b0000 elif (self.data.value() & 0b01100000) == 0b01100000: # print(' maybe jump {} {}'.format(self.acc >> 8, self.acc)) if not (self.data.value() & 0b10000000) and (self.acc & 0b100000000): # print(' jcc not taken') self.states = 0b1101 elif (self.data.value() & 0b10000000) and (self.acc & 0xFF) == 0: # print(' jnz not taken') self.states = 0b1101 else: # print(' branch taken') self.states = 0b0000 else: # print(' going to state for {:03b}'.format(self.data.value() >> 5)) self.states = ~((self.data.value() >> 5) & 0b111) & 0b111 if (not (self.data.value() >> 7) and (self.data.value() & 0b01100000) != 0b01100000): # print('offset by x', self.x) self.adreg += self.x clk = self.clk.value() self.addr <<= self.adreg & 0x1F if self.states == 0b0101: self.data <<= self.acc & 0xFF elif self.states == 0b0001: self.data <<= self.x & 0xFF else: self.data <<= None self.oe <<= (0 if (clk == 1 or self.states in ( 0b0001, 0b0101, 0b1101, )) else 1) self.we <<= (0 if (clk == 1 or self.states not in ( 0b0001, 0b0101, )) else 1)
class Decoder(Component): MASK_OP = 0b011 MASK_REG = 0b100 OP_NOR = 0b000 OP_ADD = 0b001 OP_ST = 0b010 OP_J = 0b011 REG_A = 0b000 REG_X = 0b100 def __init__(self): super().__init__("decoder") self.clk = NotifySignal(self, "clk", 1) self.addr = Signal(self, "addr", 13) self.data = Signal(self, "data", 8) self.we = Signal(self, "we", 1) self.oe = Signal(self, "oe", 1) self.acc = 0 self.x = 0 self.adreg = 0 self.hi5 = 0 self.pc = 0 self.state = 0 self.op = 0 def reset(self): self.addr <<= 0 self.data <<= None self.oe <<= 1 self.we <<= 0 def update(self, signal): if self.clk.had_edge(0, 1): # print('clock {}'.format(self.state)) if self.state == 0: self.pc = self.adreg + 2 self.adreg = self.adreg + 1 self.op = (self.data.value() >> 5) & 0b111 self.hi5 = self.data.value() & 0x1F elif self.state == 1: self.adreg = (self.hi5 << 8) | self.data.value() elif self.state == 2: self.adreg = self.pc # ALU / Data Path if self.op == Decoder.REG_A | Decoder.OP_ADD: # print(' add a {} + {}'.format(self.acc, self.data.value())) self.acc = ((self.acc & 0xFF) + self.data.value()) & 0x1FF # print(' = {}'.format(self.acc)) elif self.op == Decoder.REG_A | Decoder.OP_NOR: # print(' nor a {} + {}'.format(self.acc, self.data.value())) carry = self.acc & 0b100000000 value = self.acc & 0xFF nor = (~(value | self.data.value())) & 0xFF self.acc = carry | nor # print(' = {}'.format(self.acc)) elif self.op == Decoder.REG_X | Decoder.OP_ADD: # print(' add x {} + {}'.format(self.x, self.data.value())) self.x = ((self.x & 0xFF) + self.data.value()) & 0x1FF elif self.op == Decoder.REG_X | Decoder.OP_NOR: # print(' nor x {} + {}'.format(self.x, self.data.value())) carry = self.x & 0b100000000 value = self.x & 0xFF nor = (~(value | self.data.value())) & 0xFF self.x = carry | nor elif (self.op & Decoder.MASK_OP) == Decoder.OP_J: # Clear carry on all non-taken jumps. # print(' j not taken') self.acc = self.acc & 0xFF elif (self.op & Decoder.MASK_OP) == Decoder.OP_ST: # print(' sta / stx') pass else: print(" unknown op") else: print("unknown state") # State machine if self.state == 0: # print('get next byte') self.state = 1 elif self.state == 2: self.state = 0 elif self.state == 1: if (self.op & Decoder.MASK_OP) == Decoder.OP_J: # print(' maybe jump {} {}'.format(self.acc >> 8, self.acc)) if self.op & Decoder.MASK_REG == Decoder.REG_A and ( self.acc & 0b100000000): # print(' jcc not taken') self.state = 2 elif (self.op & Decoder.MASK_REG == Decoder.REG_X and (self.acc & 0xFF) == 0): # print(' jnz not taken') self.state = 2 else: # print(' branch taken') self.state = 0 else: self.state = 2 # print(' going to state={} op={:03b}'.format(self.state, self.op)) if self.op & Decoder.MASK_REG == 0: # print('offset by x', self.x) self.adreg += self.x else: print("unknown state") clk = self.clk.value() # print('addr: {:04x}'.format(self.adreg & 0x1fff)) self.addr <<= self.adreg & 0x1FFF if self.state == 2 and self.op == Decoder.REG_A | Decoder.OP_ST: self.data <<= self.acc & 0xFF elif self.state == 2 and self.op == Decoder.REG_X | Decoder.OP_ST: self.data <<= self.x & 0xFF else: self.data <<= None if clk == 1: self.oe <<= 0 self.we <<= 0 else: if self.state == 2 and (self.op & Decoder.MASK_OP) == Decoder.OP_ST: self.oe <<= 0 else: self.oe <<= 1 if self.state == 2 and (self.op & Decoder.MASK_OP) == Decoder.OP_ST: self.we <<= 1 else: self.we <<= 0