1
0
Fork 0

Add SAP-2 code

This commit is contained in:
Austin Morlan 2023-01-15 13:57:23 -08:00
parent 7590cd0cf3
commit 8eee1171a8
Signed by: austin
GPG Key ID: FD6B27654AF5E348
24 changed files with 4925 additions and 22 deletions

View File

@ -9,24 +9,47 @@ BIN_DIR=$APIO_HOME_DIR/packages/tools-oss-cad-suite/bin
COMMAND=$1 COMMAND=$1
VERSION=$2 VERSION=$2
MODULES=" SAP1_MODULES="
$SRC_DIR/adder.v $SRC_DIR/sap1/adder.v
$SRC_DIR/clock.v $SRC_DIR/sap1/clock.v
$SRC_DIR/controller.v $SRC_DIR/sap1/controller.v
$SRC_DIR/ir.v $SRC_DIR/sap1/ir.v
$SRC_DIR/memory.v $SRC_DIR/sap1/memory.v
$SRC_DIR/pc.v $SRC_DIR/sap1/pc.v
$SRC_DIR/reg_a.v $SRC_DIR/sap1/reg_a.v
$SRC_DIR/reg_b.v" $SRC_DIR/sap1/reg_b.v"
SAP1_TOP=$SRC_DIR/sap1/top.v
SAP1_TB=$SRC_DIR/sap1/top_tb.v
SAP2_MODULES="
$SRC_DIR/sap2/alu.v
$SRC_DIR/sap2/clock.v
$SRC_DIR/sap2/controller.v
$SRC_DIR/sap2/ir.v
$SRC_DIR/sap2/memory.v
$SRC_DIR/sap2/pc.v
$SRC_DIR/sap2/register.v
$SRC_DIR/sap2/flags.v"
SAP2_TOP=$SRC_DIR/sap2/top.v
SAP2_TB=$SRC_DIR/sap2/top_tb.v
TOP=$SRC_DIR/top.v
TB=$SRC_DIR/top_tb.v
if [ -z "$COMMAND" ]; then if [ -z "$COMMAND" ]; then
mkdir -p $BUILD_DIR mkdir -p $BUILD_DIR/sap1
pushd $BUILD_DIR > /dev/null pushd $BUILD_DIR/sap1 > /dev/null
$BIN_DIR/yosys -q -p "synth_ice40 -json hardware.json" $MODULES $TOP $BIN_DIR/yosys -q -p "synth_ice40 -json hardware.json" $SAP1_MODULES $SAP1_TOP
$BIN_DIR/nextpnr-ice40 --lp8k --package cm81 --json hardware.json --asc hardware.asc --pcf $SRC_DIR/pins.pcf -q
$BIN_DIR/icepack hardware.asc hardware.bin
popd > /dev/null
mkdir -p $BUILD_DIR/sap2
pushd $BUILD_DIR/sap2 > /dev/null
$BIN_DIR/yosys -q -p "synth_ice40 -json hardware.json" $SAP2_MODULES $SAP2_TOP
$BIN_DIR/nextpnr-ice40 --lp8k --package cm81 --json hardware.json --asc hardware.asc --pcf $SRC_DIR/pins.pcf -q $BIN_DIR/nextpnr-ice40 --lp8k --package cm81 --json hardware.json --asc hardware.asc --pcf $SRC_DIR/pins.pcf -q
$BIN_DIR/icepack hardware.asc hardware.bin $BIN_DIR/icepack hardware.asc hardware.bin
@ -41,17 +64,45 @@ elif [ "$COMMAND" == "clean" ]; then
rm -r $BUILD_DIR rm -r $BUILD_DIR
elif [ "$COMMAND" == "program" ]; then elif [ "$COMMAND" == "program" ]; then
source .env/bin/activate source .env/bin/activate
sudo tinyprog -p $BUILD_DIR/hardware.bin
if [ -z "$VERSION" ]; then
echo "program needs a version"
exit 1
elif [ "$VERSION" == "sap1" ]; then
pushd $BUILD_DIR/sap1 > /dev/null
sudo tinyprog -p hardware.bin
popd > /dev/null
elif [ "$VERSION" == "sap2" ]; then
pushd $BUILD_DIR/sap2 > /dev/null
sudo tinyprog -p hardware.bin
popd > /dev/null
fi
elif [ "$COMMAND" == "sim" ]; then elif [ "$COMMAND" == "sim" ]; then
mkdir -p $BUILD_DIR if [ -z "$VERSION" ]; then
echo "sim needs a version"
exit 1
elif [ "$VERSION" == "sap1" ]; then
mkdir -p $BUILD_DIR/sap1
pushd $SRC_DIR > /dev/null pushd $SRC_DIR/sap1 > /dev/null
$BIN_DIR/iverilog -o $BUILD_DIR/top_tb $MODULES $TB $BIN_DIR/iverilog -o $BUILD_DIR/sap1/top_tb $SAP1_MODULES $SAP1_TB
$BIN_DIR/vvp $BUILD_DIR/top_tb $BIN_DIR/vvp $BUILD_DIR/sap1/top_tb
mv top_tb.vcd $BUILD_DIR/ mv top_tb.vcd $BUILD_DIR/sap1
popd > /dev/null popd > /dev/null
gtkwave $BUILD_DIR/sap1/top_tb.vcd $BUILD_DIR/sap1/top_tb.gtkw
elif [ "$VERSION" == "sap2" ]; then
mkdir -p $BUILD_DIR/sap2
pushd $SRC_DIR/sap2 > /dev/null
$BIN_DIR/iverilog -o $BUILD_DIR/sap2/top_tb $SAP2_MODULES $SAP2_TB
$BIN_DIR/vvp $BUILD_DIR/sap2/top_tb
mv top_tb.vcd $BUILD_DIR/sap2
popd > /dev/null
gtkwave $BUILD_DIR/sap2/top_tb.vcd $BUILD_DIR/sap2/top_tb.gtkw
fi
gtkwave $BUILD_DIR/top_tb.vcd $BUILD_DIR/top_tb.gtkw
else else
echo "Invalid arguments" echo "Invalid arguments"
fi fi

