/** * Controller to interface CPU with the outside world. * The clk and reset inputs work as expected. * Inputs are fed in from the various input sources, * and given directly to CPU. * spi_clk, spi_ss and spi_mosi are SPI connections used to program the CPU. * Outputs displayed from the CPU disp instruction. */ module cpu_controller(input logic clk, reset, input logic [11:0] inputs, input logic spi_clk, spi_ss, spi_mosi, output logic [11:0] outputs); logic [31:0] inst; logic [7:0] addr; logic [19:0] the_void; logic prog; logic en; logic inst_ready; logic inst_done; logic inst_ready_edge; logic cpu_clk; edge_detector inst_ready_detector( .in(inst_ready), .clk(clk), .reset(reset), .pos_edge(inst_ready_edge)); logic prog_forward_clk; assign prog_forward_clk = inst_ready_edge & ~inst_done & prog; assign cpu_clk = reset | (en ? clk : prog_forward_clk); spi_slave prog_slave( .clk(clk), .reset(reset), .master_clk(spi_clk), .ss(spi_ss), .mosi(spi_mosi), .ready(inst_ready), .done(inst_done), .data(inst)); cpu cpu_unit( .clk(cpu_clk), .inputs({4'b0, inputs}), .reset(reset), .prog(prog), .pinst(inst), .paddr(addr), .disp({the_void, outputs})); always_ff@(posedge clk) if (reset) begin prog <= 0; en <= 0; addr <= 0; end else begin en <= inst_done; prog <= (prog & ~inst_done) | (inst_ready_edge & (inst == 32'hCAFEBABE)); addr <= addr + prog_forward_clk; end endmodule