#include #include #include using namespace std; using namespace chdl; // All of our basic types, in case we want to change the word size or number of // registesr later. const unsigned INST_SZ(16), IMEM_SZ(8), WORD_SZ(8); typedef bvec inst_t; typedef bvec word_t; typedef bvec<3> rname_t; word_t LitW(unsigned n) { return Lit(n); } // Instruction memory; we use a Harvard architecture. inst_t InstMem(const word_t &a) { return LLRom(Zext(a), "demo.hex"); } void RegFile(word_t &s0out, word_t &s1out, rname_t s0, rname_t s1, rname_t d, word_t dest_val, node wr) { TAP(wr); TAP(dest_val); TAP(s0); TAP(s1); TAP(d); vec<8, word_t> regs; TAP(regs); for (unsigned i = 0; i < 8; ++i) regs[i] = Wreg(wr && d == Lit<3>(i), dest_val); s0out = Mux(s0, regs); s1out = Mux(s1, regs); } void Cpu() { // Program Counter word_t pc, next_pc; pc = Reg(next_pc); TAP(pc); TAP(next_pc); // Instruction Register inst_t ir(InstMem(pc)); bvec<2> op(ir[range<14,15>()]); TAP(ir); // Register File word_t s0val, s1val, dval; RegFile( s0val, s1val, ir[range<8,10>()], ir[range<5,7>()], ir[range<11,13>()], dval, op == Lit<2>(1) || op == Lit<2>(2) || op == Lit<2>(3) ); TAP(s0val); TAP(s1val); // Compute next program counter Cassign(next_pc). IF(op == Lit<2>(0) && OrN(s0val), pc + LitW(1) + Sext(ir[range<0,7>()])). ELSE(pc + LitW(1)); // Compute value to be written to destination register Cassign(dval). IF(op == Lit<2>(1), s0val + s1val). // 1: add IF(op == Lit<2>(2), s0val - s1val). // 2: sub IF(op == Lit<2>(3), Sext(ir[range<0,7>()])). // 3: ldi ELSE(LitW(0)); } int main() { Cpu(); optimize(); ofstream vcd("demo.vcd"); run(vcd, 1000); return 0; }