6 changed files with 533 additions and 37 deletions
@ -0,0 +1,365 @@ |
|||||||
|
`default_nettype none |
||||||
|
|
||||||
|
module cpu |
||||||
|
( |
||||||
|
nrst, |
||||||
|
clk, |
||||||
|
nmi, |
||||||
|
irq, |
||||||
|
o_led); |
||||||
|
|
||||||
|
`include "parameters.vh" |
||||||
|
|
||||||
|
localparam STATE_START_1 = 4'hc; |
||||||
|
localparam STATE_START_2 = 4'hd; |
||||||
|
localparam STATE_START_3 = 4'he; |
||||||
|
localparam STATE_START_4 = 4'hf; |
||||||
|
localparam STATE_START_0 = 4'hb; |
||||||
|
localparam STATE_FETCH = 0; |
||||||
|
localparam STATE_EXECUTE = 1; |
||||||
|
localparam STATE_WRITE = 2; |
||||||
|
localparam STATE_FETCH_DATA_1 = 3; |
||||||
|
localparam STATE_FETCH_DATA_2 = 4; |
||||||
|
localparam STATE_EXECUTE_DATA_2 = 5; |
||||||
|
localparam STATE_BRANCH = 7; |
||||||
|
|
||||||
|
localparam |
||||||
|
READ_SOURCE_NONE = 2'h0, |
||||||
|
READ_SOURCE_MEM = 2'h1, |
||||||
|
READ_SOURCE_ALU = 2'h2; |
||||||
|
|
||||||
|
input wire nrst; |
||||||
|
input wire clk; |
||||||
|
input wire nmi; |
||||||
|
input wire irq; |
||||||
|
output wire [5:0] o_led; |
||||||
|
|
||||||
|
|
||||||
|
reg [7:0] X; |
||||||
|
reg [7:0] Y; |
||||||
|
reg [7:0] A; |
||||||
|
reg [15:0] PC; |
||||||
|
reg [7:0] S; |
||||||
|
reg [7:0] P; |
||||||
|
|
||||||
|
reg [7:0] tmp; |
||||||
|
|
||||||
|
reg [3:0] state; |
||||||
|
|
||||||
|
reg [7:0] instr; |
||||||
|
|
||||||
|
wire [4:0] address_code; |
||||||
|
wire [7:0] decoded_instr; |
||||||
|
|
||||||
|
wire rst = !nrst; |
||||||
|
|
||||||
|
logic mem_wr; |
||||||
|
wire [7:0] mem_data; |
||||||
|
wire [15:0] mem_addr_eff; |
||||||
|
logic [7:0] mem_data_wr; |
||||||
|
logic [2:0] mem_sel; |
||||||
|
logic [7:0] mem_aux_addr; |
||||||
|
|
||||||
|
logic [7:0] alu_op_1; |
||||||
|
logic [7:0] alu_op_2; |
||||||
|
logic alu_op_c; |
||||||
|
logic [2:0] alu_op_sel; |
||||||
|
wire [7:0] alu_op_result; |
||||||
|
logic alu_n; |
||||||
|
logic alu_z; |
||||||
|
logic alu_v; |
||||||
|
logic alu_c; |
||||||
|
reg [7:0] data; |
||||||
|
reg [15:0] mem_addr; |
||||||
|
reg [2:0] mem_addr_offset; |
||||||
|
logic [1:0] pending_a_read; |
||||||
|
logic [1:0] pending_x_read; |
||||||
|
logic pending_rel_branch; |
||||||
|
|
||||||
|
initial A = 0; |
||||||
|
initial X = 0; |
||||||
|
initial Y = 0; |
||||||
|
initial P = 0; |
||||||
|
initial S = 8'hff; |
||||||
|
initial mem_data_wr = 0; |
||||||
|
initial mem_wr = 0; |
||||||
|
assign mem_addr_eff = mem_addr; |
||||||
|
initial pending_a_read = 0; |
||||||
|
initial pending_x_read = 0; |
||||||
|
initial pending_rel_branch = 0; |
||||||
|
|
||||||
|
alu alui( |
||||||
|
.A(alu_op_1), |
||||||
|
.B(alu_op_2), |
||||||
|
.C(alu_op_c), |
||||||
|
.sel(alu_op_sel), |
||||||
|
.result(alu_op_result), |
||||||
|
.r_n(alu_n), |
||||||
|
.r_z(alu_z), |
||||||
|
.r_v(alu_v), |
||||||
|
.r_c(alu_c)); |
||||||
|
|
||||||
|
decoder decoder ( |
||||||
|
.clk(clk), |
||||||
|
.rst(rst), |
||||||
|
.instr((state == STATE_EXECUTE ? mem_data : instr)), |
||||||
|
.address_code(address_code), |
||||||
|
.decoded(decoded_instr) |
||||||
|
); |
||||||
|
|
||||||
|
mio mioi(.clk(clk), |
||||||
|
.i_data(mem_data_wr), |
||||||
|
.i_addr(mem_addr_eff), |
||||||
|
.i_wr(mem_wr), |
||||||
|
.o_data(mem_data), |
||||||
|
.o_led(o_led)); |
||||||
|
|
||||||
|
dmux dmuxi( |
||||||
|
.sel(mem_sel), |
||||||
|
.i_pc(PC), |
||||||
|
.i_a(A), |
||||||
|
.i_x(X), |
||||||
|
.i_y(Y), |
||||||
|
.i_sp(S), |
||||||
|
.i_aux({mem_data, mem_aux_addr}), |
||||||
|
.o_mux(mem_addr)); |
||||||
|
|
||||||
|
initial state = STATE_FETCH; |
||||||
|
initial PC = 0; |
||||||
|
initial mem_sel = 0; |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (state == STATE_START_0) |
||||||
|
begin |
||||||
|
mem_sel <= DMUX_AUX; |
||||||
|
mem_aux_addr <= 16'hfffc; |
||||||
|
state <= STATE_START_1; |
||||||
|
end |
||||||
|
else if (state == STATE_START_1) |
||||||
|
begin |
||||||
|
state <= STATE_START_2; |
||||||
|
end |
||||||
|
else if (state == STATE_START_2) |
||||||
|
begin |
||||||
|
PC[7:0] <= mem_data; |
||||||
|
mem_aux_addr <= 16'hfffd; |
||||||
|
state <= STATE_START_3; |
||||||
|
end |
||||||
|
else if(state == STATE_START_3) |
||||||
|
begin |
||||||
|
PC[15:8] <= mem_data; |
||||||
|
mem_sel <= DMUX_PC; |
||||||
|
state <= STATE_FETCH; |
||||||
|
end |
||||||
|
|
||||||
|
always_comb |
||||||
|
begin |
||||||
|
alu_op_1 = 0; |
||||||
|
alu_op_2 = 0; |
||||||
|
alu_op_c = 0; |
||||||
|
alu_op_sel = 0; |
||||||
|
if (decoded_instr == I_DEX) |
||||||
|
begin |
||||||
|
alu_op_1 = X; |
||||||
|
alu_op_2 = 1'b1; |
||||||
|
alu_op_c = 1'b1; |
||||||
|
alu_op_sel = OP_SUB; |
||||||
|
end |
||||||
|
if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
begin |
||||||
|
if (decoded_instr == I_EOR) |
||||||
|
begin |
||||||
|
alu_op_1 = A; |
||||||
|
alu_op_2 = mem_data; |
||||||
|
alu_op_c = 0; |
||||||
|
alu_op_sel = OP_EOR; |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (state == STATE_FETCH) |
||||||
|
begin |
||||||
|
if (pending_a_read == READ_SOURCE_MEM) |
||||||
|
begin |
||||||
|
A <= mem_data; |
||||||
|
P[P_Z] <= (mem_data == 0); |
||||||
|
P[P_N] <= mem_data[7]; |
||||||
|
end |
||||||
|
else if (pending_a_read == READ_SOURCE_ALU) |
||||||
|
begin |
||||||
|
A <= alu_op_result; |
||||||
|
P[P_Z] <= alu_z; |
||||||
|
P[P_N] <= alu_n; |
||||||
|
end |
||||||
|
pending_a_read <= READ_SOURCE_NONE; |
||||||
|
|
||||||
|
if (pending_x_read == READ_SOURCE_MEM) |
||||||
|
begin |
||||||
|
X <= mem_data; |
||||||
|
P[P_Z] <= (mem_data == 0); |
||||||
|
P[P_N] <= mem_data[7]; |
||||||
|
end |
||||||
|
else if (pending_x_read == READ_SOURCE_ALU) |
||||||
|
begin |
||||||
|
X <= alu_op_result; |
||||||
|
P[P_Z] <= alu_z; |
||||||
|
P[P_N] <= alu_n; |
||||||
|
end |
||||||
|
pending_x_read <= READ_SOURCE_NONE; |
||||||
|
PC <= PC + 1; |
||||||
|
state <= STATE_EXECUTE; |
||||||
|
end |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (state == STATE_EXECUTE) |
||||||
|
begin |
||||||
|
instr <= mem_data; |
||||||
|
if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
begin |
||||||
|
PC <= PC + 1; |
||||||
|
state <= STATE_FETCH_DATA_2; |
||||||
|
end |
||||||
|
else if (address_code == ADDR_MODE_IMMEDIATE) |
||||||
|
begin |
||||||
|
if (decoded_instr == I_LDX) |
||||||
|
begin |
||||||
|
pending_x_read <= READ_SOURCE_MEM; |
||||||
|
|
||||||
|
state <= STATE_FETCH; |
||||||
|
PC <= PC + 1; |
||||||
|
end |
||||||
|
else if (decoded_instr == I_LDA) |
||||||
|
begin |
||||||
|
pending_a_read <= READ_SOURCE_MEM; |
||||||
|
|
||||||
|
state <= STATE_FETCH; |
||||||
|
PC <= PC + 1; |
||||||
|
end |
||||||
|
end |
||||||
|
else if (address_code == ADDR_MODE_IMPLIED) |
||||||
|
begin |
||||||
|
if (decoded_instr == I_DEX) |
||||||
|
begin |
||||||
|
pending_x_read <= READ_SOURCE_ALU; |
||||||
|
|
||||||
|
state <= STATE_FETCH; |
||||||
|
end |
||||||
|
end |
||||||
|
else if (decoded_instr == I_BNE) |
||||||
|
begin |
||||||
|
if(!P[P_Z]) |
||||||
|
begin |
||||||
|
pending_rel_branch = 1'b1; |
||||||
|
state <= STATE_BRANCH; |
||||||
|
end |
||||||
|
else |
||||||
|
begin |
||||||
|
state <= STATE_FETCH; |
||||||
|
PC <= PC + 1; |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (state == STATE_BRANCH) |
||||||
|
begin |
||||||
|
if (pending_rel_branch) |
||||||
|
begin |
||||||
|
PC <= PC + {{8{mem_data[7]}}, mem_data[7:0]} + 1'b1; |
||||||
|
end |
||||||
|
pending_rel_branch <= 0; |
||||||
|
state <= STATE_FETCH; |
||||||
|
end |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (state == STATE_FETCH_DATA_2) |
||||||
|
begin |
||||||
|
if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
begin |
||||||
|
mem_aux_addr[7:0] <= mem_data; |
||||||
|
mem_sel <= DMUX_AUX; |
||||||
|
|
||||||
|
state <= STATE_EXECUTE_DATA_2; |
||||||
|
PC <= PC + 1'b1; |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
begin |
||||||
|
if (state == STATE_EXECUTE_DATA_2) |
||||||
|
begin |
||||||
|
if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
begin |
||||||
|
mem_sel <= DMUX_PC; |
||||||
|
state <= STATE_FETCH; |
||||||
|
if (decoded_instr == I_EOR) |
||||||
|
begin |
||||||
|
tmp <= mem_data; |
||||||
|
pending_a_read <= READ_SOURCE_ALU; |
||||||
|
end |
||||||
|
else if(decoded_instr == I_JMP) |
||||||
|
begin |
||||||
|
PC <= mem_addr; |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
always_comb |
||||||
|
begin |
||||||
|
mem_data_wr = 0; |
||||||
|
mem_wr = 0; |
||||||
|
if (state == STATE_EXECUTE_DATA_2) |
||||||
|
begin |
||||||
|
if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
begin |
||||||
|
if(decoded_instr == I_STA) |
||||||
|
begin |
||||||
|
mem_data_wr = A; |
||||||
|
mem_wr = 1'b1; |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
always_comb |
||||||
|
begin |
||||||
|
mem_addr_offset = 0; |
||||||
|
// if (state == STATE_FETCH) |
||||||
|
// begin |
||||||
|
// mem_addr_offset = 1; |
||||||
|
// end |
||||||
|
// if (state == STATE_BRANCH) |
||||||
|
// begin |
||||||
|
// mem_addr_offset = 0; |
||||||
|
// end |
||||||
|
// if (state == STATE_EXECUTE) |
||||||
|
// begin |
||||||
|
// if (address_code == ADDR_MODE_IMMEDIATE) |
||||||
|
// begin |
||||||
|
// mem_addr_offset = 1; |
||||||
|
// end |
||||||
|
// else if (address_code == ADDR_MODE_RELATIVE) |
||||||
|
// begin |
||||||
|
// if (decoded_instr == I_BNE ) |
||||||
|
// if (!P[P_Z]) |
||||||
|
// mem_addr_offset = 0; |
||||||
|
// else |
||||||
|
// mem_addr_offset = 1; |
||||||
|
// end |
||||||
|
// else if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
// begin |
||||||
|
// mem_addr_offset = 1; |
||||||
|
// end |
||||||
|
// end |
||||||
|
// if (state == STATE_FETCH_DATA_2) |
||||||
|
// begin |
||||||
|
// if (address_code == ADDR_MODE_ABSOLUTE) |
||||||
|
// begin |
||||||
|
// mem_addr_offset = 1; |
||||||
|
// end |
||||||
|
// end |
||||||
|
end |
||||||
|
|
||||||
|
endmodule |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
`default_nettype none |
||||||
|
module dmux(sel, i_pc, i_a, i_x, i_y, i_sp, i_aux, o_mux); |
||||||
|
input wire [2:0] sel; |
||||||
|
input wire [15:0] i_pc; |
||||||
|
input wire [7:0] i_a; |
||||||
|
input wire [7:0] i_x; |
||||||
|
input wire [7:0] i_y; |
||||||
|
input wire [7:0] i_sp; |
||||||
|
input wire [15:0] i_aux; |
||||||
|
output logic [15:0] o_mux; |
||||||
|
|
||||||
|
`include "parameters.vh" |
||||||
|
|
||||||
|
always_comb |
||||||
|
begin |
||||||
|
o_mux = 0; |
||||||
|
if (sel == DMUX_PC) |
||||||
|
o_mux = i_pc; |
||||||
|
else if (sel == DMUX_A) |
||||||
|
o_mux[15:0] = { 8'h0, i_a }; |
||||||
|
else if (sel == DMUX_X) |
||||||
|
o_mux[15:0] = { 8'h0, i_x }; |
||||||
|
else if (sel == DMUX_Y) |
||||||
|
o_mux[15:0] = { 8'h0, i_y }; |
||||||
|
else if (sel == DMUX_SP) |
||||||
|
o_mux[15:0] = { 8'h1, i_sp }; |
||||||
|
else if (sel == DMUX_AUX) |
||||||
|
o_mux = i_aux; |
||||||
|
end |
||||||
|
|
||||||
|
endmodule |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
`default_nettype none |
||||||
|
module mio(clk, i_data, i_addr, i_wr, o_data, o_led); |
||||||
|
|
||||||
|
input wire clk; |
||||||
|
input wire [7:0] i_data; |
||||||
|
input wire [15:0] i_addr; |
||||||
|
input wire i_wr; |
||||||
|
output logic [7:0] o_data; |
||||||
|
output logic [5:0] o_led; |
||||||
|
|
||||||
|
reg [7:0] memory [0:65535]; |
||||||
|
|
||||||
|
initial $readmemh("foo.hex", memory); |
||||||
|
initial begin |
||||||
|
memory[32768] <= 8'h00; |
||||||
|
memory[65532] <= 8'h00; |
||||||
|
memory[65533] <= 8'h00; |
||||||
|
end; |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
o_data <= memory[i_addr]; |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
o_led <= memory[32768]; |
||||||
|
|
||||||
|
always @(posedge clk) |
||||||
|
if (i_wr) |
||||||
|
begin |
||||||
|
memory[i_addr] <= i_data; |
||||||
|
end |
||||||
|
|
||||||
|
endmodule |
||||||
Loading…
Reference in new issue