output1 = [0] * 32768 output2 = [0] * 32768 # define opcodes LDA = 0b00001 ADD = 0b00010 SUB = 0b00011 STA = 0b00100 LDI = 0b00101 JMP = 0b00110 JZ = 0b00111 JC = 0b01000 OUT = 0b01110 HALT = 0b01111 # define control signals HLT = 0b1000000000000000 MI = 0b0100000000000000 RI = 0b0010000000000000 RO = 0b0001000000000000 IO = 0b0000100000000000 II = 0b0000010000000000 AI = 0b0000001000000000 AO = 0b0000000100000000 EO = 0b0000000010000000 SU = 0b0000000001000000 BI = 0b0000000000100000 OI = 0b0000000000010000 CE = 0b0000000000001000 CO = 0b0000000000000100 J = 0b0000000000000010 FI = 0b0000000000000001 # define CPU flags EEPROM address bits CF_ADDR_BIT = 14 ZF_ADDR_BIT = 13 # define microcode array microcode = [ [LDA, MI|CO, RO|II|CE, MI|CO, RO|MI|CE, RO|AI] , [ADD, MI|CO, RO|II|CE, MI|CO, RO|MI|CE, RO|BI, AI|EO|FI], [SUB, MI|CO, RO|II|CE, MI|CO, RO|MI|CE, RO|BI, AI|EO|SU|FI], [STA, MI|CO, RO|II|CE, MI|CO, RO|MI|CE, AO|RI], [LDI, MI|CO, RO|II|CE, MI|CO, RO|AI|CE], [JMP, MI|CO, RO|II|CE, MI|CO, RO|J], [JZ, MI|CO, RO|II|CE, CE], [JC, MI|CO, RO|II|CE, CE], [OUT, MI|CO, RO|II|CE, AO|OI], [HALT, MI|CO, RO|II|CE, HLT] ] # populate ROM with the first two micro-instruction stages for all possible opcodes for i in range(4096): address = i << 3 output1[address] = ((MI|CO) & 0xFF00) >> 8 output1[address+1] = ((RO|II|CE) & 0xFF00) >> 8 output2[address] = (MI|CO) & 0x00FF output2[address+1] = (RO|II|CE) & 0x00FF # load ROM with micro-instructions for cf in [0,1]: for zf in [0,1]: # calculate base address as a function of CF and ZF base_addr = (cf * 2 ** CF_ADDR_BIT) | (zf * 2 ** ZF_ADDR_BIT) # set up JC microcode according to CF flag value if cf == 1: # override default JC micro-code for CF = 1 microcode[7] = [JC, MI|CO, RO|II|CE, MI|CO, RO|J] else: microcode[7] = [JC, MI|CO, RO|II|CE, CE] # set up JZ microcode according to ZF flag value if zf == 1: # override default JZ micro-code for ZF = 1 microcode[6] = [JZ, MI|CO, RO|II|CE, MI|CO, RO|J] else: microcode[6] = [JZ, MI|CO, RO|II|CE, CE] # populate micro-code for inst in microcode: opCode = inst[0] signals = inst[1:] for stage, signal in enumerate(signals): address = base_addr | (opCode << 3) | stage output1[address] = (signal & 0xFF00) >> 8 output2[address] = signal & 0x00FF with open('eeprom1.bin', 'wb') as file1: for x in output1: file1.write(x.to_bytes(1, byteorder='big', signed=False)) with open('eeprom2.bin', 'wb') as file2: for x in output2: file2.write(x.to_bytes(1, byteorder='big', signed=False))