64
src/sap2/alu.v Normal file
View File

@ -0,0 +1,64 @@
module alu(
input clk,
input[7:0] a,
input[2:0] op,
input load,
input en,
inout[15:0] bus
);
reg[7:0] alu = 0;
reg[7:0] tmp = 0;
localparam OP_ADD = 0;
localparam OP_SUB = 1;
localparam OP_AND = 2;
localparam OP_OR = 3;
localparam OP_XOR = 4;
localparam OP_CMA = 5;
localparam OP_RAL = 6;
localparam OP_RAR = 7;
always @(posedge clk) begin
if (load) begin
tmp <= bus[7:0];
end
end
always @(*) begin
case (op)
OP_ADD: begin
alu = a + tmp;
end
OP_SUB: begin
alu = a - tmp;
end
OP_AND: begin
alu = a & tmp;
end
OP_OR: begin
alu = a | tmp;
end
OP_XOR: begin
alu = a ^ tmp;
end
OP_CMA: begin
alu = ~a;
end
OP_RAL: begin
alu = a << 1;
alu[0] = a[7];
end
OP_RAR: begin
alu = a >> 1;
end
default: begin
alu = 0;
end
endcase
end
assign bus = (en) ? alu : 16'bz;
endmodule

9
src/sap2/clock.v Normal file
View File

@ -0,0 +1,9 @@
module clock(
input hlt,
input clk_in,
output clk_out);
assign clk_out = (hlt) ? 1'b0 : clk_in;
endmodule

80
src/sap2/controller.v Normal file
View File

