You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
366 lines
8.8 KiB
366 lines
8.8 KiB
|
1 month ago
|
`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
|