/* * pico16s.sfl */ module pico16 { submod_type alu16 { input a<16>, b<16>; output y<16>; instrin sa, sb; instrin and, or, xor, not; instrin add, sub; instrin sll, srl, sra; instrin rol, ror; instrin sgt, slt, seq; instrin sge, sle, sne; /* not slt, not sgt, not seq */ instrin ldl, ldh; instr_arg sa(a, b); /* no operation */ instr_arg sb(a, b); /* no operation */ instr_arg and(a, b); /* logical AND */ instr_arg or(a, b); /* logical OR */ instr_arg xor(a, b); /* logical Exclusive-OR */ instr_arg not(a, b); /* logical not */ instr_arg add(a, b); /* addition */ instr_arg sub(a, b); /* subtraction */ instr_arg sll(a, b); /* shift left logical */ instr_arg srl(a, b); /* shift right logical */ instr_arg sra(a, b); /* shift right arithmetic */ instr_arg rol(a, b); /* rotate left */ instr_arg ror(a, b); /* rotate right */ instr_arg sgt(a, b); /* greater (neither less nor equal) */ instr_arg slt(a, b); /* less (neither greater nor equal) */ instr_arg seq(a, b); /* equal */ instr_arg sge(a, b); /* greater or equal */ instr_arg sle(a, b); /* less or equal */ instr_arg sne(a, b); /* not equal */ instr_arg ldl(a, b); /* load low */ instr_arg ldh(a, b); /* load high */ } /* alu16 */ submod_type dec4to16 { input a<4>; output y0, y1, y2, y3, y4, y5, y6, y7; output y8, y9, y10, y11, y12, y13, y14, y15; instrin enable; instr_arg enable(a); } /* dec4to16 */ circuit_class ram16x16 { input A<4>; input D<16>; output O<16>; mem cell[16]<16>; instrin read; instrin write; instruct_arg read(A); instruct_arg write(A, D); instruct read O = cell[A]; instruct write cell[A] := D; } input datain<16>; /* data input */ output dataout<16>; /* data output */ output address<16>; /* address */ output oe; /* output enable (LOW) */ output we; /* write enable (LOW) */ /* for monitor */ output m_s1bus<16>, m_s2bus<16>, m_dbus<16>, m_pc<16>; instrin start; alu16 ALU; dec4to16 OP, FUNC; ram16x16 BANK1; ram16x16 BANK2; reg pc<16>; /* program counter */ reg ir<16>; /* instruction register */ reg rd_buf<16>, rs_buf<16>; tmp s1bus<16>, s2bus<16>, dbus<16>; tmp zero; stage_name stage_a { task run(); } instruct start generate stage_a.run(); stage stage_a { state_name init; state_name if; state_name rr; state_name ex; first_state init; par { address = s1bus; dataout = dbus; zero = ^/|rd_buf; OP.enable(ir<15:12>); FUNC.enable(ir<7:4>); /* for monitor */ m_s1bus = s1bus; m_s2bus = s2bus; m_dbus = dbus; m_pc = pc; } /* initialize */ state init par { oe = 0b1; we = 0b1; pc := 0x0000; goto if; } /* instruction fetch */ state if par { oe = 0b0; we = 0b1; s1bus = pc; dbus = datain; ir := dbus; goto rr; } /* register read */ state rr par { oe = 0b1; we = 0b1; s1bus = pc; s2bus = 0x0002; dbus = ALU.add(s1bus, s2bus).y; pc := dbus; alt { OP.y1: /* JAL */ par { BANK1.write(0b1111, dbus); BANK2.write(0b1111, dbus); } OP.y5: /* JALR */ par { BANK1.write(0b1111, dbus); BANK2.write(0b1111, dbus); } OP.y2: /* BEQZ */ rd_buf := BANK1.read(0b1111).O; OP.y3: /* BNEZ */ rd_buf := BANK1.read(0b1111).O; else: par { rd_buf := BANK1.read(ir<11:8>).O; rs_buf := BANK2.read(ir<3:0>).O; } } goto ex; } /* execute */ state ex par { /* s1bus */ alt { ^ir<15> & ^ir<14>: /* J type func */ s1bus = pc; OP.y15 & FUNC.y3: /* LD */ s1bus = rs_buf; else: s1bus = rd_buf; } /* s2bus */ alt { ^ir<15> & ^ir<14>: /* J type func */ s2bus = 16 # ir<11:0>; ir<15> & ir<14> & ir<13> & ^ir<12> & ^ir<7>: /* I2 type func */ s2bus = 0b00000000 || ir<7:0>; ir<15> & ir<14> & ir<13>: /* R type func */ s2bus = rs_buf; else: /* I1 type func */ s2bus = 0b00000000 || ir<7:0>; } /* dbus */ alt { OP.y0: /* J */ dbus = ALU.add(s1bus, s2bus).y; OP.y1: /* JAL */ dbus = ALU.add(s1bus, s2bus).y; OP.y2: /* BEQZ */ dbus = ALU.add(s1bus, s2bus).y; OP.y3: /* BNEZ */ dbus = ALU.add(s1bus, s2bus).y; OP.y4: /* JR */ dbus = ALU.sa(s1bus, s2bus).y; OP.y5: /* JALR */ dbus = ALU.sa(s1bus, s2bus).y; OP.y6: /* LDL */ dbus = ALU.ldl(s1bus, s2bus).y; OP.y7: /* LDH */ dbus = ALU.ldh(s1bus, s2bus).y; OP.y8: /* ANDI */ dbus = ALU.and(s1bus, s2bus).y; OP.y9: /* ORI */ dbus = ALU.or(s1bus, s2bus).y; OP.y10: /* XORI */ dbus = ALU.xor(s1bus, s2bus).y; OP.y12: /* ADDI */ dbus = ALU.add(s1bus, s2bus).y; OP.y13: /* SUBI */ dbus = ALU.sub(s1bus, s2bus).y; OP.y14: /* func1 */ alt { FUNC.y0: /* SRLI */ dbus = ALU.srl(s1bus, s2bus).y; FUNC.y1: /* SLLI */ dbus = ALU.sll(s1bus, s2bus).y; FUNC.y2: /* SRAI */ dbus = ALU.sra(s1bus, s2bus).y; FUNC.y4: /* RORI */ dbus = ALU.ror(s1bus, s2bus).y; FUNC.y5: /* ROLI */ dbus = ALU.rol(s1bus, s2bus).y; FUNC.y8: /* SRL */ dbus = ALU.srl(s1bus, s2bus).y; FUNC.y9: /* SLL */ dbus = ALU.sll(s1bus, s2bus).y; FUNC.y10: /* SRA */ dbus = ALU.sra(s1bus, s2bus).y; FUNC.y12: /* ROR */ dbus = ALU.ror(s1bus, s2bus).y; FUNC.y13: /* ROL */ dbus = ALU.rol(s1bus, s2bus).y; } OP.y15: /* func2 */ alt { FUNC.y0: /* SGT */ dbus = ALU.sgt(s1bus, s2bus).y; FUNC.y1: /* SLT */ dbus = ALU.slt(s1bus, s2bus).y; FUNC.y2: /* SEQ */ dbus = ALU.seq(s1bus, s2bus).y; FUNC.y3: /* LD */ dbus = datain; FUNC.y4: /* SLE */ dbus = ALU.sle(s1bus, s2bus).y; FUNC.y5: /* SGE */ dbus = ALU.sge(s1bus, s2bus).y; FUNC.y6: /* SNE */ dbus = ALU.sne(s1bus, s2bus).y; FUNC.y7: /* ST */ dbus = ALU.sb(s1bus, s2bus).y; FUNC.y8: /* AND */ dbus = ALU.and(s1bus, s2bus).y; FUNC.y9: /* OR */ dbus = ALU.or(s1bus, s2bus).y; FUNC.y10: /* XOR */ dbus = ALU.xor(s1bus, s2bus).y; FUNC.y11: /* MOV */ dbus = ALU.sb(s1bus, s2bus).y; FUNC.y12: /* ADD */ dbus = ALU.add(s1bus, s2bus).y; FUNC.y13: /* SUB */ dbus = ALU.sub(s1bus, s2bus).y; } } /* output */ alt { OP.y0: /* J */ pc := dbus; OP.y4: /* JR */ pc := dbus; OP.y1: /* JAL */ pc := dbus; OP.y5: /* JALR */ pc := dbus; OP.y2: /* BEQZ */ alt { zero: pc := dbus; } OP.y3: /* BNEZ */ alt { ^zero: pc := dbus; } ^(OP.y15 & FUNC.y7): /* ST */ par { BANK1.write(ir<11:8>, dbus); BANK2.write(ir<11:8>, dbus); } } alt { OP.y15 & FUNC.y3: /* LD */ par { oe = 0b0; we = 0b1; } OP.y15 & FUNC.y7: /* ST */ par { oe = 0b1; we = 0b0; } else: par { oe = 0b1; we = 0b1; } } goto if; } } /* stage_a */ } /* pico16 */ %i "alu16.sfl" %i "add16c.sfl" %i "brlsft16.sfl" %i "dec4to16.sfl"