@ -0,0 +1,80 @@
module controller(
input clk,
input[7:0] instr,
input[1:0] flags,
output reg[33:0] ctrl_word
);
localparam SIG_END = 34;
localparam SIG_HLT = 33;
localparam SIG_A_LOAD = 32;
localparam SIG_A_EN = 31;
localparam SIG_A_INC = 30;
localparam SIG_A_DEC = 29;
localparam SIG_B_LOAD = 28;
localparam SIG_B_EN = 27;
localparam SIG_B_INC = 26;
localparam SIG_B_DEC = 25;
localparam SIG_C_LOAD = 24;
localparam SIG_C_EN = 23;
localparam SIG_C_INC = 22;
localparam SIG_C_DEC = 21;
localparam SIG_FLAGS_LDA = 20;
localparam SIG_FLAGS_LDB = 19;
localparam SIG_FLAGS_LDC = 18;
localparam SIG_ALU_OP2 = 17;
localparam SIG_ALU_OP1 = 16;
localparam SIG_ALU_OP0 = 15;
localparam SIG_ALU_LD = 14;
localparam SIG_ALU_EN = 13;
localparam SIG_IR_LOAD = 12;
localparam SIG_PC_INC = 11;
localparam SIG_PC_LOAD = 10;
localparam SIG_PC_EN = 9;
localparam SIG_MAR_LOADH = 8;
localparam SIG_MAR_LOADL = 7;
localparam SIG_MDR_LOAD = 6;
localparam SIG_MDR_EN = 5;
localparam SIG_RAM_LOAD = 4;
localparam SIG_RAM_ENH = 3;
localparam SIG_RAM_ENL = 2;
localparam SIG_CALL = 1;
localparam SIG_RET = 0;
localparam OP_JZ = 8'hCA;
localparam OP_JNZ = 8'hC2;
localparam OP_JM = 8'hFA;
localparam FLAG_Z = 1;
localparam FLAG_S = 0;
reg[34:0] ctrl_rom[0:4095];
initial begin
$readmemb("ctrl_rom.bin", ctrl_rom);
end
reg reset = 0;
reg[3:0] stage = 0;
always @(negedge clk) begin
if (reset) begin
stage <= 0;
end else begin
stage <= stage + 1;
end
end
always @(*) begin
ctrl_word = ctrl_rom[{instr, stage}];
if ((instr == OP_JZ && stage == 4 && flags[FLAG_Z] == 0) ||
(instr == OP_JNZ && stage == 4 && flags[FLAG_Z] == 1) ||
(instr == OP_JM && stage == 4 && flags[FLAG_S] == 0))
begin
reset = 1;
end else begin
reset = ctrl_rom[{instr, stage}][SIG_END];
end
end
endmodule

4096
src/sap2/ctrl_rom.bin Normal file

File diff suppressed because it is too large Load Diff

33
src/sap2/flags.v Normal file
View File

@ -0,0 +1,33 @@
module flags(
input clk,
input[7:0] a,
input[7:0] b,
input[7:0] c,
input load_a,
input load_b,
input load_c,
output[1:0] out
);
localparam FLAG_Z = 1;
localparam FLAG_S = 0;
reg[1:0] data = 0;
always @(negedge clk) begin
if (load_a) begin
data[FLAG_Z] <= (a == 0) ? 1'b1 : 1'b0;
data[FLAG_S] <= (a[7] == 1) ? 1'b1 : 1'b0;
end else if (load_b) begin
data[FLAG_Z] <= (b == 0) ? 1'b1 : 1'b0;
data[FLAG_S] <= (b[7] == 1) ? 1'b1 : 1'b0;
end else if (load_c) begin
data[FLAG_Z] <= (c == 0) ? 1'b1 : 1'b0;
data[FLAG_S] <= (c[7] == 1) ? 1'b1 : 1'b0;
end
end
assign out = data;
endmodule

22
src/sap2/ir.v Normal file
View File

@ -0,0 +1,22 @@
module ir(
input clk,
input clr,
input load,
input[15:0] bus,
output[7:0] out
);
reg[7:0] data = 0;
always @(posedge clk or posedge clr) begin
if (clr) begin
data <= 8'b0;
end else if (load) begin
data <= bus[7:0];
end
end
assign out = data;
endmodule

62
src/sap2/memory.v Normal file
View File

