Add comments.
This commit is contained in:
parent
d00131973b
commit
672eae920a
22
alu.sv
22
alu.sv
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Arithmetic Logic Unit, as described in our book. This is a general
|
||||||
|
* purpose aritmetic circuit. The width parameter specifies the operand width,
|
||||||
|
* and left and right are the operands. op is the instruction, which decodes as
|
||||||
|
* follows:
|
||||||
|
|
||||||
|
* 000 left AND right
|
||||||
|
* 001 left OR right
|
||||||
|
* 010 left + right
|
||||||
|
* 011 unused
|
||||||
|
* 000 left AND NOT right
|
||||||
|
* 001 left OR NOT right
|
||||||
|
* 010 left - right
|
||||||
|
* 011 SLT left, right
|
||||||
|
*
|
||||||
|
*/
|
||||||
module alu #(width=32)
|
module alu #(width=32)
|
||||||
(input logic [width-1:0] left, right,
|
(input logic [width-1:0] left, right,
|
||||||
input logic [2:0] op,
|
input logic [2:0] op,
|
||||||
|
@ -9,13 +25,13 @@ module alu #(width=32)
|
||||||
.right(not_right),
|
.right(not_right),
|
||||||
.select(op[2]),
|
.select(op[2]),
|
||||||
.out(selected_right));
|
.out(selected_right));
|
||||||
|
|
||||||
logic [width-1:0] op_and, op_or, op_sum, op_slt;
|
logic [width-1:0] op_and, op_or, op_sum, op_slt;
|
||||||
assign op_and = left & selected_right;
|
assign op_and = left & selected_right;
|
||||||
assign op_or = left | selected_right;
|
assign op_or = left | selected_right;
|
||||||
assign op_sum = left + selected_right + op[2];
|
assign op_sum = left + selected_right + op[2];
|
||||||
assign op_slt = op_sum[width-1];
|
assign op_slt = op_sum[width-1];
|
||||||
|
|
||||||
mux4 output_mux(
|
mux4 output_mux(
|
||||||
.first(op_and),
|
.first(op_and),
|
||||||
.second(op_or),
|
.second(op_or),
|
||||||
|
@ -23,4 +39,4 @@ module alu #(width=32)
|
||||||
.fourth(op_slt),
|
.fourth(op_slt),
|
||||||
.select(op[1:0]),
|
.select(op[1:0]),
|
||||||
.out(out));
|
.out(out));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
38
cpu.sv
38
cpu.sv
|
@ -1,3 +1,11 @@
|
||||||
|
/**
|
||||||
|
* 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,
|
module cpu (input logic clk, reset,
|
||||||
input logic prog,
|
input logic prog,
|
||||||
input logic [15:0] inputs,
|
input logic [15:0] inputs,
|
||||||
|
@ -15,19 +23,19 @@ module cpu (input logic clk, reset,
|
||||||
logic [31:0] cpu_disp;
|
logic [31:0] cpu_disp;
|
||||||
logic [31:0] reg_alu_out, const_alu_out, val_out;
|
logic [31:0] reg_alu_out, const_alu_out, val_out;
|
||||||
logic should_jump, should_write, use_const;
|
logic should_jump, should_write, use_const;
|
||||||
|
|
||||||
assign op = inst[31:26];
|
assign op = inst[31:26];
|
||||||
assign rd = inst[25:23];
|
assign rd = inst[25:23];
|
||||||
assign rs = inst[22:20];
|
assign rs = inst[22:20];
|
||||||
assign rt = inst[19:17];
|
assign rt = inst[19:17];
|
||||||
assign const_val = inst[15:0];
|
assign const_val = inst[15:0];
|
||||||
|
|
||||||
assign should_write = inst[31];
|
assign should_write = inst[31];
|
||||||
assign use_const = inst[30];
|
assign use_const = inst[30];
|
||||||
assign should_jump = inst[29];
|
assign should_jump = inst[29];
|
||||||
|
|
||||||
assign const_extend = const_val;
|
assign const_extend = const_val;
|
||||||
|
|
||||||
registers #(32) regs(
|
registers #(32) regs(
|
||||||
.raddr1(rs),
|
.raddr1(rs),
|
||||||
.raddr2(rt),
|
.raddr2(rt),
|
||||||
|
@ -38,7 +46,7 @@ module cpu (input logic clk, reset,
|
||||||
.reset(reset),
|
.reset(reset),
|
||||||
.out1(rs_val),
|
.out1(rs_val),
|
||||||
.out2(rt_val));
|
.out2(rt_val));
|
||||||
|
|
||||||
memory #(32) insts(
|
memory #(32) insts(
|
||||||
.raddr(pc),
|
.raddr(pc),
|
||||||
.waddr(paddr),
|
.waddr(paddr),
|
||||||
|
@ -47,31 +55,31 @@ module cpu (input logic clk, reset,
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.out(inst),
|
.out(inst),
|
||||||
.reset(reset));
|
.reset(reset));
|
||||||
|
|
||||||
alu #(32) reg_alu(
|
alu #(32) reg_alu(
|
||||||
.left(rs_val),
|
.left(rs_val),
|
||||||
.right(rt_val),
|
.right(rt_val),
|
||||||
.op(inst[28:26]),
|
.op(inst[28:26]),
|
||||||
.out(reg_alu_out));
|
.out(reg_alu_out));
|
||||||
|
|
||||||
alu #(32) const_alu(
|
alu #(32) const_alu(
|
||||||
.left(rs_val),
|
.left(rs_val),
|
||||||
.right(const_extend),
|
.right(const_extend),
|
||||||
.op(inst[28:26]),
|
.op(inst[28:26]),
|
||||||
.out(const_alu_out));
|
.out(const_alu_out));
|
||||||
|
|
||||||
mux2 #(32) out_mux(
|
mux2 #(32) out_mux(
|
||||||
.left(reg_alu_out),
|
.left(reg_alu_out),
|
||||||
.right(const_alu_out),
|
.right(const_alu_out),
|
||||||
.select(use_const),
|
.select(use_const),
|
||||||
.out(val_out));
|
.out(val_out));
|
||||||
|
|
||||||
mux2 #(32) rd_mux(
|
mux2 #(32) rd_mux(
|
||||||
.left(val_out),
|
.left(val_out),
|
||||||
.right({16'b0, inputs}),
|
.right({16'b0, inputs}),
|
||||||
.select(~inst[28] & inst[27] & inst[26]),
|
.select(~inst[28] & inst[27] & inst[26]),
|
||||||
.out(rd_val));
|
.out(rd_val));
|
||||||
|
|
||||||
assign pc_compute = rt_val + const_val;
|
assign pc_compute = rt_val + const_val;
|
||||||
|
|
||||||
mux2 #(8) pc_mux(
|
mux2 #(8) pc_mux(
|
||||||
|
@ -79,8 +87,8 @@ module cpu (input logic clk, reset,
|
||||||
.right(pc_compute),
|
.right(pc_compute),
|
||||||
.select(should_jump & (inst[28] | (inst[26] ^ (rs_val == 0)))),
|
.select(should_jump & (inst[28] | (inst[26] ^ (rs_val == 0)))),
|
||||||
.out(pc_next));
|
.out(pc_next));
|
||||||
|
|
||||||
always_ff@(posedge clk)
|
always_ff@(posedge clk)
|
||||||
if(reset) begin
|
if(reset) begin
|
||||||
pc <= 0;
|
pc <= 0;
|
||||||
cpu_disp <= 0;
|
cpu_disp <= 0;
|
||||||
|
@ -90,7 +98,7 @@ module cpu (input logic clk, reset,
|
||||||
endcase
|
endcase
|
||||||
pc <= pc_next;
|
pc <= pc_next;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign disp = cpu_disp;
|
assign disp = cpu_disp;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/**
|
||||||
|
* 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,
|
module cpu_controller(input logic clk, reset,
|
||||||
input logic [11:0] inputs,
|
input logic [11:0] inputs,
|
||||||
input logic spi_clk, spi_ss, spi_mosi,
|
input logic spi_clk, spi_ss, spi_mosi,
|
||||||
|
@ -7,23 +15,23 @@ module cpu_controller(input logic clk, reset,
|
||||||
logic [19:0] the_void;
|
logic [19:0] the_void;
|
||||||
logic prog;
|
logic prog;
|
||||||
logic en;
|
logic en;
|
||||||
|
|
||||||
logic inst_ready;
|
logic inst_ready;
|
||||||
logic inst_done;
|
logic inst_done;
|
||||||
logic inst_ready_edge;
|
logic inst_ready_edge;
|
||||||
|
|
||||||
logic cpu_clk;
|
logic cpu_clk;
|
||||||
|
|
||||||
edge_detector inst_ready_detector(
|
edge_detector inst_ready_detector(
|
||||||
.in(inst_ready),
|
.in(inst_ready),
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.out(inst_ready_edge));
|
.out(inst_ready_edge));
|
||||||
|
|
||||||
logic prog_forward_clk;
|
logic prog_forward_clk;
|
||||||
|
|
||||||
assign prog_forward_clk = inst_ready_edge & ~inst_done & prog;
|
assign prog_forward_clk = inst_ready_edge & ~inst_done & prog;
|
||||||
assign cpu_clk = reset | (en ? clk : prog_forward_clk);
|
assign cpu_clk = reset | (en ? clk : prog_forward_clk);
|
||||||
|
|
||||||
spi_slave prog_slave(
|
spi_slave prog_slave(
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset(reset),
|
.reset(reset),
|
||||||
|
@ -33,7 +41,7 @@ module cpu_controller(input logic clk, reset,
|
||||||
.ready(inst_ready),
|
.ready(inst_ready),
|
||||||
.done(inst_done),
|
.done(inst_done),
|
||||||
.data(inst));
|
.data(inst));
|
||||||
|
|
||||||
cpu cpu_unit(
|
cpu cpu_unit(
|
||||||
.clk(cpu_clk),
|
.clk(cpu_clk),
|
||||||
.inputs({4'b0, inputs}),
|
.inputs({4'b0, inputs}),
|
||||||
|
@ -42,7 +50,7 @@ module cpu_controller(input logic clk, reset,
|
||||||
.pinst(inst),
|
.pinst(inst),
|
||||||
.paddr(addr),
|
.paddr(addr),
|
||||||
.disp({the_void, outputs}));
|
.disp({the_void, outputs}));
|
||||||
|
|
||||||
always_ff@(posedge clk)
|
always_ff@(posedge clk)
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
prog <= 0;
|
prog <= 0;
|
||||||
|
@ -53,5 +61,5 @@ module cpu_controller(input logic clk, reset,
|
||||||
prog <= (prog & ~inst_done) | (inst_ready_edge & (inst == 32'hCAFEBABE));
|
prog <= (prog & ~inst_done) | (inst_ready_edge & (inst == 32'hCAFEBABE));
|
||||||
addr <= addr + prog_forward_clk;
|
addr <= addr + prog_forward_clk;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Simple edge detector circuit. Takes in a clock and a signal,
|
||||||
|
* and produces an output of 1 when the signal changes from 0 to 1.
|
||||||
|
* Otherwise, the output is 0.
|
||||||
|
*/
|
||||||
module edge_detector(input logic in, clk,
|
module edge_detector(input logic in, clk,
|
||||||
output logic out);
|
output logic out);
|
||||||
logic old_in;
|
logic old_in;
|
||||||
|
|
||||||
always_ff@(posedge clk)
|
always_ff@(posedge clk)
|
||||||
old_in <= in;
|
old_in <= in;
|
||||||
|
|
||||||
assign out = in & ~old_in;
|
assign out = in & ~old_in;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
12
memory.sv
12
memory.sv
|
@ -1,3 +1,9 @@
|
||||||
|
/**
|
||||||
|
* CPU-specific memory. raddr is used for reading,
|
||||||
|
* while wen (write enable), waddr, and in are used in combination to write.
|
||||||
|
* Reads are performed immediately, but writes are performed on
|
||||||
|
* positive clock edge. Reset clears the memory to 0.
|
||||||
|
*/
|
||||||
module memory #(width=32)
|
module memory #(width=32)
|
||||||
(input logic [7:0] raddr, waddr,
|
(input logic [7:0] raddr, waddr,
|
||||||
input logic [width-1:0] in,
|
input logic [width-1:0] in,
|
||||||
|
@ -8,10 +14,10 @@ module memory #(width=32)
|
||||||
if(reset) begin
|
if(reset) begin
|
||||||
data <= '{default: 0};
|
data <= '{default: 0};
|
||||||
end else begin
|
end else begin
|
||||||
if(wen) begin
|
if(wen) begin
|
||||||
data[waddr] <= in;
|
data[waddr] <= in;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assign out = data[raddr];
|
assign out = data[raddr];
|
||||||
endmodule
|
endmodule
|
||||||
|
|
4
mux2.sv
4
mux2.sv
|
@ -1,6 +1,8 @@
|
||||||
|
/* A two-input multiplexer.
|
||||||
|
*/
|
||||||
module mux2 #(width=32)
|
module mux2 #(width=32)
|
||||||
(input logic [width-1:0] left, right,
|
(input logic [width-1:0] left, right,
|
||||||
input logic select,
|
input logic select,
|
||||||
output logic [width-1:0] out);
|
output logic [width-1:0] out);
|
||||||
assign out = select ? right : left;
|
assign out = select ? right : left;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
11
mux4.sv
11
mux4.sv
|
@ -1,10 +1,13 @@
|
||||||
|
/**
|
||||||
|
* A four-input multiplexer.
|
||||||
|
*/
|
||||||
module mux4 #(width=32)
|
module mux4 #(width=32)
|
||||||
(input logic [width-1:0] first, second, third, fourth,
|
(input logic [width-1:0] first, second, third, fourth,
|
||||||
input logic [1:0] select,
|
input logic [1:0] select,
|
||||||
output logic [width-1:0] out);
|
output logic [width-1:0] out);
|
||||||
|
|
||||||
logic [width-1:0] lower, upper;
|
logic [width-1:0] lower, upper;
|
||||||
|
|
||||||
mux2 lower_mux(
|
mux2 lower_mux(
|
||||||
.left(first),
|
.left(first),
|
||||||
.right(second),
|
.right(second),
|
||||||
|
@ -15,10 +18,10 @@ module mux4 #(width=32)
|
||||||
.right(fourth),
|
.right(fourth),
|
||||||
.select(select[0]),
|
.select(select[0]),
|
||||||
.out(upper));
|
.out(upper));
|
||||||
|
|
||||||
mux2 final_mux(
|
mux2 final_mux(
|
||||||
.left(lower),
|
.left(lower),
|
||||||
.right(upper),
|
.right(upper),
|
||||||
.select(select[1]),
|
.select(select[1]),
|
||||||
.out(out));
|
.out(out));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
12
register.sv
12
register.sv
|
@ -1,10 +1,16 @@
|
||||||
|
/**
|
||||||
|
* Register file as used by the CPU. Has two read addresses so that
|
||||||
|
* two-register instructions can be performed in one cycle. Just like memory,
|
||||||
|
* reading is asynchronous, while writes occur on positive clock edge.
|
||||||
|
* wen, waddr, and in are used to write to register memory.
|
||||||
|
*/
|
||||||
module registers #(width=32)
|
module registers #(width=32)
|
||||||
(input logic [2:0] raddr1, raddr2, waddr,
|
(input logic [2:0] raddr1, raddr2, waddr,
|
||||||
input clk, wen, reset,
|
input clk, wen, reset,
|
||||||
input logic [width-1:0] in,
|
input logic [width-1:0] in,
|
||||||
output logic [width-1:0] out1, out2);
|
output logic [width-1:0] out1, out2);
|
||||||
logic [width-1:0] data [0:7];
|
logic [width-1:0] data [0:7];
|
||||||
|
|
||||||
always_ff@(posedge clk)
|
always_ff@(posedge clk)
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
data <= '{default: 0};
|
data <= '{default: 0};
|
||||||
|
@ -14,5 +20,5 @@ module registers #(width=32)
|
||||||
|
|
||||||
assign out1 = data[raddr1];
|
assign out1 = data[raddr1];
|
||||||
assign out2 = data[raddr2];
|
assign out2 = data[raddr2];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
19
spi_slave.sv
19
spi_slave.sv
|
@ -1,3 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Specialized SPI slave.
|
||||||
|
* Reads width bits at a time, and sets the ready flag
|
||||||
|
* whenever a full 32 bits has been read. Also, recognizes
|
||||||
|
* 0x00 as a pattern, and when full 0s are read, sets the done flag.
|
||||||
|
* 0x00 is a special value in the CPU programming process that indicates
|
||||||
|
* end-of-program.
|
||||||
|
*
|
||||||
|
* master_clk, ss, and mosi are all SPI-specific inputs.
|
||||||
|
* data should only be read when ready is high.
|
||||||
|
*/
|
||||||
module spi_slave #(width=32)
|
module spi_slave #(width=32)
|
||||||
(input logic clk, reset,
|
(input logic clk, reset,
|
||||||
input logic master_clk, ss, mosi,
|
input logic master_clk, ss, mosi,
|
||||||
|
@ -7,7 +18,7 @@ module spi_slave #(width=32)
|
||||||
logic [width-1:0] storage;
|
logic [width-1:0] storage;
|
||||||
logic unsigned [$clog2(width)-1:0] counter;
|
logic unsigned [$clog2(width)-1:0] counter;
|
||||||
logic old_clk;
|
logic old_clk;
|
||||||
|
|
||||||
always_ff@(posedge clk)
|
always_ff@(posedge clk)
|
||||||
if(reset) begin
|
if(reset) begin
|
||||||
counter <= 0;
|
counter <= 0;
|
||||||
|
@ -30,7 +41,7 @@ module spi_slave #(width=32)
|
||||||
end
|
end
|
||||||
old_clk <= master_clk;
|
old_clk <= master_clk;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign data = storage;
|
assign data = storage;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Loading…
Reference in New Issue
Block a user