1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-20 08:29:30 +00:00

worked on CPU

This commit is contained in:
Steven Hugg 2018-02-10 00:22:17 -06:00
parent 9c25aed9fa
commit e7067ff50d
2 changed files with 91 additions and 68 deletions

View File

@ -1,40 +1,41 @@
`define OP_LOAD_A 4'h0 parameter OP_LOAD_A = 4'h0;
`define OP_LOAD_B 4'h1 parameter OP_LOAD_B = 4'h1;
`define OP_OR 4'h2 parameter OP_OR = 4'h2;
`define OP_AND 4'h3 parameter OP_AND = 4'h3;
`define OP_XOR 4'h4 parameter OP_XOR = 4'h4;
`define OP_INC 4'h5 parameter OP_INC = 4'h5;
`define OP_DEC 4'h6 parameter OP_DEC = 4'h6;
`define OP_ZERO 4'h7 parameter OP_ZERO = 4'h7;
// operations that generate carry // operations that generate and use carry
`define OP_ADD 4'h8 parameter OP_ADC = 4'h8;
`define OP_SUB 4'h9 parameter OP_SBB = 4'h9;
`define OP_ASL 4'ha parameter OP_ROL = 4'ha;
`define OP_LSR 4'hb parameter OP_ROR = 4'hb;
module ALU( module ALU(A, B, Y, aluop, carry);
input [7:0] A,
input [7:0] B, input [7:0] A;
output [8:0] Y, input [7:0] B;
input [3:0] aluop output [8:0] Y;
); input [3:0] aluop;
input carry;
always @(*) always @(*)
case (aluop) case (aluop)
`OP_LOAD_A: Y = {1'b0, A}; OP_LOAD_A: Y = {1'b0, A};
`OP_LOAD_B: Y = {1'b0, B}; OP_LOAD_B: Y = {1'b0, B};
`OP_OR: Y = {1'b0, A | B}; OP_OR: Y = {1'b0, A | B};
`OP_AND: Y = {1'b0, A & B}; OP_AND: Y = {1'b0, A & B};
`OP_XOR: Y = {1'b0, A ^ B}; OP_XOR: Y = {1'b0, A ^ B};
`OP_INC: Y = A + 1; OP_INC: Y = A + 1;
`OP_DEC: Y = A - 1; OP_DEC: Y = A - 1;
`OP_ZERO: Y = 0; OP_ZERO: Y = 0;
`OP_ADD: Y = A + B; OP_ADC: Y = A + B + (carry?1:0);
`OP_SUB: Y = A - B; OP_SBB: Y = A - B - (carry?1:0);
`OP_ASL: Y = A + A; OP_ROL: Y = {A, carry};
`OP_LSR: Y = {A[0], A >> 1}; OP_ROR: Y = {A[0], carry, A[7:1]};
default: Y = 9'bx; default: Y = 9'bx;
endcase endcase
@ -57,33 +58,37 @@ tttt = flags test for conditional branch
*/ */
// destinations for COMPUTE instructions // destinations for COMPUTE instructions
`define DEST_A 2'b00 parameter DEST_A = 2'b00;
`define DEST_B 2'b01 parameter DEST_B = 2'b01;
`define DEST_IP 2'b10 parameter DEST_IP = 2'b10;
`define DEST_NOP 2'b11 parameter DEST_NOP = 2'b11;
// instruction macros // instruction macros
`define I_COMPUTE(dest,op) { 2'b00, 2'(dest), 4'(op) } `define I_COMPUTE(dest,op) { 2'b00, 2'(dest), 4'(op) }
`define I_COMPUTE_IMM(dest,op) { 2'b01, 2'(dest), 4'(op) } `define I_COMPUTE_IMM(dest,op) { 2'b01, 2'(dest), 4'(op) }
`define I_COMPUTE_READB(dest,op) { 2'b11, 2'(dest), 4'(op) } `define I_COMPUTE_READB(dest,op) { 2'b11, 2'(dest), 4'(op) }
`define I_CONST_IMM_A { 2'b01, `DEST_A, `OP_LOAD_B } `define I_CONST_IMM_A { 2'b01, DEST_A, OP_LOAD_B }
`define I_CONST_IMM_B { 2'b01, `DEST_B, `OP_LOAD_B } `define I_CONST_IMM_B { 2'b01, DEST_B, OP_LOAD_B }
`define I_JUMP_IMM { 2'b01, `DEST_IP, `OP_LOAD_B } `define I_JUMP_IMM { 2'b01, DEST_IP, OP_LOAD_B }
`define I_STORE_A(addr) { 4'b1001, 4'(addr) } `define I_STORE_A(addr) { 4'b1001, 4'(addr) }
`define I_BRANCH_IF_CARRY(carry) { 4'b1010, 2'b00, 1'(carry), 1'b1 } `define I_BRANCH_IF(zv,zu,cv,cu) { 4'b1010, 1'(zv), 1'(zu), 1'(cv), 1'(cu) }
`define I_CLEAR_CARRY { 8'b10001000 }
`define I_SWAP_AB { 8'b10000001 } `define I_SWAP_AB { 8'b10000001 }
`define I_RESET { 8'b10111111 } `define I_RESET { 8'b10111111 }
// convenience macros // convenience macros
`define I_ZERO_A `I_COMPUTE(`DEST_A, `OP_ZERO) `define I_ZERO_A `I_COMPUTE(DEST_A, OP_ZERO)
`define I_ZERO_B `I_COMPUTE(`DEST_B, `OP_ZERO) `define I_ZERO_B `I_COMPUTE(DEST_B, OP_ZERO)
`define I_BRANCH_IF_CARRY(carry) `I_BRANCH_IF(0,0,carry,1)
`define I_BRANCH_IF_ZERO(zero) `I_BRANCH_IF(zero,1,0,0)
`define I_CLEAR_ZERO `I_COMPUTE(DEST_NOP,OP_ZERO)
module CPU( module CPU(clk, reset, address, data_in, data_out, write);
input clk,
input reset, input clk;
output [7:0] address, input reset;
input [7:0] data_in, output [7:0] address;
output [7:0] data_out, input [7:0] data_in;
output write output [7:0] data_out;
); output write;
reg [7:0] IP; reg [7:0] IP;
reg [7:0] A, B; reg [7:0] A, B;
@ -105,7 +110,12 @@ module CPU(
localparam S_COMPUTE = 3; localparam S_COMPUTE = 3;
localparam S_READ_IP = 4; localparam S_READ_IP = 4;
ALU alu(.A(A), .B(B_or_data?data_in:B), .Y(Y), .aluop(aluop)); ALU alu(
.A(A),
.B(B_or_data ? data_in : B),
.Y(Y),
.aluop(aluop),
.carry(carry));
always @(posedge clk) always @(posedge clk)
if (reset) begin if (reset) begin
@ -128,7 +138,7 @@ module CPU(
end end
// state 2: read/decode opcode // state 2: read/decode opcode
S_DECODE: begin S_DECODE: begin
opcode <= data_in; opcode <= data_in; // (only use opcode next cycle)
casez (data_in) casez (data_in)
// ALU A + B -> dest // ALU A + B -> dest
8'b00??????: begin 8'b00??????: begin
@ -145,13 +155,18 @@ module CPU(
address <= B; address <= B;
state <= S_COMPUTE; state <= S_COMPUTE;
end end
// A -> write [aluop] // A -> write [nnnn]
8'b1001????: begin 8'b1001????: begin
address <= {4'b0, aluop}; address <= {4'b0, data_in[3:0]};
data_out <= A; data_out <= A;
write <= 1; write <= 1;
state <= S_SELECT; state <= S_SELECT;
end end
// clear carry
8'b10001000: begin
carry <= 0;
state <= S_SELECT;
end
// swap A,B // swap A,B
8'b10000001: begin 8'b10000001: begin
A <= B; A <= B;
@ -181,15 +196,15 @@ module CPU(
S_COMPUTE: begin S_COMPUTE: begin
// transfer ALU output to destination // transfer ALU output to destination
case (opdest) case (opdest)
`DEST_A: A <= Y[7:0]; DEST_A: A <= Y[7:0];
`DEST_B: B <= Y[7:0]; DEST_B: B <= Y[7:0];
`DEST_IP: IP <= Y[7:0]; DEST_IP: IP <= Y[7:0];
`DEST_NOP: ; DEST_NOP: ;
endcase endcase
// set carry for certain operations (code >= 8) // set carry for certain operations (code >= 8)
if (aluop[3]) carry <= Y[8]; if (aluop[3]) carry <= Y[8];
// set zero flag // set zero flag
zero <= ~|Y; zero <= ~|Y[7:0];
// repeat CPU loop // repeat CPU loop
state <= S_SELECT; state <= S_SELECT;
end end
@ -212,7 +227,9 @@ module test_CPU_top(
output write_enable, output write_enable,
output [7:0] IP, output [7:0] IP,
output [7:0] A, output [7:0] A,
output [7:0] B output [7:0] B,
output zero,
output carry
); );
reg [7:0] ram[0:127]; reg [7:0] ram[0:127];
@ -221,6 +238,8 @@ module test_CPU_top(
assign IP = cpu.IP; assign IP = cpu.IP;
assign A = cpu.A; assign A = cpu.A;
assign B = cpu.B; assign B = cpu.B;
assign zero = cpu.zero;
assign carry = cpu.carry;
CPU cpu(.clk(clk), CPU cpu(.clk(clk),
.reset(reset), .reset(reset),
@ -229,27 +248,31 @@ module test_CPU_top(
.data_out(from_cpu), .data_out(from_cpu),
.write(write_enable)); .write(write_enable));
// does not work as (posedge clk) always @(posedge clk)
if (write_enable) begin
ram[address_bus[6:0]] <= from_cpu;
end
always @(*) always @(*)
if (write_enable) if (address_bus[7] == 0)
ram[address_bus[6:0]] = from_cpu;
else if (address_bus[7] == 0)
to_cpu = ram[address_bus[6:0]]; to_cpu = ram[address_bus[6:0]];
else else
to_cpu = rom[address_bus[6:0]]; to_cpu = rom[address_bus[6:0]];
initial begin initial begin
rom = '{ rom = '{
`I_CLEAR_CARRY,
`I_ZERO_A, `I_ZERO_A,
`I_CONST_IMM_B, `I_CONST_IMM_B,
1, 1,
`I_COMPUTE(`DEST_A, `OP_ADD), // addr 4 `I_COMPUTE(DEST_A, OP_ADC), // addr 4
`I_SWAP_AB, `I_SWAP_AB,
`I_BRANCH_IF_CARRY(0), `I_BRANCH_IF_CARRY(0),
3 + 'h80, // correct for ROM offset 4 + 'h80, // correct for ROM offset
`I_STORE_A(0),
`I_RESET, `I_RESET,
// leftover elements // leftover elements
120{0} 118{0}
}; };
end end

View File

@ -54,7 +54,7 @@ module sprite_multiple_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.vstart(player_vstart), .vstart(player_vstart),
.load(hpos == 256), .load(hpos == 256),
.hstart(player_hstart), .hstart(player_hstart),
.rom_yofs(car_sprite_yofs), .rom_addr(car_sprite_yofs),
.rom_bits(car_sprite_bits), .rom_bits(car_sprite_bits),
.gfx(player_gfx), .gfx(player_gfx),
.in_progress(player_is_drawing)); .in_progress(player_is_drawing));
@ -64,7 +64,7 @@ module sprite_multiple_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.vstart(enemy_vstart), .vstart(enemy_vstart),
.load(hpos == 257), .load(hpos == 257),
.hstart(enemy_hstart), .hstart(enemy_hstart),
.rom_yofs(car_sprite_yofs), .rom_addr(car_sprite_yofs),
.rom_bits(car_sprite_bits), .rom_bits(car_sprite_bits),
.gfx(enemy_gfx), .gfx(enemy_gfx),
.in_progress(player_is_drawing)); .in_progress(player_is_drawing));