Compare commits
2 Commits
8c126980a6
...
69dbe3b7c6
Author | SHA1 | Date | |
---|---|---|---|
69dbe3b7c6 | |||
e9b8d44104 |
59
flake.nix
59
flake.nix
|
@ -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
30
rot.v
|
@ -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
18
simulation/test_alu.cpp
Normal 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
28
verilog-src/alu.v
Normal 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
|
29
verilog-src/alu/carry_select_adder.v
Normal file
29
verilog-src/alu/carry_select_adder.v
Normal 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
|
39
verilog-src/alu/carry_select_block.v
Normal file
39
verilog-src/alu/carry_select_block.v
Normal 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
7
verilog-src/alu/fa.v
Normal 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
|
Loading…
Reference in New Issue
Block a user