1
0
Fork 0
This commit is contained in:
Austin Morlan 2023-01-03 18:26:45 -08:00
parent 1ffabc4e7b
commit ac7850987a
Signed by: austin
GPG Key ID: FD6B27654AF5E348
13 changed files with 535 additions and 0 deletions

58
build.sh Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -e
SRC_DIR=$(pwd)/src
BUILD_DIR=$(pwd)/.build
APIO_HOME_DIR=$(pwd)/.apio
BIN_DIR=$APIO_HOME_DIR/packages/tools-oss-cad-suite/bin
COMMAND=$1
VERSION=$2
MODULES="
$SRC_DIR/adder.v
$SRC_DIR/clock.v
$SRC_DIR/controller.v
$SRC_DIR/ir.v
$SRC_DIR/memory.v
$SRC_DIR/pc.v
$SRC_DIR/reg_a.v
$SRC_DIR/reg_b.v"
TOP=$SRC_DIR/top.v
TB=$SRC_DIR/top_tb.v
if [ -z "$COMMAND" ]; then
mkdir -p $BUILD_DIR
pushd $BUILD_DIR > /dev/null
$BIN_DIR/yosys -q -p "synth_ice40 -json hardware.json" $MODULES $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
elif [ "$COMMAND" == "init" ]; then
virtualenv .env
source .env/bin/activate
pip install apio tinyprog
export APIO_HOME_DIR=$APIO_HOME_DIR
apio install oss-cad-suite
elif [ "$COMMAND" == "clean" ]; then
rm -r $BUILD_DIR
elif [ "$COMMAND" == "program" ]; then
source .env/bin/activate
sudo tinyprog -p $BUILD_DIR/hardware.bin
elif [ "$COMMAND" == "sim" ]; then
mkdir -p $BUILD_DIR
pushd $SRC_DIR > /dev/null
$BIN_DIR/iverilog -o $BUILD_DIR/top_tb $MODULES $TB
$BIN_DIR/vvp $BUILD_DIR/top_tb
mv top_tb.vcd $BUILD_DIR/
popd > /dev/null
gtkwave $BUILD_DIR/top_tb.vcd $BUILD_DIR/top_tb.gtkw
else
echo "Invalid arguments"
fi

14
src/adder.v Normal file
View File

@ -0,0 +1,14 @@
module adder(
input[7:0] a,
input[7:0] b,
input sub,
input en,
output[7:0] bus);
assign bus =
(en) ?
((sub) ? a-b : a+b) :
8'bz;
endmodule

9
src/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

123
src/controller.v Normal file
View File

@ -0,0 +1,123 @@
module controller(
input clk,
input[3:0] instr,
output reg[11:0] ctrl_word);
localparam SIG_HLT = 11;
localparam SIG_PC_INC = 10;
localparam SIG_PC_EN = 9;
localparam SIG_MEM_LOAD = 8;
localparam SIG_MEM_EN = 7;
localparam SIG_IR_LOAD = 6;
localparam SIG_IR_EN = 5;
localparam SIG_A_LOAD = 4;
localparam SIG_A_EN = 3;
localparam SIG_B_LOAD = 2;
localparam SIG_ADDER_SUB = 1;
localparam SIG_ADDER_EN = 0;
localparam OP_LDA = 4'b0000;
localparam OP_ADD = 4'b0001;
localparam OP_SUB = 4'b0010;
localparam OP_HLT = 4'b1111;
reg[2:0] stage = 0;
always @(negedge clk) begin
if (stage == 6) begin
stage <= 1;
end else begin
stage <= stage + 1;
end
end
always @(*) begin
case (stage)
1: begin
ctrl_word = 12'b0;
ctrl_word[SIG_PC_EN] = 1;
ctrl_word[SIG_MEM_LOAD] = 1;
end
2: begin
ctrl_word = 12'b0;
ctrl_word[SIG_PC_INC] = 1;
end
3: begin
ctrl_word = 12'b0;
ctrl_word[SIG_MEM_EN] = 1;
ctrl_word[SIG_IR_LOAD] = 1;
end
4: begin
case (instr)
OP_LDA: begin
ctrl_word = 12'b0;
ctrl_word[SIG_IR_EN] = 1;
ctrl_word[SIG_MEM_LOAD] = 1;
end
OP_ADD: begin
ctrl_word = 12'b0;
ctrl_word[SIG_IR_EN] = 1;
ctrl_word[SIG_MEM_LOAD] = 1;
end
OP_SUB: begin
ctrl_word = 12'b0;
ctrl_word[SIG_IR_EN] = 1;
ctrl_word[SIG_MEM_LOAD] = 1;
end
OP_HLT: begin
ctrl_word = 12'b0;
ctrl_word[SIG_HLT] = 1;
end
default: begin
ctrl_word = 12'b0;
end
endcase
end
5: begin
case (instr)
OP_LDA: begin
ctrl_word = 12'b0;
ctrl_word[SIG_MEM_EN] = 1;
ctrl_word[SIG_A_LOAD] = 1;
end
OP_ADD: begin
ctrl_word = 12'b0;
ctrl_word[SIG_MEM_EN] = 1;
ctrl_word[SIG_B_LOAD] = 1;
end
OP_SUB: begin
ctrl_word = 12'b0;
ctrl_word[SIG_MEM_EN] = 1;
ctrl_word[SIG_B_LOAD] = 1;
end
default: begin
ctrl_word = 12'b0;
end
endcase
end
6: begin
case (instr)
OP_ADD: begin
ctrl_word = 12'b0;
ctrl_word[SIG_ADDER_EN] = 1;
ctrl_word[SIG_A_LOAD] = 1;
end
OP_SUB: begin
ctrl_word = 12'b0;
ctrl_word[SIG_ADDER_SUB] = 1;
ctrl_word[SIG_ADDER_EN] = 1;
ctrl_word[SIG_A_LOAD] = 1;
end
default: begin
ctrl_word = 12'b0;
end
endcase
end
default: begin
ctrl_word = 12'b0;
end
endcase
end
endmodule

