diff options
-rw-r--r-- | Makefile | 39 | ||||
-rwxr-xr-x | clean.sh | 13 | ||||
-rw-r--r-- | flake.lock | 11 | ||||
-rw-r--r-- | flake.nix | 18 | ||||
-rw-r--r-- | src/Top.bs | 111 | ||||
-rw-r--r-- | src/icebreaker.pcf | 54 |
6 files changed, 172 insertions, 74 deletions
@@ -1,19 +1,36 @@ -BSC_COMP_FLAGS = -aggressive-conditions -check-assert -keep-fires +BSC_COMP_FLAGS = -aggressive-conditions -bdir tmp -check-assert -keep-fires \ + -p src:$(BSC_CONTRIB)/Libraries/FPGA/Misc:+ -vdir tmp BSC_LINK_FLAGS = -keep-fires +BSC_SOURCES = Counter.v SizedFIFO.v TOPFILE = Top TOPMODULE = mkTop +SRCS = $(shell find src -name '*.bs') -all: tmp/$(TOPMODULE).exe tmp/$(TOPMODULE).v +all: tmp/$(TOPMODULE).bin clean: clean.sh - @./clean.sh -.PHONY: all clean + @git status --porcelain=v1 --ignored -z \ + | grep -z '^!!' \ + | xargs -0 awk 'BEGIN { for(i = 1; i < ARGC; i++) printf "%s%c", substr(ARGV[i], 4), 0; }' \ + | xargs -0 rm -r +flash: tmp/$(TOPMODULE).bin + sudo iceprog $< +.PHONY: all clean flash -tmp/$(TOPMODULE).exe: tmp/$(TOPMODULE).ba +tmp/%.bin: tmp/%.asc + # icetime -d up5k -c 12 $< + icepack $< $@ +tmp/%.asc: tmp/%.json src/icebreaker.pcf + nextpnr-ice40 -ql tmp/$*.nplog --up5k --package sg48 --freq 12 \ + --asc $@ --pcf src/icebreaker.pcf --json $< +tmp/$(TOPMODULE).json: tmp/$(TOPMODULE).v $(addprefix $(BSC)/lib/Verilog/,$(BSC_SOURCES)) + yosys -ql tmp/$(TOPMODULE).yslog -p 'synth_ice40 -top mkTop -json $@' $^ +tmp/$(TOPMODULE).v: tmp/$(TOPFILE).bo + bsc -g $(TOPMODULE) -verilog $(BSC_COMP_FLAGS) src/$(TOPFILE).bs +tmp/%.bo: @mkdir -p $(dir $@) - bsc -e $(TOPMODULE) -o $@ -p $(dir $<) -sim -simdir tmp -u $(BSC_LINK_FLAGS) -tmp/$(TOPMODULE).ba: src/$(TOPFILE).bs - @mkdir -p $(dir $@) - bsc -bdir $(dir $@) -g $(TOPMODULE) -sim -u $(BSC_COMP_FLAGS) $< -tmp/$(TOPMODULE).v: src/$(TOPFILE).bs + bsc -verilog $(BSC_COMP_FLAGS) $< + +tmp/depends.mk: @mkdir -p $(dir $@) - bsc -bdir tmp -g $(TOPMODULE) -u -verilog -vdir tmp $(BSC_COMP_FLAGS) $< + bluetcl -exec makedepend $(BSC_COMP_FLAGS) src/$(TOPFILE).bs > $@ +include tmp/depends.mk diff --git a/clean.sh b/clean.sh deleted file mode 100755 index 68769e6..0000000 --- a/clean.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -set -eu - -cd "$(git rev-parse --show-toplevel)" - -if [ "$(git status --porcelain=v1 --ignored -z | grep -z '^!!' | wc -c)" = 0 ]; then - exit -fi - -git status --porcelain=v1 --ignored -z \ -| grep -z '^!!' \ -| xargs -0 awk 'BEGIN { for(i = 1; i < ARGC; i++) printf "%s%c", substr(ARGV[i], 4), 0; }' \ -| xargs -0 rm -r @@ -19,16 +19,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1708702655, - "narHash": "sha256-qxT5jSLhelfLhQ07+AUxSTm1VnVH+hQxDkQSZ/m/Smo=", + "lastModified": 1714933973, + "narHash": "sha256-a3cOXb2Hhj/z6N+oCfJJTdpWUx0V8rTqmY96i8N9B0A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c5101e457206dd437330d283d6626944e28794b3", + "rev": "135fbd12c398100f8071584d2b8c9c7aa2bc5e99", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" } }, "root": { @@ -1,7 +1,16 @@ { + inputs.nixpkgs.url = "github:NixOS/nixpkgs"; outputs = { self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem (system: - let pkgs = nixpkgs.legacyPackages.${system}; + let + pkgs = nixpkgs.legacyPackages.${system}; + bsc-contrib = pkgs.fetchFromGitHub { + name = "bsc-contrib-src"; + owner = "B-Lang-org"; + repo = "bsc-contrib"; + rev = "fc26b91c8add9660204c4311dcc60d223ed23ea5"; + hash = "sha256-7H+R7QwcyskrXGO51zZuuyIwZZROc25gJy9nqg/I6lM="; + }; in rec { devShells.default = pkgs.mkShell { inputsFrom = builtins.attrValues packages; @@ -9,9 +18,14 @@ pkgs.bluespec pkgs.gtkwave pkgs.icestorm - pkgs.verilator + pkgs.nextpnr + pkgs.picocom pkgs.yosys ]; + env = { + BSC = pkgs.bluespec; + BSC_CONTRIB = bsc-contrib; + }; }; packages = { }; @@ -1,53 +1,78 @@ package Top where -mkTop :: Module Empty -mkTop = - module - deepThought :: DeepThought_IFC <- mkDeepThought - - rules - "rl_ask": when True ==> do - $display "Asking the Ultimate Question of Life, The Universe and Everything" - deepThought.whatIsTheAnswer +import GetPut +import RS232 - "rl_print_answer": when True ==> do - x <- deepThought.getAnswer - $display "Deep Thought says: Hello, World! The answer is %0d." x - $finish +interface Top = + -- RS232 + rx :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [RX] #-} + tx :: Bit 1 {-# always_ready, result = TX #-} + -- Onboard LEDs + ledR_N :: Bit 1 {-# always_ready, result = LEDR_N #-} + ledG_N :: Bit 1 {-# always_ready, result = LEDG_N #-} + -- RGB LED driver + ledRed_N :: Bit 1 {-# always_ready, result = LED_RED_N #-} + ledGrn_N :: Bit 1 {-# always_ready, result = LED_GRN_N #-} + ledBlu_N :: Bit 1 {-# always_ready, result = LED_BLU_N #-} + -- LEDs and buttons (PMOD 2) + led1 :: Bit 1 {-# always_ready, result = LED1 #-} + led2 :: Bit 1 {-# always_ready, result = LED2 #-} + led3 :: Bit 1 {-# always_ready, result = LED3 #-} + led4 :: Bit 1 {-# always_ready, result = LED4 #-} + led5 :: Bit 1 {-# always_ready, result = LED5 #-} + btn1 :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [BTN1] #-} + btn2 :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [BTN2] #-} + btn3 :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [BTN3] #-} -interface DeepThought_IFC = - whatIsTheAnswer :: Action - getAnswer :: ActionValue (Int 32) +clockFreqHz :: Integer +clockFreqHz = 12_000_000 -data State_DT = IDLE | THINKING | ANSWER_READY - deriving (Eq, Bits, FShow) - -mkDeepThought :: Module DeepThought_IFC -mkDeepThought = +mkTop :: Module Top +mkTop = module - rg_state_dt :: Reg State_DT <- mkReg IDLE - rg_half_millenia :: Reg (Bit 4) <- mkReg 0 + let uartBaud :: Integer + uartBaud = 115200 + uartDivider :: Integer + uartDivider = clockFreqHz / uartBaud + uart :: UART 8 <- mkUART 8 NONE STOP_1 (fromInteger uartDivider) - let millenia = rg_half_millenia [3:1] - let half_millenium = rg_half_millenia [0:0] + clkState :: Reg (Bit 32) <- mkReg 0 + btn1State :: Reg (Bit 1) <- mkReg 0 + btn2State :: Reg (Bit 1) <- mkReg 0 + btn3State :: Reg (Bit 1) <- mkReg 0 + led4State :: Reg (Bit 1) <- mkReg 0 + led5State :: Reg (Bit 1) <- mkReg 0 rules - "rl_think": when (rg_state_dt == THINKING) ==> do - $write " DeepThought: ... thinking ... (%0d" millenia - if (half_millenium == 1) then $write ".5" else noAction - $display " million years)" - - if (rg_half_millenia == 15) then - rg_state_dt := ANSWER_READY - else - rg_half_millenia := rg_half_millenia + 1 - - interface - whatIsTheAnswer = rg_state_dt := THINKING - when (rg_state_dt == IDLE) + "echo": when (clkState == 0) ==> do + led4State := led4State + 1 + uart.rx.put 0x7e + "increment_clock": when True ==> do + if clkState == fromInteger (clockFreqHz / 10) then do + clkState := 0 + led5State := led5State + 1 + else + clkState := clkState + 1 - getAnswer = do - rg_state_dt := IDLE - rg_half_millenia := 0 - return 42 - when (rg_state_dt == ANSWER_READY) + interface Top + -- RS232 + rx = uart.rs232.sin + tx = uart.rs232.sout + -- Onboard LEDs + ledR_N = 1 + ledG_N = 1 + -- RGB LED driver + ledRed_N = 1 + ledGrn_N = 1 + ledBlu_N = 1 + -- LEDs and buttons (PMOD 2) + led1 = btn1State + led2 = btn2State + led3 = btn3State + led4 = led4State + led5 = led5State + btn1 x = btn1State := x + btn2 x = btn2State := x + btn3 x = btn3State := x +{-# verilog mkTop #-} +{-# properties mkTop = { RSTN = BTN_N } #-} diff --git a/src/icebreaker.pcf b/src/icebreaker.pcf new file mode 100644 index 0000000..1164c98 --- /dev/null +++ b/src/icebreaker.pcf @@ -0,0 +1,54 @@ +# 12 MHz clock +set_io -nowarn CLK 35 + +# RS232 +set_io -nowarn RX 6 +set_io -nowarn TX 9 + +# LEDs and Button +set_io -nowarn BTN_N 10 +set_io -nowarn LEDR_N 11 +set_io -nowarn LEDG_N 37 + +# RGB LED Driver +set_io -nowarn LED_RED_N 39 +set_io -nowarn LED_GRN_N 40 +set_io -nowarn LED_BLU_N 41 + +# SPI Flash +set_io -nowarn FLASH_SCK 15 +set_io -nowarn FLASH_SSB 16 +set_io -nowarn FLASH_IO0 14 +set_io -nowarn FLASH_IO1 17 +set_io -nowarn FLASH_IO2 12 +set_io -nowarn FLASH_IO3 13 + +# PMOD 1A +set_io -nowarn P1A1 4 +set_io -nowarn P1A2 2 +set_io -nowarn P1A3 47 +set_io -nowarn P1A4 45 +set_io -nowarn P1A7 3 +set_io -nowarn P1A8 48 +set_io -nowarn P1A9 46 +set_io -nowarn P1A10 44 + +# PMOD 1B +set_io -nowarn P1B1 43 +set_io -nowarn P1B2 38 +set_io -nowarn P1B3 34 +set_io -nowarn P1B4 31 +set_io -nowarn P1B7 42 +set_io -nowarn P1B8 36 +set_io -nowarn P1B9 32 +set_io -nowarn P1B10 28 + +# LEDs and Buttons (PMOD 2) +set_io -nowarn LED1 26 +set_io -nowarn LED2 27 +set_io -nowarn LED3 25 +set_io -nowarn LED4 23 +set_io -nowarn LED5 21 +set_io -nowarn BTN1 20 +set_io -nowarn BTN2 19 +set_io -nowarn BTN3 18 |