/** * Programmable CPU to run arbitrary assembly. * clk, reset parameters behave as expected. * inputs are data from the outside world, that are read via CPU instruction. * prog, pinst, and paddr are all used to program the CPU: * - prog is a flag. When high, instead of executing, it writes instructions to memory. * - paddr is the address at which instructions are inserted. */ module cpu (input logic clk, reset, input logic prog, input logic [15:0] inputs, input logic[31:0] pinst, input logic[7:0] paddr, output logic [31:0] disp); logic [7:0] pc; logic [7:0] pc_next, pc_compute; logic [31:0] inst; logic [5:0] op; logic [2:0] rd, rs, rt; logic [31:0] rd_val, rs_val, rt_val; logic [15:0] const_val; logic [31:0] const_extend; logic [31:0] cpu_disp; logic [31:0] reg_alu_out, const_alu_out, val_out; logic should_jump, should_write, use_const; assign op = inst[31:26]; assign rd = inst[25:23]; assign rs = inst[22:20]; assign rt = inst[19:17]; assign const_val = inst[15:0]; assign should_write = inst[31]; assign use_const = inst[30]; assign should_jump = inst[29]; assign const_extend = const_val; registers #(32) regs( .raddr1(rs), .raddr2(rt), .waddr(rd), .in(rd_val), .wen(should_write), .clk(clk), .reset(reset), .out1(rs_val), .out2(rt_val)); memory #(32) insts( .raddr(pc), .waddr(paddr), .wen(prog), .in(pinst), .clk(clk), .out(inst), .reset(reset)); alu #(32) reg_alu( .left(rs_val), .right(rt_val), .op(inst[28:26]), .out(reg_alu_out)); alu #(32) const_alu( .left(rs_val), .right(const_extend), .op(inst[28:26]), .out(const_alu_out)); mux2 #(32) out_mux( .left(reg_alu_out), .right(const_alu_out), .select(use_const), .out(val_out)); mux2 #(32) rd_mux( .left(val_out), .right({16'b0, inputs}), .select(~inst[28] & inst[27] & inst[26]), .out(rd_val)); assign pc_compute = rt_val + const_val; mux2 #(8) pc_mux( .left(pc + 8'b01), .right(pc_compute), .select(should_jump & (inst[28] | (inst[26] ^ (rs_val == 0)))), .out(pc_next)); always_ff@(posedge clk) if(reset) begin pc <= 0; cpu_disp <= 0; end else if(!prog) begin case(op) 6'b0000000: cpu_disp <= rs_val; endcase pc <= pc_next; end assign disp = cpu_disp; endmodule