23
src/ir.v Normal file
View File

@ -0,0 +1,23 @@
module ir(
input clk,
input clr,
input load,
input en,
inout[7:0] bus,
output[3:0] instr);
reg[7:0] ir = 0;
always @(posedge clk or posedge clr) begin
if (clr) begin
ir <= 8'b0;
end else if (load) begin
ir <= bus;
end
end
assign instr = ir[7:4];
assign bus = (en) ? ir[3:0] : 8'bz;
endmodule

24
src/memory.v Normal file
View File

@ -0,0 +1,24 @@
module memory(
input clk,
input load,
input en,
inout[7:0] bus
);
initial begin
$readmemh("program.bin", ram);
end
reg[3:0] mar = 0;
reg[7:0] ram[0:15];
always @(posedge clk) begin
if (load) begin
mar <= bus[3:0];
end
end
assign bus = (en) ? ram[mar] : 8'bz;
endmodule

22
src/pc.v Normal file
View File

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

2
src/pins.pcf Normal file
View File

@ -0,0 +1,2 @@
set_io --warn-no-port CLK B2 # input

16
src/program.bin Normal file
View File

@ -0,0 +1,16 @@
0D
1E
2F
F0
00
00
00
00
00
00
00
00
00
03
04
02

20
src/reg_a.v Normal file
View File

@ -0,0 +1,20 @@
module reg_a(
input clk,
input load,
input en,
inout[7:0] bus,
output[7:0] val);
reg[7:0] reg_a = 0;
always @(posedge clk) begin
if (load) begin
reg_a <= bus;
end
end
assign bus = (en) ? reg_a : 8'bz;
assign val = reg_a;
endmodule

18
src/reg_b.v Normal file
View File

@ -0,0 +1,18 @@
module reg_b(
input clk,
input load,
input[7:0] bus,
output[7:0] val);
reg[7:0] reg_b = 0;
always @(posedge clk) begin
if (load) begin
reg_b <= bus;
end
end
assign val = reg_b;
endmodule

97
src/top.v Normal file
View File

@ -0,0 +1,97 @@
module top(
input CLK);
wire[7:0] bus;
wire clk;
wire hlt;
clock clock(
.hlt(hlt),
.clk_in(CLK),
.clk_out(clk)
);
wire clr;
wire pc_en;
wire pc_inc;
pc pc(
.clk(clk),
.clr(clr),
.inc(pc_inc),
.en(pc_en),
.bus(bus)
);
wire a_load;
wire a_en;
wire[7:0] a_val;
reg_a reg_a(
.clk(clk),
.load(a_load),
.en(a_en),
.bus(bus),
.val(a_val)
);
wire b_load;
wire[7:0] b_val;
reg_b reg_b(
.clk(clk),
.load(b_load),
.bus(bus),
.val(b_val)
);
wire adder_sub;
wire adder_en;
adder adder(
.a(a_val),
.b(b_val),
.sub(adder_sub),
.en(adder_en),
.bus(bus)
);
wire mar_load;
wire mem_en;
memory mem(
.clk(clk),
.load(mar_load),
.en(mem_en),
.bus(bus)
);
wire ir_load;
wire ir_en;
wire[3:0] ir_instr;
ir ir(
.clk(clk),
.clr(clr),
.load(ir_load),
.en(ir_en),
.bus(bus),
.instr(ir_instr)
);
controller controller(
.clk(clk),
.instr(ir_instr),
.ctrl_word(
{
hlt,
pc_inc,
pc_en,
mar_load,
mem_en,
ir_load,
ir_en,
a_load,
a_en,
b_load,
adder_sub,
adder_en
})
);
endmodule

109
src/top_tb.v Normal file
View File

@ -0,0 +1,109 @@
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 < 128; i++) begin
#1 clk_in = ~clk_in;
end
end
wire clk;
wire hlt;
wire clr;
wire[7:0] bus;
clock clock(
.hlt(hlt),
.clk_in(clk_in),
.clk_out(clk)
);
wire pc_en;
wire pc_inc;
pc pc(
.clk(clk),
.clr(clr),
.inc(pc_inc),
.en(pc_en),
.bus(bus)
);
wire a_load;
wire a_en;
wire[7:0] a_val;
reg_a reg_a(
.clk(clk),
.load(a_load),
.en(a_en),
.bus(bus),
.val(a_val)
);
wire b_load;
wire[7:0] b_val;
reg_b reg_b(
.clk(clk),
.load(b_load),
.bus(bus),
.val(b_val)
);
wire adder_sub;
wire adder_en;
adder adder(
.a(a_val),
.b(b_val),
.sub(adder_sub),
.en(adder_en),
.bus(bus)
);
wire mar_load;
wire mem_en;
memory mem(
.clk(clk),
.load(mar_load),
.en(mem_en),
.bus(bus)
);
wire ir_load;
wire ir_en;
wire[3:0] ir_instr;
ir ir(
.clk(clk),
.clr(clr),
.load(ir_load),
.en(ir_en),
.bus(bus),
.instr(ir_instr)
);
controller controller(
.clk(clk),
.instr(ir_instr),
.ctrl_word(
{
hlt,
pc_inc,
pc_en,
mar_load,
mem_en,
ir_load,
ir_en,
a_load,
a_en,
b_load,
adder_sub,
adder_en
})
);
endmodule