// pipe2.e fetch instructions and pass through stages // assume the instructions are load word, load from data memory // needs add32 component // component: greg general register set // memory is internal, a1 address reads and outputs on out1 // a2 address reads and outputs on out2 // aw address writes input on wr & clk falling define greg(a1[5], a2[5], aw[5], input[32], wr, clk, out1[32], out2[32]) memory mr[1024]; // 32 registers of 32 bits each circuits mr read out1 from a1.#b00000 when #b1; // always available mr read out2 from a2.#b00000 when #b1; mr write input to aw.#b00000 when wr&(aw[0]|aw[1]|aw[2]|aw[3]|aw[4]) on falling clk; end circuits; end greg; // component: dmem data memory // addr 32 bit address to read or write // data 32 bit data to write into memory // outp 32 bit data read from memory // wr 1 for write, 0 for read write on falling clock define dmem(addr[32], data[32], wr, clk, outp[32]) memory mr[4096]; // 128 words of 32 bits each circuits mr read outp from addr[15:2].#b00000 when #b1; // always available mr write data to addr[15:2].#b00000 when wr on falling clk; end circuits; end dmem; // component: inst_mem has instruction memory, pc increment and fetch // pc is address, inst is instruction read from pc // pc gets 4 added to it on falling clk, 4 bytes is one instruction define inst_mem(pc[32], inst[32], clk) memory mr[1024]; // will hold up to 32, 32 bit instructions signal four[32] <= #h00000004; signal a_in[32]; signal a_out[32]; signal cin <= #b0; signal cout; circuits mr read inst from pc[6:0].#b000 when #b1; // always available // all of this stuff is a sloppy way to increment the pc pc_incr use add32(four, a_in, cin, a_out, cout); a_in <= pc after 1ns; pc <= a_out on falling clk; end circuits; end inst_mem; // clock generator and enable controlled counter component define cntr5(clk, enb, cntr[5]) // 5 bit counter circuits clk <= ~clk after 100ns; cntr[0] <= ~cntr[0] when enb else cntr[0] on falling clk after 1ns; cntr[1] <= ~cntr[1] on falling cntr[0] after 1ns; cntr[2] <= ~cntr[2] on falling cntr[1] after 1ns; cntr[3] <= ~cntr[3] on falling cntr[2] after 1ns; cntr[4] <= ~cntr[4] on falling cntr[3] after 1ns; end circuits; end cntr5; // IF STAGE SIGNALS - instruction fetch and program counter signal pc[32] <= #h00000000; // program counter signal inst[32]; // instruction from memory at program counter // ID STAGE SIGNALS - instruction decode and register read (write) signal ir_s1[32]; // Instruction register, pipeline stage 1 signal a_to_s2[32]; // A output of general register signal b_to_s2[32]; // B output of general register signal c_to_s2[32]; // sign extended low 16 bits of instruction signal wr_reg <= #b0; // write into register signal regdst <= #b0; // register destination selection, 1=rr_op signal rdto_s2[5]; // register destination from ir_s1 signal s; // sign bit for sign extend // EX STAGE SIGNALS - execute signal ir_s2[32]; // Instruction register, pipeline stage 2 signal a_s2[32]; // A value register, pipeline stage 2 signal b_s2[32]; // B value register, pipeline stage 2 signal c_s2[32]; // C value register, pipeline stage 2 signal rd_s2[5]; // register destination, pipeline stage 2 signal bb_s2[32]; // output of multiplexer signal a_to_s3[32]; // A input to stage 3 (computed in stage 2) signal cin <= #b0; // 32 bit adder carry input signal cout; // 32 bit adder carry output signal alusrc <= #b1; // ALU source C or B // MEM STAGE SIGNALS - data memory read and write signal ir_s3[32]; // Instruction register, pipeline stage 3 signal a_s3[32]; // A value register, pipeline stage 3 signal b_s3[32]; // B value register, pipeline stage 3 signal rd_s3[5]; // register destination, pipeline stage 3 signal a_to_s4[32]; // A input to stage 4 (computed in stage 3) signal wr_mem <= #b0; // write into memory // WB STAGE SIGNALS - write back mux signal ir_s4[32]; // Instruction register, pipeline stage 4 signal a_s4[32]; // A value register, pipeline stage 4 signal b_s4[32]; // B value register, pipeline stage 4 signal rd_s4[5]; // register destination, pipeline stage 4 signal a_to_greg[32]; // input to general register for write signal memtoreg <= #b1;// memory to be written into register // SYSTEM SIGNALS signal clk <= #b0; // main system clock signal clk_ <= #b1; // clock bar, inverted clock signal cntr[5] <= #b00000; // just used for output labeling here signal enb <= #b1; // counter enable, must be 1 to count circuits // IF STAGE CIRCUITS inst_mem use inst_mem(pc, inst, clk); // inst is the output // ID STAGE CIRCUITS ir_s1 <= inst on falling clk; // move instruction through pipeline greg use greg (ir_s1[25:21], ir_s1[20:16], rd_s4, a_to_greg, wr_reg, clk_, a_to_s2, b_to_s2); c_to_s2 <= s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.ir_s1[15:0] after 1ns; // use 16 sign bits with low 16 bits of IR and s <= ir_s1[15] after 1ns; // sign bit for extend regdst <= ir_s1[28] after 1ns; rdto_s2 <= ir_s1[15:11] when regdst else ir_s1[20:16] after 1ns; // mux // fix, rdto_s2 should be set to zero for beq, jump, sw in ir_s1 // EX STAGE CIRCUITS ir_s2 <= ir_s1 on falling clk; // move instruction through pipeline a_s2 <= a_to_s2 on falling clk; // move A through pipeline b_s2 <= b_to_s2 on falling clk; // move B through pipeline c_s2 <= c_to_s2 on falling clk; // move C through pipeline rd_s2 <= rdto_s2 on falling clk; // move rd through pipeline add32 use add32 (a_s2, bb_s2, cin, a_to_s3, cout); // replace simple adder above with alu component bb_s2 <= c_s2 when alusrc else b_s2 after 1ns; // mux // MEM STAGE CIRCUITS ir_s3 <= ir_s2 on falling clk; // move instruction through pipeline a_s3 <= a_to_s3 on falling clk; // move A through pipeline b_s3 <= b_s2 on falling clk; // move B through pipeline rd_s3 <= rd_s2 on falling clk; // move rd through pipeline dmem use dmem (a_s3, b_s3, wr_mem, clk_, a_to_s4); // WB STAGE CIRCUITS ir_s4 <= ir_s3 on falling clk; // move instruction through pipeline a_s4 <= a_to_s4 on falling clk; // move A through pipeline b_s4 <= a_s3 on falling clk; // move B through pipeline rd_s4 <= rd_s3 on falling clk; // move rd through pipeline a_to_greg <= a_s4 when memtoreg else b_s4 after 1ns; // mux // memtoreg <= compute #b1 for lw in ir_s4 wr_reg <= ir_s4[31] after 1ns; // fix, #b1 for lw, ai, rr_op // SYSTEM CIRCUITS clock use cntr5 (clk, enb, cntr); // clk and cntr are output clk_ <= ~clk after 1ns; // inverted clock to trigger on clock rising edge end circuits;