Compare commits

..

2 Commits

Author SHA1 Message Date
69dbe3b7c6 Rename project 2024-01-12 13:45:05 +01:00
e9b8d44104 Start work on ALU 2024-01-12 13:44:33 +01:00
9 changed files with 140 additions and 70 deletions

View File

@ -1,5 +1,5 @@
{
description = "ice40 testing";
description = "fox32 on FPGA";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
@ -11,38 +11,23 @@
verilator = import ./verilator.nix pkgs ;
rot-sim = pkgs.runCommandCC "rot-sim" {} ''
cp "${./rot.v}" rot.v
${verilator}/bin/verilator --cc -O3 --exe --build --trace ${./sim_main.cpp} rot.v
vflags = "-Wpedantic -Wwarn-lint -Wwarn-style";
verilate-src = cmd: ''
cp -r ${./verilog-src} ./verilog-src
cp -r ${./simulation} ./simulation
find ./verilog-src/ -name '*.v' -exec ${verilator}/bin/verilator ${vflags} ${cmd} {} +
'';
lint = pkgs.runCommand "lint" {} ''
${verilate-src "--lint-only"}
echo "compiler didn't get angry :3"
: 3 > $out
'';
alu-sim = pkgs.runCommandCC "alu-sim" {} ''
${verilate-src "--cc --build --exe ./simulation/test_alu.cpp"}
mv obj_dir "$out"
'';
rot-trace = pkgs.runCommand "rot-trace" {} ''
mkdir "$out"
${rot-sim}/Vrot $out/trace.vcd
'';
rot-trace-view = pkgs.writeScriptBin "rot-view" ''
${pkgs.gtkwave}/bin/gtkwave ${rot-trace}/trace.vcd
'';
rot-synth = pkgs.runCommand "rot-synth" {} ''
mkdir "$out"
${pkgs.yosys}/bin/yosys -p "read -vlog95 ${./rot.v} ; synth_ice40 -json $out/synth.json"
'';
rot-route = pkgs.runCommand "rot-route" {} ''
mkdir "$out"
${pkgs.nextpnr}/bin/nextpnr-ice40 --pcf ${./rot.pcf} --json ${rot-synth}/synth.json --asc $out/routed.asc --up5k --top rot --freq 12
'';
rot-pack = pkgs.runCommand "rot-pack" {} ''
mkdir "$out"
${pkgs.icestorm}/bin/icepack ${rot-route}/routed.asc $out/packed.bin
'';
rot-upload = pkgs.writeScriptBin "rot-upload" ''
${pkgs.icestorm}/bin/iceprog ${rot-pack}/packed.bin
mkdir "$out/bin" && cp "$out/Valu" "$out/bin/alu-sim"
'';
deps = with pkgs; [
@ -51,15 +36,9 @@
in rec {
packages.verilator = verilator;
packages.rot-sim = rot-sim;
packages.rot-trace = rot-trace;
packages.rot-trace-view = rot-trace-view;
packages.rot-synth = rot-synth;
packages.rot-route = rot-route;
packages.rot-pack = rot-pack;
packages.rot-upload = rot-upload;
packages.lint = lint;
packages.alu-sim = alu-sim;
devShells.default = pkgs.mkShell {
packages = deps;
};

30
rot.v
View File

@ -1,30 +0,0 @@
module rot (input clk, output D0, output D1, output D2, output D3);
reg ready = 0;
reg [23:0] divider;
reg [3:0] rot;
always @(posedge clk) begin
if (ready)
begin
if (divider == 12_000_000)
begin
divider <= 0;
rot <= {rot[2], rot[1], rot[0], rot[3]};
end
else
divider <= divider + 1;
end
else begin
ready <= 1;
rot <= 4'b1;
divider <= 0;
end
end
assign D0 = rot[0];
assign D1 = rot[1];
assign D2 = rot[2];
assign D3 = rot[3];
endmodule

18
simulation/test_alu.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "Valu.h"
#include "verilated.h"
#include <iostream>
int main(int argc, char **argv) {
VerilatedContext *vctx = new VerilatedContext;
Valu *valu = new Valu(vctx);
valu->A = 0x2137;
valu->B = 0x1234;
valu->op = 0b000;
valu->eval();
printf("A = %04x + B = %04x = O = %04x\n", valu->A, valu->B, valu->O);
valu->op = 0b001;
valu->eval();
printf("A = %04x - B = %04x = O = %04x\n", valu->A, valu->B, valu->O);
}

28
verilog-src/alu.v Normal file
View File

@ -0,0 +1,28 @@
/*
A and B are inputs, O is out
OP is the operation to perform:
000 = add
001 = sub
010 = mul
(011)
100 = and
101 = or
110 = xor
111 = not A
*/
module alu(
input [31:0] A,
input [31:0] B,
input [2:0] op,
output [31:0] O,
output Cout,
output Fzero
);
wire subtraction = op == 3'b001;
wire [31:0] adder_B = subtraction ? ~B : B;
carry_select_adder a(A, adder_B, subtraction, O, Cout);
assign Fzero = & O;
endmodule

View File

@ -0,0 +1,29 @@
// 5 blocks of size 6, final block of size 2
module carry_select_adder(
input [31:0] A,
input [31:0] B,
input Cin,
output [31:0] O,
output Cout
);
// TODO: First block should not be carry_select, a normal RCA is better
// i think?
wire Cout_5;
carry_select_block#(6) B0 (A[5:0], B[5:0], Cin, O[5:0], Cout_5);
wire Cout_11;
carry_select_block#(6) B1 (A[11:6], B[11:6], Cout_5, O[11:6], Cout_11);
wire Cout_17;
carry_select_block#(6) B2 (A[17:12], B[17:12], Cout_11, O[17:12], Cout_17);
wire Cout_23;
carry_select_block#(6) B3 (A[23:18], B[23:18], Cout_17, O[23:18], Cout_23);
wire Cout_29;
carry_select_block#(6) B4 (A[29:24], B[29:24], Cout_23, O[29:24], Cout_29);
carry_select_block#(2) B6 (A[31:30], B[31:30], Cout_29, O[31:30], Cout);
endmodule

View File

@ -0,0 +1,39 @@
module carry_select_block#(
parameter N = 4
) (
input [N-1:0] A,
input [N-1:0] B,
input Cin,
output [N-1:0] O,
output Cout
);
// Case for Cin = 0
wire [N-1:0] O_C0;
wire Cout_C0;
begin
wire [N-1:1] carry;
fa fa0(A[0], B[0], 0, O_C0[0], carry[1]);
genvar i; for (i = 1; i <= N - 1; i = i + 1) begin
fa fai(A[i], B[i], carry[i], O_C0[i], carry[i+1]);
end
assign Cout_C0 = carry[N-1];
end
// Case for Cin = 1
wire [N-1:0] O_C1;
wire Cout_C1;
begin
wire [N-1:1] carry;
fa fa0(A[0], B[0], 1, O_C1[0], carry[1]);
genvar i; for (i = 1; i <= N - 1; i = i + 1) begin
fa fai(A[i], B[i], carry[i], O_C1[i], carry[i+1]);
end
assign Cout_C1 = carry[N-1];
end
assign O = Cin == 0 ? O_C0 : O_C1;
assign Cout = Cin == 0 ? Cout_C0 : Cout_C1;
endmodule

7
verilog-src/alu/fa.v Normal file
View File

@ -0,0 +1,7 @@
// One bit full-adder
module fa(input A, input B, input Cin, output O, output Cout);
assign O = A ^ B ^ Cin;
assign Cout = (A & B) | (B & Cin) | (Cin & A);
endmodule