aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAugustin Fabre <augustin@augfab.fr>2019-06-16 18:19:45 +0200
committerAugustin Fabre <augustin@augfab.fr>2019-06-16 18:20:20 +0200
commit49d379c0f33635ab1eaf475fbe08694f7eb71998 (patch)
treeda435d694ead25e1f52a194f512dfb24f4d678ae
downloadminimal-cpu-49d379c0f33635ab1eaf475fbe08694f7eb71998.tar.gz
minimal-cpu-49d379c0f33635ab1eaf475fbe08694f7eb71998.tar.bz2
minimal-cpu-49d379c0f33635ab1eaf475fbe08694f7eb71998.tar.xz
Add Verilog description of MCPU
-rw-r--r--logical/cpu.sv106
1 files changed, 106 insertions, 0 deletions
diff --git a/logical/cpu.sv b/logical/cpu.sv
new file mode 100644
index 0000000..7bd4b47
--- /dev/null
+++ b/logical/cpu.sv
@@ -0,0 +1,106 @@
+`ifndef CPU_
+`define CPU_
+typedef enum logic [1:0] {
+ NOR = 2'b00,
+ ADD = 2'b01,
+ STA = 2'b10,
+ JCC = 2'b11
+} opcode_t;
+
+typedef enum logic [2:0] {
+ FETCH,
+ WRITE,
+ READ_ADD,
+ READ_NOR,
+ CLEAR_CARRY
+} state_t;
+
+module cpu (
+ input wire clk_i,
+ input wire nrst_i,
+
+ input wire [7:0] data_i,
+
+ output wire we_o,
+ output wire [5:0] addr_o,
+ output wire [7:0] data_o
+);
+
+state_t state_q;
+logic [5:0] pc_q; // Program counter.
+logic [8:0] acc_q; // Accumulator. Bit 8 is carry.
+
+logic we_q; // Write enable.
+logic [5:0] addr_q;
+
+wire opcode_t op = data_i[7:6];
+wire logic [5:0] addr = data_i[5:0];
+
+wire logic carry = acc_q[8];
+wire logic [7:0] data = acc_q[7:0];
+
+always @(posedge clk_i or negedge nrst_i) begin
+ if (~nrst_i) begin
+ state_q <= FETCH;
+ pc_q <= '0;
+ acc_q <= '0;
+ addr_q <= '0;
+ we_q <= '0;
+ end else begin
+ case (state_q)
+ FETCH: begin
+ pc_q <= addr_q + 6'b1;
+ addr_q <= addr;
+ we_q <= '0;
+ case (op)
+ NOR: begin
+ state_q <= READ_NOR;
+ end
+ ADD: begin
+ state_q <= READ_ADD;
+ end
+ STA: begin
+ state_q <= WRITE;
+ end
+ JCC: begin
+ if (carry)
+ state_q <= FETCH;
+ else
+ state_q <= CLEAR_CARRY;
+ end
+ default: begin
+ end
+ endcase
+ end
+ WRITE: begin
+ state_q <= FETCH;
+ addr_q <= pc_q;
+ we_q <= 1'b1;
+ end
+ READ_ADD: begin
+ state_q <= FETCH;
+ acc_q <= {1'b0, data} + {1'b0, data_i};
+ addr_q <= pc_q;
+ end
+ READ_NOR: begin
+ state_q <= FETCH;
+ acc_q[7:0] <= ~(data | data_i);
+ addr_q <= pc_q;
+ end
+ CLEAR_CARRY: begin
+ state_q <= FETCH;
+ acc_q[8] <= 1'b0;
+ addr_q <= pc_q;
+ end
+ default: begin
+ end
+ endcase
+ end
+end
+
+assign we_o = we_q;
+assign addr_o = addr_q;
+assign data_o = acc_q[7:0];
+
+endmodule
+`endif