@ -0,0 +1,62 @@
module memory(
input clk,
input mar_loadh,
input mar_loadl,
input mdr_load,
input mdr_en,
input ram_load,
input ram_enh,
input ram_enl,
input call,
input ret,
inout[15:0] bus
);
initial begin
$readmemh("program.bin", ram);
end
reg[15:0] mar = 0;
reg[15:0] mdr = 0;
reg[7:0] ram[0:65535];
always @(posedge clk) begin
if (mar_loadh) begin
mar[15:8] <= bus[15:8];
end
if (mar_loadl) begin
mar[7:0] <= bus[7:0];
end
if (mdr_load) begin
mdr[7:0] <= bus[7:0];
end
if (ram_load) begin
ram[mar] <= mdr;
end
if (ram_enh) begin
mdr[15:8] <= ram[mar];
end
if (ram_enl) begin
mdr[7:0] <= ram[mar];
end
if (call) begin
ram[16'hFFFE] <= bus[15:8];
ram[16'hFFFF] <= bus[7:0];
end
if (ret) begin
mdr[15:8] <= ram[16'hFFFE];
mdr[7:0] <= ram[16'hFFFF];
end
end
assign bus = (mdr_en) ? mdr : 16'bz;
endmodule

25
src/sap2/pc.v Normal file
View File

@ -0,0 +1,25 @@
module pc(
input clk,
input clr,
input inc,
input load,
input en,
output[15:0] bus
);
reg[15:0] pc = 0;
always @(posedge clk or posedge clr) begin
if (clr) begin
pc <= 16'b0;
end else if (load) begin
pc <= bus;
end else if (inc) begin
pc <= pc + 1;
end
end
assign bus = (en) ? pc : 16'bz;
endmodule

2
src/sap2/program.bin Normal file
View File

@ -0,0 +1,2 @@
3e 00 06 0c 0e 08 80 0d
ca 0e 00 c3 06 00 76

27
src/sap2/register.v Normal file
View File

@ -0,0 +1,27 @@
module register(
input clk,
input load,
input en,
input inc,
input dec,
inout[15:0] bus,
output[7:0] out
);
reg[7:0] data = 0;
always @(posedge clk) begin
if (load) begin
data <= bus[7:0];
end else if (inc) begin
data <= data + 1;
end else if (dec) begin
data <= data - 1;
end
end
assign bus = (en) ? {8'b0, data} : 16'bz;
assign out = data;
endmodule

210
src/sap2/top.v Normal file
View File

@ -0,0 +1,210 @@
module top(
input CLK
);
wire[15:0] bus;
wire clr;
wire hlt;
wire clk;
clock clock(
// In
.hlt(hlt),
.clk_in(CLK),
// Out
.clk_out(clk)
);
wire pc_inc;
wire pc_load;
wire pc_en;
pc pc(
// In
.clk(clk),
.clr(clr),
.inc(pc_inc),
.load(pc_load),
.en(pc_en),
// Output
.bus(bus)
);
wire ir_load;
wire[7:0] ir_instr;
ir ir(
// In
.clk(clk),
.clr(clr),
.load(ir_load),
// Inout
.bus(bus),
// Out
.out(ir_instr)
);
wire mar_loadh;
wire mar_loadl;
wire mdr_load;
wire mdr_en;
wire ram_load;
wire ram_enh;
wire ram_enl;
wire call;
wire ret;
memory mem(
// In
.clk(clk),
.mar_loadh(mar_loadh),
.mar_loadl(mar_loadl),
.mdr_load(mdr_load),
.mdr_en(mdr_en),
.ram_load(ram_load),
.ram_enh(ram_enh),
.ram_enl(ram_enl),
.call(call),
.ret(ret),
// Inout
.bus(bus)
);
wire a_load;
wire a_en;
wire a_inc;
wire a_dec;
wire[7:0] a_val;
register reg_a(
// In
.clk(clk),
.load(a_load),
.en(a_en),
.inc(a_inc),
.dec(a_dec),
// Inout
.bus(bus),
// Out
.out(a_val)
);
wire b_load;
wire b_en;
wire b_inc;
wire b_dec;
wire[7:0] b_val;
register reg_b(
// In
.clk(clk),
.load(b_load),
.en(b_en),
.inc(b_inc),
.dec(b_dec),
// Inout
.bus(bus),
// Out
.out(b_val)
);
wire c_load;
wire c_en;
wire c_inc;
wire c_dec;
wire[7:0] c_val;
register reg_c(
// In
.clk(clk),
.load(c_load),
.en(c_en),
.inc(c_inc),
.dec(c_dec),
// Inout
.bus(bus),
// Out
.out(c_val)
);
wire[2:0] alu_op;
wire alu_load;
wire alu_en;
alu alu(
// In
.clk(clk),
.a(a_val),
.load(alu_load),
.op(alu_op),
.en(alu_en),
// Out
.bus(bus)
);
wire[1:0] flags_val;
wire flags_lda;
wire flags_ldb;
wire flags_ldc;
flags flags(
// In
.clk(clk),
.a(a_val),
.b(b_val),
.c(c_val),
.load_a(flags_lda),
.load_b(flags_ldb),
.load_c(flags_ldc),
// Out
.out(flags_val)
);
controller controller(
.clk(clk),
.instr(ir_instr),
.flags(flags_val),
.ctrl_word({
hlt,
a_load,
a_en,
a_inc,
a_dec,
b_load,
b_en,
b_inc,
b_dec,
c_load,
c_en,
c_inc,
c_dec,
flags_lda,
flags_ldb,
flags_ldc,
alu_op,
alu_load,
alu_en,
ir_load,
pc_inc,
pc_load,
pc_en,
mar_loadh,
mar_loadl,
mdr_load,
mdr_en,
ram_load,
ram_enh,
ram_enl,
call,
ret})
);
endmodule

222
src/sap2/top_tb.v Normal file
View File

@ -0,0 +1,222 @@
module top_tb();
initial begin
$dumpfile("top_tb.vcd");
$dumpvars(0, top_tb);
end
reg clk_in = 0;
integer i;
initial begin
for (i = 0; i < 512; i++) begin
#1 clk_in = ~clk_in;
end
end
wire hlt;
wire clr = 0;
wire[15:0] bus;
wire clk;
clock clock(
// In
.hlt(hlt),
.clk_in(clk_in),
// Out
.clk_out(clk)
);
wire pc_inc;
wire pc_load;
wire pc_en;
pc pc(
// In
.clk(clk),
.clr(clr),
.inc(pc_inc),
.load(pc_load),
.en(pc_en),
// Output
.bus(bus)
);
wire ir_load;
wire[7:0] ir_val;
ir ir(
// In
.clk(clk),
.clr(clr),
.load(ir_load),
// Inout
.bus(bus),
// Out
.out(ir_val)
);
wire mar_loadh;
wire mar_loadl;
wire mdr_load;
wire mdr_en;
wire ram_load;
wire ram_enh;
wire ram_enl;
wire call;
wire ret;
memory mem(
// In
.clk(clk),
.mar_loadh(mar_loadh),
.mar_loadl(mar_loadl),
.mdr_load(mdr_load),
.mdr_en(mdr_en),
.ram_load(ram_load),
.ram_enh(ram_enh),
.ram_enl(ram_enl),
.call(call),
.ret(ret),
// Inout
.bus(bus)
);
wire a_load;
wire a_en;
wire a_inc;
wire a_dec;
wire[7:0] a_val;
register reg_a(
// In
.clk(clk),
.load(a_load),
.en(a_en),
.inc(a_inc),
.dec(a_dec),
// Inout
.bus(bus),
// Out
.out(a_val)
);
wire b_load;
wire b_en;
wire b_inc;
wire b_dec;
wire[7:0] b_val;
register reg_b(
// In
.clk(clk),
.load(b_load),
.en(b_en),
.inc(b_inc),
.dec(b_dec),
// Inout
.bus(bus),
// Out
.out(b_val)
);
wire c_load;
wire c_en;
wire c_inc;
wire c_dec;
wire[7:0] c_val;
register reg_c(
// In
.clk(clk),
.load(c_load),
.en(c_en),
.inc(c_inc),
.dec(c_dec),
// Inout
.bus(bus),
// Out
.out(c_val)
);
wire[2:0] alu_op;
wire alu_load;
wire alu_en;
alu alu(
// In
.clk(clk),
.a(a_val),
.load(alu_load),
.op(alu_op),
.en(alu_en),
// Inout
.bus(bus)
);
wire[1:0] flags_val;
wire flags_lda;
wire flags_ldb;
wire flags_ldc;
flags flags(
// In
.clk(clk),
.a(a_val),
.b(b_val),
.c(c_val),
.load_a(flags_lda),
.load_b(flags_ldb),
.load_c(flags_ldc),
// Out
.out(flags_val)
);
controller controller(
.clk(clk),
.instr(ir_val),
.flags(flags_val),
.ctrl_word({
hlt,
a_load,
a_en,
a_inc,
a_dec,
b_load,
b_en,
b_inc,
b_dec,
c_load,
c_en,
c_inc,
c_dec,
flags_lda,
flags_ldb,
flags_ldc,
alu_op,
alu_load,
alu_en,
ir_load,
pc_inc,
pc_load,
pc_en,
mar_loadh,
mar_loadl,
mdr_load,
mdr_en,
ram_load,
ram_enh,
ram_enl,
call,
ret})
);
endmodule