summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.envrc1
-rw-r--r--.gitignore3
-rw-r--r--blinker.cabal84
-rw-r--r--flake.lock61
-rw-r--r--flake.nix99
-rw-r--r--src/Blinker.hs32
6 files changed, 280 insertions, 0 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..8392d15
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use flake
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..16023c9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+result
+.direnv
+dist-newstyle
\ No newline at end of file
diff --git a/blinker.cabal b/blinker.cabal
new file mode 100644
index 0000000..3a2d389
--- /dev/null
+++ b/blinker.cabal
@@ -0,0 +1,84 @@
+cabal-version:       2.4
+name:                Blinker
+version:             0.1
+license:             BSD-2-Clause
+author:              John Smith <john@example.com>
+maintainer:          John Smith <john@example.com>
+
+common common-options
+  default-extensions:
+    BangPatterns
+    BinaryLiterals
+    ConstraintKinds
+    DataKinds
+    DefaultSignatures
+    DeriveAnyClass
+    DeriveDataTypeable
+    DeriveFoldable
+    DeriveFunctor
+    DeriveGeneric
+    DeriveLift
+    DeriveTraversable
+    DerivingStrategies
+    InstanceSigs
+    KindSignatures
+    LambdaCase
+    NoStarIsType
+    PolyKinds
+    RankNTypes
+    ScopedTypeVariables
+    StandaloneDeriving
+    TupleSections
+    TypeApplications
+    TypeFamilies
+    TypeOperators
+    ViewPatterns
+
+    -- TemplateHaskell is used to support convenience functions such as
+    -- 'listToVecTH' and 'bLit'.
+    TemplateHaskell
+    QuasiQuotes
+
+    -- Prelude isn't imported by default as Clash offers Clash.Prelude
+    NoImplicitPrelude
+  ghc-options:
+    -Wall -Wcompat
+    -haddock
+
+    -- Plugins to support type-level constraint solving on naturals
+    -fplugin GHC.TypeLits.Extra.Solver
+    -fplugin GHC.TypeLits.Normalise
+    -fplugin GHC.TypeLits.KnownNat.Solver
+
+    -- Clash needs access to the source code in compiled modules
+    -fexpose-all-unfoldings
+
+    -- Worker wrappers introduce unstable names for functions that might have
+    -- blackboxes attached for them. You can disable this, but be sure to add
+    -- a no-specialize pragma to every function with a blackbox.
+    -fno-worker-wrapper
+
+    -- Strict annotations - while sometimes preventing space leaks - trigger
+    -- optimizations Clash can't deal with. See:
+    --
+    --    https://github.com/clash-lang/clash-compiler/issues/2361
+    --
+    -- These flags disables these optimizations. Note that the fields will
+    -- remain strict.
+    -fno-unbox-small-strict-fields
+    -fno-unbox-strict-fields
+  build-depends:
+    base,
+    Cabal,
+
+    -- clash-prelude will set suitable version bounds for the plugins
+    clash-prelude >= 1.8.1 && < 1.10,
+    ghc-typelits-natnormalise,
+    ghc-typelits-extra,
+    ghc-typelits-knownnat
+
+library
+  import: common-options
+  hs-source-dirs: src
+  exposed-modules: Blinker
+  default-language: Haskell2010
\ No newline at end of file
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..f6b8125
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,61 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1694529238,
+        "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1699781429,
+        "narHash": "sha256-UYefjidASiLORAjIvVsUHG6WBtRhM67kTjEY4XfZOFs=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "e44462d6021bfe23dfb24b775cc7c390844f773d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..1517d5a
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,99 @@
+{
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+    flake-utils.url = "github:numtide/flake-utils";
+  };
+
+  outputs = { nixpkgs, flake-utils, self }:
+    flake-utils.lib.eachDefaultSystem (system: 
+  let
+    name = "Blinker";
+    family = "Cyclone V";
+    device = "5CGXFC5C6F27C7";
+    hdl = "vhdl";
+    src = ./.;
+ 
+    pkgs = import nixpkgs { inherit system; config.allowUnfree = true; };
+    hpkgs = pkgs.haskellPackages.override {
+      overrides = self: super: {
+        clash-prelude = super.callHackageDirect {
+        pkg = "clash-prelude";
+        ver = "1.8.1";
+        sha256 = "sha256-HUt8Aw5vMFWThp26e/FdVkcjGQK8rvUV/ZMlv/KvHgg=";
+      } {};
+        clash-ghc = super.callHackageDirect {
+        pkg = "clash-ghc";
+        ver = "1.8.1";
+        sha256 = "sha256-oMK756+7WA5rGSRLkJ6Rpdkb2IkJ2VA6S82HGGyiK7Y=";
+      } {};
+        clash-lib = super.callHackageDirect {
+        pkg = "clash-lib";
+        ver = "1.8.1";
+        sha256 = "sha256-/dFgCj9e+gkyyUDAB1n1ukaEnkugCR7cRkP+SFJmjjY=";
+      } {};
+      };
+    };
+    hpkg = pkgs.haskell.lib.overrideCabal (hpkgs.callCabal2nix name src {}) (drv: {
+        enableLibraryProfiling = false;
+
+        postBuild = ''
+          ${hpkgs.clash-ghc}/bin/clash -package-db dist/package.conf.inplace ${name} --${hdl}
+        '';
+
+        postInstall = ''
+          mkdir -p "$out/share"
+          cp -r "${hdl}/" "$out/share/${hdl}"
+        '';
+    });
+
+    f = "${hpkg}/share/${hdl}/${name}.topEntity";
+    hdls = builtins.filter (x: pkgs.lib.hasSuffix hdl x) (builtins.attrNames (builtins.readDir f));
+    # qsys = pkgs.lib.findFirst (x: pkgs.lib.hasSuffix "qsys" x) (throw "no qsys found") (builtins.attrNames (builtins.readDir f));
+    qsf = pkgs.lib.concatStringsSep "\n" ([
+      "set_global_assignment -name DEVICE ${device}"
+      "set_global_assignment -name FAMILY \"${family}\""
+      "set_global_assignment -name TOP_LEVEL_ENTITY ${name}"
+      "set_global_assignment -name SDC_FILE ${name}.sdc"
+      # "set_global_assignment -name QSYS_FILE ${qsys}"
+    ] ++ (map (x: "set_global_assignment -name VHDL_FILE ${x}") hdls));
+  in
+    {
+      packages.default = hpkg;
+      packages.sof = pkgs.runCommand "${name}.sof" {
+        buildInputs = [ pkgs.quartus-prime-lite ];
+        src = pkgs.symlinkJoin {
+          name = "${name}.topEntity";
+          paths = [
+            "${hpkg}/share/${hdl}/${name}.topEntity"
+            (pkgs.writeTextDir "${name}.qsf" qsf)
+            (pkgs.writeTextDir "${name}.qpf" ''
+              PROJECT_REVISION = "${name}"
+            '')
+          ];
+        };
+      } ''
+        mkdir $out
+        ln -s $src/* .
+        # quartus_map --read_settings_files=on --write_settings_files=off Blinker -c Blinker
+        quartus_sh --flow compile ${name}
+        cp -r * $out
+      '';
+
+      devShells.default = hpkgs.shellFor {
+        packages = p: [ hpkg ];
+        nativeBuildInputs = [
+          pkgs.cabal-install
+          hpkgs.haskell-language-server
+          hpkgs.clash-ghc
+
+          (pkgs.writeShellScriptBin "flash" ''
+            quartus_pgm -m jtag -o "p;$1"
+          '')
+        ];
+        buildInputs = [ pkgs.quartus-prime-lite ];
+      };
+
+      formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt;
+    }
+  );
+}
diff --git a/src/Blinker.hs b/src/Blinker.hs
new file mode 100644
index 0000000..30e6f0e
--- /dev/null
+++ b/src/Blinker.hs
@@ -0,0 +1,32 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Blinker where
+
+import Clash.Prelude
+import Clash.Annotations.SynthesisAttributes
+
+-- Define a synthesis domain with a clock with a period of 20000 /ps/.
+-- i.e. 50 MHz
+-- createDomain vSystem{vName="Input", vPeriod=20000}
+
+-- Define a synthesis domain with a clock with a period of 50000 /ps/.
+-- i.e. 20 MHz
+createDomain vSystem{vName="Dom20MHz", vPeriod=50000}
+
+{-# ANN topEntity
+  (Synthesize
+    { t_name   = "Blinker"
+    , t_inputs = [ PortName "KEY0" ]
+    , t_output = PortName "LED"
+    }) #-}
+topEntity ::
+  Signal Dom20MHz Bit
+    `Annotate` 'StringAttr "chip_pin" "AC9"
+    `Annotate` 'StringAttr
+                "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\"" ->
+
+  Signal Dom20MHz Bit
+    `Annotate` 'StringAttr
+                "chip_pin" "F7"
+    `Annotate` 'StringAttr
+                "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
+topEntity sw = sw
\ No newline at end of file