├── .gitignore ├── LICENSE ├── Make.2057.rules ├── Make.icestick.rules ├── Make.rules ├── Make.upduino.rules ├── Makefile ├── README.md ├── always ├── Makefile ├── README.md ├── always0 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── always1 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── always2 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── always3 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── always4 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── always5 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── always6 │ ├── Makefile │ ├── README.md │ ├── led.v │ └── top_tb.v ├── blinky ├── Makefile ├── blinky1 │ ├── Makefile │ ├── pinmap-2057.pcf │ ├── pinmap-icestick.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v └── blinky2 │ ├── Makefile │ ├── README.md │ ├── counter.v │ ├── counter_tb.v │ ├── pinmap-2057.pcf │ ├── pinmap-icestick.pcf │ ├── pinmap-upduino.pcf │ └── top.v ├── case ├── Makefile ├── README.md ├── case0 │ ├── Makefile │ ├── README.md │ ├── led.v │ └── top_tb.v └── case1 │ ├── Makefile │ ├── README.md │ ├── bassackward.v │ └── top_tb.v ├── equality ├── Makefile ├── README.md └── top_tb.v ├── fsm ├── Makefile ├── README.md ├── fsm0 │ ├── Makefile │ ├── README.md │ ├── fsm.v │ └── top_tb.v ├── fsm1 │ ├── Makefile │ ├── README.md │ ├── fsm.v │ └── top_tb.v ├── fsm2 │ ├── Makefile │ ├── README.md │ ├── fsm.v │ └── top_tb.v ├── fsm3 │ ├── Makefile │ ├── README.md │ ├── fsm.v │ ├── top2_tb.v │ └── top_tb.v └── fsm4 │ ├── Makefile │ ├── README.md │ ├── fsm.v │ ├── top2_tb.v │ └── top_tb.v ├── halfadder ├── Makefile ├── halfadder1 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder2 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder3 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder4 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder5 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder6 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── halfadder7 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v └── halfadder8 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── lib ├── debounce │ ├── Makefile │ ├── debounce.v │ └── debounce_tb.v ├── stretcher │ ├── Makefile │ ├── README.md │ ├── sync_stretch.v │ └── sync_stretch_tb.v └── sync │ ├── Makefile │ ├── README.md │ ├── sync.v │ └── sync_tb.v ├── minimal ├── Makefile ├── minimal1 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-icestick.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── minimal2 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-icestick.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v └── minimal3 │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── pinmap-icestick.pcf │ ├── pinmap-upduino.pcf │ ├── top.v │ └── top_tb.v ├── modules ├── Makefile ├── README.md ├── mod0 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── mod1 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── nonblock ├── Makefile ├── nb1 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── nb2 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── nb3 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── pics ├── selsig.png └── waveform.png ├── pll ├── README.md ├── example1 │ ├── Makefile │ ├── README.md │ ├── counter.v │ ├── counter_tb.v │ ├── pinmap-2057.pcf │ ├── pll_25_100.v │ ├── pll_25_40.v │ └── top.v └── example2 │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── counter.v │ ├── pinmap-2057.pcf │ └── top.v ├── prog-2057-flash.sh ├── ps2 ├── Makefile ├── naive-reset │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── ps2.v │ ├── ps2_tb.v │ └── top.v └── naive │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ ├── ps2.v │ ├── ps2_tb.v │ └── top.v ├── sb_io ├── Makefile ├── README.md ├── bidir │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ └── top.v ├── tristate_sb_io │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ └── top.v └── tristate_ternary │ ├── Makefile │ ├── README.md │ ├── pinmap-2057.pcf │ └── top.v ├── sim ├── Makefile ├── sim1 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── sim2 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── sim3 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── sim4 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── sim5 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── sim6 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── types ├── Makefile ├── types1 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── types2 │ ├── Makefile │ ├── README.md │ └── top_tb.v ├── types3 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── types4 │ ├── Makefile │ ├── README.md │ └── top_tb.v └── vga ├── Makefile ├── bars-1024x768 ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── bars-1280x1024 ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── bars-640x350 ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── bars-720x400 ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── bars ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── sync ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── top.v ├── vgasync.v └── vgasync_tb.v ├── vdp-1280x1024div4 ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── rom_binnacle.hex ├── rom_color.hex ├── rom_name.hex ├── rom_pattern.hex ├── top.v ├── vdp_table_test.v ├── vdp_table_test_tb.v ├── vdp_timing_test.v ├── vgasync.v └── vgasync_tb.v ├── vdp-640x480div2 ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── rom_binnacle.hex ├── rom_color.hex ├── rom_name.hex ├── rom_pattern.hex ├── top.v ├── vdp_table_test.v ├── vdp_table_test_tb.v ├── vgasync.v └── vgasync_tb.v └── vdp ├── .gitignore ├── Makefile ├── README.md ├── pinmap-2057.pcf ├── rom_binnacle.hex ├── rom_color.hex ├── rom_name.hex ├── rom_pattern.hex ├── top.v ├── vdp_table_test.v ├── vdp_table_test_tb.v ├── vdp_timing_test.v ├── vgasync.v └── vgasync_tb.v /.gitignore: -------------------------------------------------------------------------------- 1 | *.asc 2 | *.bin 3 | *.json 4 | *.vcd 5 | *.vvp 6 | Make.local 7 | X 8 | new 9 | -------------------------------------------------------------------------------- /Make.2057.rules: -------------------------------------------------------------------------------- 1 | # rules that are specific to the 2057-ICE40HX4K-TQ144-breakout board 2 | # for arachne, set DEVICE = 8k 3 | # for nextpnr, set DEVICE = hx8k 4 | 5 | #DEVICE = 8k 6 | DEVICE = hx8k 7 | PACKAGE = tq144:4k 8 | FLASH_PROG = sudo $(TOP)/prog-2057-flash.sh 9 | PINMAP = pinmap-2057.pcf 10 | -------------------------------------------------------------------------------- /Make.icestick.rules: -------------------------------------------------------------------------------- 1 | # rules that are specific to the IceStick board 2 | 3 | #DEVICE = 1k 4 | DEVICE = hx1k 5 | PACKAGE = tq144 6 | FLASH_PROG = iceprog -d i:0x0403:0x6010:0 7 | PINMAP = pinmap-icestick.pcf 8 | -------------------------------------------------------------------------------- /Make.upduino.rules: -------------------------------------------------------------------------------- 1 | # rules that are specific to the IceStick board 2 | 3 | DEVICE = up5k 4 | PACKAGE = sg48 5 | FLASH_PROG = sudo iceprog -d i:0x0403:0x6014 6 | PINMAP = pinmap-upduino.pcf 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TOP=. 2 | 3 | SUBDIRS= \ 4 | minimal \ 5 | halfadder \ 6 | sim \ 7 | blinky \ 8 | types \ 9 | always \ 10 | vga \ 11 | sb_io 12 | 13 | include $(TOP)/Make.rules 14 | -------------------------------------------------------------------------------- /always/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | always0 \ 5 | always1 \ 6 | always2 \ 7 | always3 \ 8 | always4 \ 9 | always5 \ 10 | always6 11 | 12 | include $(TOP)/Make.rules 13 | -------------------------------------------------------------------------------- /always/always0/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always0/README.md: -------------------------------------------------------------------------------- 1 | The `always` block can be used in a number of different ways. 2 | 3 | Here we see an example of it creating a periodic clock and a combinational circuit. 4 | -------------------------------------------------------------------------------- /always/always0/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module tb(); 4 | 5 | reg clk3; 6 | reg clk11; 7 | reg func; 8 | 9 | initial begin 10 | $dumpfile("top_tb.vcd"); 11 | $dumpvars; 12 | 13 | clk3 = 0; 14 | clk11 = 0; 15 | 16 | #100; // wait a while 17 | $finish; // stop the simulation 18 | end 19 | 20 | // Two processes that can not be synthesized. 21 | // But are useful for simulation to generate clock signals. 22 | always begin 23 | #3; 24 | clk3 = ~clk3; 25 | end 26 | 27 | always #11 clk11 = ~clk11; 28 | 29 | // This is a synthesizable combinational process/circuit. 30 | // @* means: Run this once each time anything used as input changes. 31 | always @* 32 | func = clk3 & clk11; 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /always/always1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always1/README.md: -------------------------------------------------------------------------------- 1 | An always block implementing a decoder. 2 | -------------------------------------------------------------------------------- /always/always1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | reg c; 8 | reg [7:0] Y; 9 | 10 | initial begin 11 | $dumpfile("top_tb.vcd"); // where to write the dump 12 | $dumpvars; // dump EVERYTHING 13 | end 14 | 15 | initial begin 16 | // %2t leaves room for 2-digts 17 | //$monitor("time:%2t addr=%d,%b Y=%b", $time, {a,b,c}, {a,b,c}, Y ); 18 | $monitor("time:%2t addr=%b%b%b Y=%b", $time, a, b, c, Y ); 19 | 20 | // the implied length of {a,b,c} is 3 because a, b, and c are 1 each 21 | {a,b,c} = 0; 22 | #1; 23 | {a,b,c} = 1; 24 | #1; 25 | {a,b,c} = 2; 26 | #1; 27 | {a,b,c} = 3; 28 | #1; 29 | {a,b,c} = 4; 30 | #1; 31 | {a,b,c} = 5; 32 | #1; 33 | {a,b,c} = 6; 34 | #1; 35 | {a,b,c} = 7; 36 | #1; 37 | 38 | $finish; 39 | end 40 | 41 | always @* // simple but subtle! 42 | // always @( * ) // same as @* 43 | // always @( a, b, c ) // if we list ALL the RHS signals here, then is same as * 44 | // always @( a or b or c ) // the original way... eewwwww! (punctuation is clearer!) 45 | begin 46 | // note that else-if, else-if,... is not necessairly the best way to do this. 47 | // also note that this uses the == operator so all comparisons are literal. 48 | if ( {a,b,c} == 0 ) Y = 8'b00000001; // use begin/end if need mult statements 49 | else if ( {a,b,c} == 1 ) Y = 8'b00000010; 50 | else if ( {a,b,c} == 2 ) Y = 8'b00000100; 51 | else if ( {a,b,c} == 3 ) Y = 8'b00001000; 52 | else if ( {a,b,c} == 4 ) Y = 8'b00010000; 53 | else if ( {a,b,c} == 5 ) Y = 8'b00100000; 54 | else if ( {a,b,c} == 6 ) Y = 8'b01000000; 55 | else if ( {a,b,c} == 7 ) Y = 8'b10000000; 56 | end 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /always/always2/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always2/README.md: -------------------------------------------------------------------------------- 1 | An always block implementing a decoder with an implied latch. 2 | -------------------------------------------------------------------------------- /always/always2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | reg c; 8 | reg [7:0] Y; 9 | 10 | initial begin 11 | $dumpfile("top_tb.vcd"); 12 | $dumpvars; 13 | end 14 | 15 | initial begin 16 | $monitor("time:%2t addr=%b%b%b Y=%b", $time, a, b, c, Y ); 17 | 18 | {a,b,c} = 0; 19 | #1; 20 | {a,b,c} = 1; 21 | #1; 22 | {a,b,c} = 2; 23 | #1; 24 | {a,b,c} = 3; 25 | #1; 26 | {a,b,c} = 4; 27 | #1; 28 | {a,b,c} = 5; 29 | #1; 30 | {a,b,c} = 6; 31 | #1; 32 | {a,b,c} = 7; 33 | #1; 34 | 35 | $finish; 36 | end 37 | 38 | // When an always block optionally assigns a value to a variable like Y 39 | // below then an implied latch has to exist to retain its value when the 40 | // block is executed but does not assign a new value to Y. Such a 41 | // circuit is legal. But is often not what is intended. 42 | // SystemVerilog has an always_latch that can be used to indicate 43 | // that such a design is by intent. 44 | always @* 45 | begin 46 | if ( {a,b,c} == 0 ) Y = 8'b00000001; 47 | else if ( {a,b,c} == 1 ) Y = 8'b00000010; 48 | else if ( {a,b,c} == 2 ) Y = 8'b00000100; 49 | else if ( {a,b,c} == 3 ) Y = 8'b00001000; 50 | else if ( {a,b,c} == 4 ) Y = 8'b00010000; 51 | else if ( {a,b,c} == 5 ) Y = 8'b00100000; 52 | // else if ( {a,b,c} == 6 ) Y = 8'b01000000; // what if one is missing? 53 | else if ( {a,b,c} == 7 ) Y = 8'b10000000; 54 | end 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /always/always3/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always3/README.md: -------------------------------------------------------------------------------- 1 | An always block implementing a decoder with a mistake & a default value. 2 | 3 | Use a default/else to propagate a value that is less likely to mask an error 4 | than an implied latch! 5 | -------------------------------------------------------------------------------- /always/always3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | reg c; 8 | reg [7:0] Y; 9 | 10 | initial begin 11 | $dumpfile("top_tb.vcd"); 12 | $dumpvars; 13 | end 14 | 15 | initial begin 16 | $monitor("time:%2t addr=%b%b%b Y=%b", $time, a, b, c, Y ); 17 | 18 | {a,b,c} = 0; 19 | #1; 20 | {a,b,c} = 1; 21 | #1; 22 | {a,b,c} = 2; 23 | #1; 24 | {a,b,c} = 3; 25 | #1; 26 | {a,b,c} = 4; 27 | #1; 28 | {a,b,c} = 5; 29 | #1; 30 | {a,b,c} = 6; 31 | #1; 32 | {a,b,c} = 7; 33 | #1; 34 | 35 | $finish; 36 | end 37 | 38 | // In this case, there is no implied latch. If an omission has 39 | // been made, a default value will be assigned. 40 | always @* 41 | begin 42 | if ( {a,b,c} == 0 ) Y = 8'b00000001; 43 | else if ( {a,b,c} == 1 ) Y = 8'b00000010; 44 | else if ( {a,b,c} == 2 ) Y = 8'b00000100; 45 | else if ( {a,b,c} == 3 ) Y = 8'b00001000; 46 | else if ( {a,b,c} == 4 ) Y = 8'b00010000; 47 | else if ( {a,b,c} == 5 ) Y = 8'b00100000; 48 | // else if ( {a,b,c} == 6 ) Y = 8'b01000000; // what if one is missing? 49 | else if ( {a,b,c} == 7 ) Y = 8'b10000000; 50 | else Y = 'bx; 51 | end 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /always/always4/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always4/README.md: -------------------------------------------------------------------------------- 1 | An always block implementing a decoder with unknown input values. 2 | 3 | In simulation, == is a literal comparison. 4 | 5 | More reasons for a default value during simulation. 6 | -------------------------------------------------------------------------------- /always/always4/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | reg c; 8 | reg [7:0] Y; 9 | 10 | initial begin 11 | $dumpfile("top_tb.vcd"); 12 | $dumpvars; 13 | end 14 | 15 | initial begin 16 | $monitor("time:%2t addr=%b%b%b Y=%b", $time, a, b, c, Y ); 17 | 18 | {a,b,c} = 0; 19 | #1; 20 | {a,b,c} = 1; 21 | #1; 22 | {a,b,c} = 2; 23 | #1; 24 | {a,b,c} = 3; 25 | #1; 26 | {a,b,c} = 4; 27 | #1; 28 | {a,b,c} = 5; 29 | #1; 30 | {a,b,c} = 6; 31 | #1; 32 | {a,b,c} = 7; 33 | #1; 34 | 35 | b = 'bx; // what happens if one of the inputs is unknown? 36 | #1; 37 | b = 'b1; // what happens if one of the inputs is unknown? 38 | #1; 39 | {a,b,c} = 0; 40 | #1; 41 | b = 'bx; 42 | #1; 43 | b = 'bz; // what happens if one of the inputs is floating? 44 | #1; 45 | {a,b,c} = 3'b1x1; 46 | #1; 47 | b = 'b0; 48 | #1; 49 | 50 | $finish; 51 | end 52 | 53 | // remember that the == is a literal match 54 | always @* 55 | begin 56 | if ( {a,b,c} == 0 ) Y = 8'b00000001; 57 | else if ( {a,b,c} == 1 ) Y = 8'b00000010; 58 | else if ( {a,b,c} == 2 ) Y = 8'b00000100; 59 | else if ( {a,b,c} == 3 ) Y = 8'b00001000; 60 | else if ( {a,b,c} == 4 ) Y = 8'b00010000; 61 | else if ( {a,b,c} == 5 ) Y = 8'b00100000; 62 | else if ( {a,b,c} == 6 ) Y = 8'b01000000; 63 | else if ( {a,b,c} == 7 ) Y = 8'b10000000; 64 | end 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /always/always5/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always5/README.md: -------------------------------------------------------------------------------- 1 | An always block implementing a decoder with unknown input values. 2 | 3 | In simulation, == is a literal comparison. 4 | 5 | Recall that Verilog was designed for sim and later adapted to FPGAs! 6 | Take care of x and z sim situations by propagating an appropriate value. 7 | 8 | Since z/x can never happen in an actual circuit, the code that handles it 9 | will be optimized away. But in sim, propagating a useful (unknown) value 10 | can help catch design flaws! 11 | -------------------------------------------------------------------------------- /always/always5/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | reg c; 8 | reg [7:0] Y; 9 | 10 | initial begin 11 | $dumpfile("top_tb.vcd"); 12 | $dumpvars; 13 | end 14 | 15 | initial begin 16 | $monitor("time:%2t addr=%b%b%b Y=%b", $time, a, b, c, Y ); 17 | 18 | {a,b,c} = 0; 19 | #1; 20 | {a,b,c} = 1; 21 | #1; 22 | {a,b,c} = 2; 23 | #1; 24 | {a,b,c} = 3; 25 | #1; 26 | {a,b,c} = 4; 27 | #1; 28 | {a,b,c} = 5; 29 | #1; 30 | {a,b,c} = 6; 31 | #1; 32 | {a,b,c} = 7; 33 | #1; 34 | 35 | b = 'bx; 36 | #1; 37 | b = 'b1; 38 | #1; 39 | {a,b,c} = 0; 40 | #1; 41 | b = 'bx; 42 | #1; 43 | b = 'bz; 44 | #1; 45 | b = 'b0; 46 | #1; 47 | 48 | $finish; 49 | end 50 | 51 | always @* 52 | begin 53 | if ( {a,b,c} == 0 ) Y = 8'b00000001; 54 | else if ( {a,b,c} == 1 ) Y = 8'b00000010; 55 | else if ( {a,b,c} == 2 ) Y = 8'b00000100; 56 | else if ( {a,b,c} == 3 ) Y = 8'b00001000; 57 | else if ( {a,b,c} == 4 ) Y = 8'b00010000; 58 | else if ( {a,b,c} == 5 ) Y = 8'b00100000; 59 | else if ( {a,b,c} == 6 ) Y = 8'b01000000; 60 | else if ( {a,b,c} == 7 ) Y = 8'b10000000; 61 | else Y = 8'bx; // will never happen in a synth'd circuit 62 | end 63 | 64 | endmodule 65 | -------------------------------------------------------------------------------- /always/always6/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v led.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /always/always6/README.md: -------------------------------------------------------------------------------- 1 | A 7-segment LED HEX decoder. 2 | -------------------------------------------------------------------------------- /always/always6/led.v: -------------------------------------------------------------------------------- 1 | module led( 2 | input wire enable, // turn off when 0 3 | input wire [3:0] D, // 0-F 4 | output wire a, 5 | output wire b, // these must be wire because driven by cont. assign 6 | output wire c, 7 | output wire d, 8 | output wire e, 9 | output wire f, 10 | output wire g 11 | ); 12 | 13 | reg [6:0] segs; 14 | 15 | assign {a,b,c,d,e,f,g} = segs; 16 | 17 | always @* 18 | begin 19 | if ( enable ) begin 20 | if ( D == 4'h0 ) segs = {7'b1111110}; 21 | else if ( D == 4'h1 ) segs = {7'b0110000}; 22 | else if ( D == 4'h2 ) segs = {7'b1101101}; 23 | else if ( D == 4'h3 ) segs = {7'b1111001}; 24 | else if ( D == 4'h4 ) segs = {7'b0110011}; 25 | else if ( D == 4'h5 ) segs = {7'b1011011}; 26 | else if ( D == 4'h6 ) segs = {7'b1011111}; 27 | else if ( D == 4'h7 ) segs = {7'b1110000}; 28 | else if ( D == 4'h8 ) segs = {7'b1111111}; 29 | else if ( D == 4'h9 ) segs = {7'b1111011}; 30 | else if ( D == 4'ha ) segs = {7'b1110111}; 31 | else if ( D == 4'hb ) segs = {7'b0011111}; 32 | else if ( D == 4'hc ) segs = {7'b1001110}; 33 | else if ( D == 4'hd ) segs = {7'b0111101}; 34 | else if ( D == 4'he ) segs = {7'b1001111}; 35 | else if ( D == 4'hf ) segs = {7'b1000111}; 36 | else segs = 7'bx; // unknown D bit values 37 | end 38 | else 39 | //segs = 0; // or could use 'bz to float the outputs 40 | segs = 'bz; 41 | end 42 | 43 | endmodule 44 | -------------------------------------------------------------------------------- /always/always6/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | reg en; // enable 6 | reg [3:0] D; 7 | wire a,b,c,d,e,f,g; 8 | 9 | integer i; // used by the for loop 10 | 11 | led uut ( 12 | .enable(en), 13 | .D(D), 14 | .a(a), 15 | .b(b), 16 | .c(c), 17 | .d(d), 18 | .e(e), 19 | .f(f), 20 | .g(g) 21 | ); 22 | 23 | initial begin 24 | // recall that unused values will just be printed in order 25 | $monitor("time:%2t en=%b D=%h segs=", $time, en, D, a,b,c,d,e,f,g ); 26 | 27 | $dumpfile("top_tb.vcd"); 28 | $dumpvars; 29 | 30 | en = 1; 31 | 32 | for (i=0; i<='hf; i=i+1) begin 33 | D = i; 34 | #1; // force the sim to propagate all signals before the $display calls 35 | 36 | /* 37 | // creatively print the LED segments 38 | $display( "%s", a ? " *** " : " " ); // a 39 | $display( "%s %s", f ? "*" : " ", b ? "*" : " " ); // f, b 40 | $display( "%s %s", f ? "*" : " ", b ? "*" : " " ); // f, b 41 | $display( "%s", g ? " *** " : " " ); // g 42 | $display( "%s %s", e ? "*" : " ", c ? "*" : " " ); // e, c 43 | $display( "%s %s", e ? "*" : " ", c ? "*" : " " ); // e, c 44 | $display( "%s", d ? " *** " : " " ); // d 45 | */ 46 | end 47 | #1; 48 | 49 | D[2] = 'bx; // generate an unknown input value 50 | #1; 51 | 52 | en = 0; 53 | #1; 54 | 55 | D[2] = 0; // make sure stays disabled even when D is known/valid 56 | #1; 57 | 58 | $finish; 59 | end 60 | 61 | endmodule 62 | -------------------------------------------------------------------------------- /blinky/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | blinky1 \ 5 | blinky2 6 | 7 | include $(TOP)/Make.rules 8 | -------------------------------------------------------------------------------- /blinky/blinky1/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd $(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp: top_tb.v top.v 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | 38 | -------------------------------------------------------------------------------- /blinky/blinky1/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk 52 2 | 3 | set_io led1 118 4 | set_io led2 116 5 | set_io led3 115 6 | set_io led4 114 7 | set_io led5 113 8 | -------------------------------------------------------------------------------- /blinky/blinky1/pinmap-icestick.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 99 2 | set_io led2 98 3 | set_io led3 97 4 | set_io led4 96 5 | set_io led5 95 6 | set_io clk 21 7 | -------------------------------------------------------------------------------- /blinky/blinky1/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io clk 20 2 | 3 | set_io led1 39 # tri-color green 4 | set_io led2 41 # tri-color red 5 | set_io led3 40 # tri-color blue 6 | set_io led4 23 # header pin 7 | set_io led5 25 # header pin 8 | -------------------------------------------------------------------------------- /blinky/blinky1/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2020 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | 23 | /** 24 | * This will blink the four LEDs on the IceStick Evaluation board 25 | * by dividing down the 12MHZ oscillator on the board. 26 | **************************************************************************/ 27 | module top ( 28 | input wire clk, // 12MHZ clock 29 | output wire led1, 30 | output wire led2, 31 | output wire led3, 32 | output wire led4, 33 | output wire led5 34 | ); 35 | 36 | reg [25:0] counter = 0; 37 | 38 | // Drive the LEDs from the MSBs of the counter 39 | 40 | assign led1 = counter[21]; // divide by 4MHZ 41 | assign led2 = counter[22]; // divide by 8MHZ 42 | assign led3 = counter[23]; // divide by 16MHZ 43 | assign led4 = counter[24]; // divide by 32MHZ 44 | assign led5 = counter[25]; // divide by 64MHZ 45 | 46 | // Add 1 to the counter on each rising edge of the clk input signal 47 | always @ (posedge clk) 48 | begin 49 | counter <= counter + 1; 50 | end 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /blinky/blinky1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // the free running clock 6 | 7 | top uut ( 8 | .clk(clk) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("top_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | clk = 0; 16 | end 17 | 18 | always #1 clk = ~clk; 19 | // always @(*) #1 clk = ~clk; // this is NOT the same thing!! 20 | 21 | initial begin 22 | #1000; 23 | //#16000000; 24 | $finish; 25 | end 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /blinky/blinky2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | counter.v 11 | 12 | all:: top.bin 13 | 14 | 15 | #top.blif: $(FILES) 16 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 17 | 18 | top.json: $(FILES) 19 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 20 | 21 | timing: top.asc 22 | icetime -tmd $(DEVICE) $^ 23 | 24 | 25 | counter_tb.vvp: counter_tb.v counter.v 26 | iverilog -o $@ $^ 27 | 28 | plot: counter_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | # extra dependancies 35 | top.asc: $(PINMAP) 36 | 37 | -------------------------------------------------------------------------------- /blinky/blinky2/README.md: -------------------------------------------------------------------------------- 1 | When using the SB_IO, you can create a different module (counter) with the application 2 | logic in it so that a test-bench can be used while a device-specific SB_IO module 3 | (that can not be simulated) can be present in a top module. 4 | 5 | This will be necessary when using the SB_IO for features that can not be specified in a .pcf file. 6 | -------------------------------------------------------------------------------- /blinky/blinky2/counter.v: -------------------------------------------------------------------------------- 1 | module counter ( 2 | input wire clk, 3 | input wire reset, 4 | output wire [7:0] led 5 | ); 6 | 7 | reg [31:0] counter = 32'b0; 8 | 9 | //assign led = ~counter[28:21]; 10 | assign led = counter[27:20]; 11 | //assign led = counter[30:23]; 12 | 13 | always @ (posedge clk) 14 | begin 15 | if (reset) 16 | counter <= 0; 17 | else 18 | counter <= counter + 1; 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /blinky/blinky2/counter_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // the free running clock 6 | 7 | counter uut ( 8 | .clk(clk) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("counter_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | clk = 0; 16 | end 17 | 18 | always #1 clk = ~clk; 19 | 20 | initial begin 21 | #1000; 22 | //#16000000; 23 | $finish; 24 | end 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /blinky/blinky2/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io hwclk 52 2 | 3 | set_io reset_n 102 4 | 5 | set_io led[0] 118 6 | set_io led[1] 116 7 | set_io led[2] 115 8 | set_io led[3] 114 9 | set_io led[4] 113 10 | set_io led[5] 112 11 | set_io led[6] 110 12 | set_io led[7] 107 13 | -------------------------------------------------------------------------------- /blinky/blinky2/pinmap-icestick.pcf: -------------------------------------------------------------------------------- 1 | set_io led[0] 99 2 | set_io led[1] 98 3 | set_io led[2] 97 4 | set_io led[3] 96 5 | set_io led[4] 95 6 | set_io hwclk 21 7 | 8 | # the following are pins on a header 9 | set_io reset_n 44 10 | set_io led[5] 45 11 | set_io led[6] 47 12 | set_io led[7] 48 13 | -------------------------------------------------------------------------------- /blinky/blinky2/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io hwclk 20 2 | 3 | set_io reset_n 28 # header pin 4 | 5 | set_io led[7] 39 # tri-color green 6 | set_io led[6] 41 # tri-color red 7 | set_io led[5] 40 # tri-color blue 8 | set_io led[4] 23 # header pin 9 | set_io led[3] 25 # header pin 10 | set_io led[2] 26 # header pin 11 | set_io led[1] 27 # header pin 12 | set_io led[0] 32 # header pin 13 | 14 | -------------------------------------------------------------------------------- /blinky/blinky2/top.v: -------------------------------------------------------------------------------- 1 | module top ( 2 | input wire hwclk, 3 | input wire reset_n, 4 | output wire [7:0] led 5 | ); 6 | 7 | wire reset_n_pu; 8 | wire reset = ~reset_n_pu; 9 | 10 | SB_IO #( 11 | .PIN_TYPE(6'b0000_01), // output = 0, input = 1 12 | .PULLUP(1'b1) // enable the pullup = 1 13 | ) reset_n_pullup ( 14 | .PACKAGE_PIN(reset_n), // the physical pin number with the pullup on it 15 | .D_IN_0(reset_n_pu) // an internal wire for this pin 16 | ); 17 | 18 | counter c ( 19 | .clk(hwclk), 20 | .reset(reset), 21 | .led(led) 22 | ); 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /case/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | case0 \ 5 | case1 6 | 7 | include $(TOP)/Make.rules 8 | -------------------------------------------------------------------------------- /case/README.md: -------------------------------------------------------------------------------- 1 | # case, casez, and casex 2 | 3 | -------------------------------------------------------------------------------- /case/case0/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v led.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /case/case0/led.v: -------------------------------------------------------------------------------- 1 | module led( 2 | input wire enable, // turn off when 0 3 | input wire [3:0] D, // 0-F 4 | output wire a, 5 | output wire b, // these must be wire because driven by cont. assign 6 | output wire c, 7 | output wire d, 8 | output wire e, 9 | output wire f, 10 | output wire g 11 | ); 12 | 13 | reg [6:0] segs; 14 | 15 | assign {a,b,c,d,e,f,g} = segs; 16 | 17 | always @* 18 | begin 19 | if ( enable ) 20 | case ( D ) 21 | //casez ( D ) 22 | //casex ( D ) 23 | 4'h0: segs = {7'b1111110}; 24 | 4'h1: segs = {7'b0110000}; 25 | 4'h2: segs = {7'b1101101}; 26 | 4'h3: segs = {7'b1111001}; 27 | 4'h4: segs = {7'b0110011}; 28 | 4'h5: segs = {7'b1011011}; 29 | 4'h6: segs = {7'b1011111}; 30 | 4'h7: segs = {7'b1110000}; 31 | 4'h8: segs = {7'b1111111}; 32 | 4'h9: segs = {7'b1111011}; 33 | 4'ha: segs = {7'b1110111}; 34 | 4'hb: segs = {7'b0011111}; 35 | 4'hc: segs = {7'b1001110}; 36 | 4'hd: segs = {7'b0111101}; 37 | 4'he: segs = {7'b1001111}; 38 | 4'hf: segs = {7'b1000111}; 39 | 40 | 4'bxxxx: segs = {7'bx0x0x0x}; // will case match x values in simulation? 41 | 42 | 4'b????: segs = {7'bz0z0z0z}; // will case match z values in simulation? 43 | //4'bzzzz: segs = {7'b0z0z0z0z}; // will case match z values in simulation? 44 | 45 | default: segs = 7'bx; // unknown or floating D bit values 46 | 47 | endcase 48 | else 49 | //segs = 0; // or could use 'bz to float the outputs 50 | segs = 'bz; 51 | end 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /case/case1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v bassackward.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /case/case1/README.md: -------------------------------------------------------------------------------- 1 | # An example of a one-hot case 2 | -------------------------------------------------------------------------------- /case/case1/bassackward.v: -------------------------------------------------------------------------------- 1 | module bassackward( 2 | output reg [1:0] Q, // 0-3 3 | input wire a, 4 | input wire b, 5 | input wire c, 6 | input wire d 7 | ); 8 | 9 | always @* 10 | begin 11 | case ( 1'b1 ) // this is a constant! 12 | a: Q = 2'b00; // a is a variable! 13 | b: Q = 2'b01; 14 | c: Q = 2'b10; 15 | d: Q = 2'b11; 16 | default: Q = 2'bxx; 17 | endcase 18 | end 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /case/case1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns // time units & precision are both 1nsec 2 | 3 | module tb(); 4 | 5 | wire [1:0] out; 6 | reg aa,bb,cc,dd; 7 | 8 | bassackward uut ( 9 | .Q(out), 10 | .a(aa), 11 | .b(bb), 12 | .c(cc), 13 | .d(dd) 14 | ); 15 | 16 | initial begin 17 | $monitor("time:%2t %b%b%b%b out=%b", $time, aa,bb,cc,dd,out ); 18 | 19 | $dumpfile("top_tb.vcd"); 20 | $dumpvars; 21 | 22 | {aa,bb,cc,dd} = 4'b1000; 23 | #1; 24 | {aa,bb,cc,dd} = 4'b0100; 25 | #1; 26 | {aa,bb,cc,dd} = 4'b0010; 27 | #1; 28 | {aa,bb,cc,dd} = 4'b0001; 29 | #1; 30 | 31 | {aa,bb,cc,dd} = 4'b0000; // (no bits set) illegal value 32 | #1; 33 | {aa,bb,cc,dd} = 4'b1010; // (more than 1 bit set) illegal value 34 | #1; 35 | {aa,bb,cc,dd} = 4'bxxxx; // just not right 36 | #1; 37 | {aa,bb,cc,dd} = 4'bzzzz; // badness 38 | #1; 39 | 40 | {aa,bb,cc,dd} = 4'bxx1x; // what happens if we do this? 41 | #1; 42 | {aa,bb,cc,dd} = 4'b?1??; // what happens if we do this? 43 | #1; 44 | 45 | $finish; 46 | end 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /equality/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /equality/README.md: -------------------------------------------------------------------------------- 1 | 2 | Recall that: 3 | 4 | 0 = false/low/ground 5 | 1 = true/high/positive-voltage 6 | x = an unknown value. (This can only happen in siumulation.) 7 | z = floating/high-impedance. (This is synthesizable as an output value.) 8 | 9 | 10 | The Verilog spec says: 11 | 12 | a === b a is equal to b including x and z 13 | a !== b a is not equal to b, including x and z 14 | a == b a is equal to b, result can be unknown 15 | a != b a is not equal to b, result can be unknown 16 | 17 | 18 | Note that x is always considered false. 19 | 20 | if ( 'bx ) 21 | // never gets here 22 | else 23 | // always gets here 24 | -------------------------------------------------------------------------------- /fsm/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | fsm0 \ 5 | fsm1 \ 6 | fsm2 \ 7 | fsm3 \ 8 | fsm4 9 | 10 | include $(TOP)/Make.rules 11 | -------------------------------------------------------------------------------- /fsm/README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Verilog Finite State Machines 2 | 3 | - fsm0: A Moore FSM built using one always block. 4 | - fsm1: A Moore FSM built using two always blocks. 5 | - fsm2: A Moore 2-bit synch counter counter with enable and synch reset. 6 | - fsm3: A Moore serial bit-stream recognizer with synch reset. 7 | - fsm4: A Mealy serial bit-stream recognizer with synch reset. 8 | 9 | Some of these examples are based on course notes and handouts that can 10 | be found here: 11 | 12 | https://faculty.cs.niu.edu/~winans/CS463/2022-fa/#fsm 13 | -------------------------------------------------------------------------------- /fsm/fsm0/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v fsm.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /fsm/fsm0/README.md: -------------------------------------------------------------------------------- 1 | # A Simple Finite State Machine 2 | 3 | This Moore FSM uses a single always block to: 4 | - Calculate the next state of the system. 5 | - Update the current system state on every system clock rising edge. 6 | -------------------------------------------------------------------------------- /fsm/fsm0/fsm.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | module fsm #( 23 | parameter WIDTH = 16 // how many bits in the counter regsister 24 | ) 25 | ( 26 | input wire clk, // the system clock 27 | input wire reset, // synchronous reset to zero the counter 28 | output reg [WIDTH-1:0] D // the current value of the counter 29 | ); 30 | 31 | // The current state of this FSM is the value of the counter 32 | 33 | always @(posedge clk) begin 34 | if (reset) 35 | D <= 0; // reset the FSM 36 | else 37 | D <= D + 1; // calculate the next state & assign 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /fsm/fsm0/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | localparam COUNTER_WIDTH = 4; 6 | localparam COUNTER_MAX = $pow( 2, COUNTER_WIDTH ); 7 | 8 | reg clk = 1; // what happens to setup & hold if we start high? 9 | reg reset = 0; // system is not reset by default 10 | 11 | wire [COUNTER_WIDTH-1:0] count; 12 | 13 | fsm #( .WIDTH(COUNTER_WIDTH) ) uut ( .clk(clk), .reset(reset), .D(count) ); 14 | 15 | always #1 clk = ~clk; // free-running clock to run the FSM 16 | 17 | initial begin 18 | // NOTE: $monitor will not trigger on things changed in other modules 19 | $monitor("time:%2t reset=%b count=%h", $time, reset, count ); 20 | $display("COUNTER_WIDTH:%3d COUNTER_MAX:%3d", COUNTER_WIDTH, COUNTER_MAX ); 21 | 22 | $dumpfile("top_tb.vcd"); 23 | $dumpvars; 24 | 25 | //#0.2 // be careful with this if precision is same as time units! 26 | #10; // just to make the reset seem interesting 27 | reset = 1; 28 | #4; // two simulation time units = one clock period 29 | reset = 0; 30 | 31 | #(COUNTER_MAX*2+6); // wait long enough for count to wrap around 32 | 33 | reset = 1; 34 | #2; 35 | reset = 0; 36 | 37 | #20; // count some more before we end the simulation 38 | 39 | $finish; 40 | end 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /fsm/fsm1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v fsm.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /fsm/fsm1/README.md: -------------------------------------------------------------------------------- 1 | # A Simple Finite State Machine 2 | 3 | This Moore FSM uses two always blocks: 4 | - One combinational block will calculate the next state of the system. 5 | - One flipflop will update the current system state on the system clock rising edge. 6 | -------------------------------------------------------------------------------- /fsm/fsm1/fsm.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | module fsm #( 23 | parameter WIDTH = 16 // how many bits in the counter regsister 24 | ) 25 | ( 26 | input wire clk, // the system clock 27 | input wire reset, // synchronous reset to zero the counter 28 | output reg [WIDTH-1:0] D // the current value of the counter 29 | ); 30 | 31 | // The current state of this FSM is the value of the counter 32 | reg [WIDTH-1:0] D_next; 33 | 34 | always @(posedge clk) begin 35 | if (reset) 36 | D <= 0; // reset the FSM 37 | else 38 | D <= D_next; 39 | end 40 | 41 | // A pure combo always block used to calculate the next 42 | // state from the current state. 43 | always @(*) begin 44 | D_next = D + 1; 45 | end 46 | 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /fsm/fsm1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | localparam COUNTER_WIDTH = 4; 6 | localparam COUNTER_MAX = $pow( 2, COUNTER_WIDTH ); 7 | 8 | reg clk = 0; // what happens to setup & hold if we start high? 9 | reg reset = 0; // system is not reset by default 10 | 11 | wire [COUNTER_WIDTH-1:0] count; 12 | 13 | fsm #( .WIDTH(COUNTER_WIDTH) ) uut ( .clk(clk), .reset(reset), .D(count) ); 14 | 15 | always #1 clk = ~clk; // free-running clock to run the FSM 16 | 17 | initial begin 18 | // NOTE: $monitor will not trigger on things changed in other modules 19 | $monitor("time:%2t reset=%b count=%h", $time, reset, count ); 20 | $display("COUNTER_WIDTH:%d COUNTER_MAX:%d", COUNTER_WIDTH, COUNTER_MAX ); 21 | 22 | $dumpfile("top_tb.vcd"); 23 | $dumpvars; 24 | 25 | //#0.1; // be careful with this if precision is same as time units! 26 | #10; // just to make the reset seem interesting 27 | reset = 1; 28 | #4; // two simulation time units = one clock period 29 | reset = 0; 30 | 31 | #(COUNTER_MAX*2+6); // wait long enough for count to wrap around 32 | 33 | reset = 1; 34 | #2; 35 | reset = 0; 36 | 37 | #20; // count some more before we end the simulation 38 | 39 | $finish; 40 | end 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /fsm/fsm2/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v fsm.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /fsm/fsm2/README.md: -------------------------------------------------------------------------------- 1 | # A Simple Finite State Machine 2 | 3 | This Moore FSM uses two always blocks: 4 | - One combinational block will calculate the next state of the system. 5 | - One flipflop will update the current system state on the system clock rising edge. 6 | -------------------------------------------------------------------------------- /fsm/fsm2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | reg clk = 0; 6 | reg reset = 0; 7 | reg enable = 0; 8 | 9 | wire [1:0] state; 10 | 11 | fsm uut ( .clk(clk), .reset(reset), .E(enable), .S(state) ); 12 | 13 | always #1 clk = ~clk; // free-running clock to run the FSM 14 | 15 | initial begin 16 | // NOTE: $monitor will not trigger on things changed in other modules 17 | $monitor("time:%2t reset:%b eanble:%b state:%b", $time, reset, enable, state ); 18 | 19 | $dumpfile("top_tb.vcd"); 20 | $dumpvars; 21 | 22 | #4; // just to make the reset seem interesting 23 | reset = 1; 24 | #4; // two simulation time units = one clock period 25 | reset = 0; 26 | 27 | #4; 28 | enable = 1; // enable the counter 29 | #12; 30 | enable = 0; // disable the counter 31 | #6; 32 | 33 | reset = 1; 34 | #2; 35 | enable = 1; 36 | #4; 37 | reset = 0; 38 | 39 | #12; 40 | 41 | $finish; 42 | end 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /fsm/fsm3/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v fsm.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | 22 | 23 | # add a second test bench 24 | top2_tb.vvp : top2_tb.v fsm.v 25 | iverilog -o $@ $^ 26 | run2: top2_tb.vvp 27 | vvp top2_tb.vvp 28 | plot2: top2_tb.vcd 29 | gtkwave $^ 30 | 31 | -------------------------------------------------------------------------------- /fsm/fsm3/README.md: -------------------------------------------------------------------------------- 1 | # A Simple Finite State Machine 2 | 3 | This is a serial bit-stream recognizer with synchronous reset. 4 | 5 | This Moore FSM is based on a course lecture and handout available on line here: 6 | 7 | https://faculty.cs.niu.edu/~winans/CS463/2022-fa/#fsm 8 | 9 | 10 | This example adds a second test that matches the Mealy glitchy waveform 11 | in the course handout. It demonstrates that a Moore machine's output 12 | will not glitch like a Mealy one can... even with the same input waveforms! 13 | -------------------------------------------------------------------------------- /fsm/fsm3/top2_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | reg clk = 1; // start hi to match course handout 6 | reg reset = 0; 7 | reg D = 0; 8 | wire Q; 9 | 10 | fsm uut ( .clk(clk), .reset(reset), .D(D), .Q(Q) ); 11 | 12 | always #1 clk = ~clk; // free-running clock to run the FSM 13 | 14 | initial begin 15 | $dumpfile("top2_tb.vcd"); 16 | $dumpvars; 17 | 18 | #2; 19 | reset = 1; 20 | #4; 21 | reset = 0; 22 | 23 | // match the example waveform in Figure 10 of the course handout 24 | D = 0; 25 | #2; 26 | D = 1; 27 | #2; 28 | D = 0; 29 | 30 | // glitches 31 | #1.1; 32 | D = 1; 33 | #0.1; 34 | D = 0; 35 | #0.1; 36 | D = 1; 37 | #0.1; 38 | D = 0; 39 | #0.6; 40 | #2; 41 | 42 | D = 1; 43 | #2; 44 | D = 0; 45 | #2; 46 | D = 1; 47 | 48 | // glitches 49 | #1.1; 50 | D = 0; 51 | #0.1; 52 | D = 1; 53 | #0.1; 54 | D = 0; 55 | #0.1; 56 | D = 1; 57 | #0.6; 58 | #2; 59 | 60 | D = 0; 61 | #2; 62 | D = 1; 63 | #8; 64 | D = 0; 65 | #3; 66 | 67 | $finish; 68 | end 69 | 70 | endmodule 71 | -------------------------------------------------------------------------------- /fsm/fsm3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | reg clk = 1; // start hi to match course handout 6 | reg reset = 0; 7 | reg D = 0; 8 | wire Q; 9 | 10 | fsm uut ( .clk(clk), .reset(reset), .D(D), .Q(Q) ); 11 | 12 | always #1 clk = ~clk; // free-running clock to run the FSM 13 | 14 | initial begin 15 | $dumpfile("top_tb.vcd"); 16 | $dumpvars; 17 | 18 | #2; 19 | reset = 1; 20 | #4; 21 | reset = 0; 22 | 23 | // match the example waveform in Figure 5 of the course handout 24 | D = 0; 25 | #2; 26 | D = 1; 27 | #2; 28 | D = 0; 29 | #4; 30 | D = 1; 31 | #2; 32 | D = 0; 33 | #2; 34 | D = 1; 35 | #4; 36 | D = 0; 37 | #2; 38 | D = 1; 39 | #8; 40 | D = 0; 41 | #3; 42 | 43 | $finish; 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /fsm/fsm4/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run run2 11 | 12 | top_tb.vvp : top_tb.v fsm.v 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | 22 | # add a second test bench 23 | top2_tb.vvp : top2_tb.v fsm.v 24 | iverilog -o $@ $^ 25 | run2: top2_tb.vvp 26 | vvp top2_tb.vvp 27 | plot2: top2_tb.vcd 28 | gtkwave $^ 29 | -------------------------------------------------------------------------------- /fsm/fsm4/README.md: -------------------------------------------------------------------------------- 1 | # A Simple Finite State Machine 2 | 3 | This is a serial bit-stream recognizer with synchronous reset. 4 | 5 | This Mealy FSM is based on a course lecture and handout available on line here: 6 | 7 | https://faculty.cs.niu.edu/~winans/CS463/2022-fa/#fsm 8 | -------------------------------------------------------------------------------- /fsm/fsm4/top2_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | reg clk = 1; // start hi to match course handout 6 | reg reset = 0; 7 | reg D = 0; 8 | wire Q; 9 | 10 | fsm uut ( .clk(clk), .reset(reset), .D(D), .Q(Q) ); 11 | 12 | always #1 clk = ~clk; // free-running clock to run the FSM 13 | 14 | initial begin 15 | $dumpfile("top2_tb.vcd"); 16 | $dumpvars; 17 | 18 | #2; 19 | reset = 1; 20 | #4; 21 | reset = 0; 22 | 23 | // match the example waveform in the course handout 24 | D = 0; 25 | #2; 26 | D = 1; 27 | #2; 28 | D = 0; 29 | 30 | // glitches 31 | #1.1; 32 | D = 1; 33 | #0.1; 34 | D = 0; 35 | #0.1; 36 | D = 1; 37 | #0.1; 38 | D = 0; 39 | #0.6; 40 | #2; 41 | 42 | D = 1; 43 | #2; 44 | D = 0; 45 | #2; 46 | D = 1; 47 | 48 | // glitches 49 | #1.1; 50 | D = 0; 51 | #0.1; 52 | D = 1; 53 | #0.1; 54 | D = 0; 55 | #0.1; 56 | D = 1; 57 | #0.6; 58 | #2; 59 | 60 | D = 0; 61 | #2; 62 | D = 1; 63 | #8; 64 | D = 0; 65 | #3; 66 | 67 | $finish; 68 | end 69 | 70 | endmodule 71 | -------------------------------------------------------------------------------- /fsm/fsm4/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps // time units & precision 2 | 3 | module tb(); 4 | 5 | reg clk = 1; // start hi to match course handout 6 | reg reset = 0; 7 | reg D = 0; 8 | wire Q; 9 | 10 | fsm uut ( .clk(clk), .reset(reset), .D(D), .Q(Q) ); 11 | 12 | always #1 clk = ~clk; // free-running clock to run the FSM 13 | 14 | initial begin 15 | $dumpfile("top_tb.vcd"); 16 | $dumpvars; 17 | 18 | #2; 19 | reset = 1; 20 | #4; 21 | reset = 0; 22 | 23 | // match the example waveform in the course handout 24 | D = 0; 25 | #2; 26 | D = 1; 27 | #2; 28 | D = 0; 29 | #4; 30 | D = 1; 31 | #2; 32 | D = 0; 33 | #2; 34 | D = 1; 35 | #4; 36 | D = 0; 37 | #2; 38 | D = 1; 39 | #8; 40 | D = 0; 41 | #3; 42 | 43 | $finish; 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /halfadder/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | halfadder1 \ 5 | halfadder2 \ 6 | halfadder3 \ 7 | halfadder4 \ 8 | halfadder5 \ 9 | halfadder6 \ 10 | halfadder7 \ 11 | halfadder8 12 | 13 | include $(TOP)/Make.rules 14 | -------------------------------------------------------------------------------- /halfadder/halfadder1/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /halfadder/halfadder1/README.md: -------------------------------------------------------------------------------- 1 | Note that since the .pcf file is not used by test-benches. 2 | Therefore it can not interfere with our ability to compile and run a simulation of it. 3 | -------------------------------------------------------------------------------- /halfadder/halfadder1/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder1/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder1/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2023 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder1/top_tb.v: -------------------------------------------------------------------------------- 1 | // 1ns = the time represented by #1 2 | // 1ps is the resolution of the times stored in the simulation VCD (Value Change Dump) file 3 | `timescale 1ns/1ps 4 | 5 | // Create a module named 'tb' that has no ports 6 | module tb(); 7 | 8 | reg a; // Signals driven from within a process (an initial or always block) must be type reg 9 | reg b; 10 | wire sum; // Signals that are driven from outside a process must be type wire 11 | wire cy; 12 | 13 | // Instantiate (create one instance of) a top module and call it 'uut' within this module 14 | // We have the opportuinity here to connect the ports of the module to our local signals. 15 | top uut ( 16 | .a(a), // connect our 'reg a' to top's input port a 17 | .b(b), // connect our 'reg b' to top's input port b 18 | .sum(sum), // connect top's output port 'sum' to our 'wire sum' 19 | .cy(cy) // connect top's output port 'cy' to our 'wire cy' 20 | ); 21 | 22 | // 'initial' is a 'process' that will run once when the simulation starts 23 | // $xyz is the notation used to refer to a 'system task' 24 | initial begin 25 | $dumpfile("top_tb.vcd"); // where to write the dump 26 | $dumpvars; // dump EVERYTHING 27 | end 28 | 29 | // all initial process blocks will start at the same time and run in parallel 30 | initial begin 31 | a = 0; // = is a 'blocking assignment' that runs in the order given during simulation 32 | b = 0; 33 | #1; // #nnn is a statement that will wait nnn units of time given in the `timescale 34 | a = 0; 35 | b = 1; 36 | #1; 37 | a = 1; 38 | b = 0; 39 | #1; 40 | a = 1; 41 | b = 1; 42 | #1; 43 | a = 0; 44 | b = 0; 45 | #10; 46 | 47 | $finish; // The $finish 'system task' halts the simulation 48 | end 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /halfadder/halfadder2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /halfadder/halfadder2/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate a half adder that has its inputs and outputs inverted so 2 | as to match the situation on the 2057 board. 3 | -------------------------------------------------------------------------------- /halfadder/halfadder2/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder2/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder2/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = ~( ~a ^ ~b ); 39 | assign cy = ~( ~a & ~b ); 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | a = 0; 24 | b = 0; 25 | #1; 26 | a = 0; 27 | b = 1; 28 | #1; 29 | a = 1; 30 | b = 0; 31 | #1; 32 | a = 1; 33 | b = 1; 34 | #1; 35 | a = 0; 36 | b = 0; 37 | #10; 38 | 39 | $finish; 40 | end 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /halfadder/halfadder3/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder3/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate the $display and $time system tasks. 2 | 3 | Note that the $display() task runs in the same time-slice as other 4 | operations. But it may run before or after those other operations! 5 | -------------------------------------------------------------------------------- /halfadder/halfadder3/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder3/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder3/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | // brute force hardcoded 24 | a = 0; 25 | b = 0; 26 | $display("%0t sum=%b, cy=%b", $time, sum, cy); // 0t removes a ton of padding 27 | #1; 28 | 29 | a = 0; 30 | b = 1; 31 | $display("%0t sum=%b, cy=%b", $time, sum, cy); 32 | #1; 33 | 34 | a = 1; 35 | b = 0; 36 | $display("%0t sum=%b, cy=%b", $time, sum, cy); 37 | #1; 38 | 39 | a = 1; 40 | b = 1; 41 | $display("%0t sum=%b, cy=%b", $time, sum, cy); 42 | #1; 43 | 44 | a = 0; 45 | b = 0; 46 | $display("%0t sum=%b, cy=%b", $time, sum, cy); 47 | #10; 48 | 49 | $finish; 50 | end 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /halfadder/halfadder4/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder4/README.md: -------------------------------------------------------------------------------- 1 | Replace $display() with $strobe() so that it runs after everything in the 2 | current time step has completed. 3 | -------------------------------------------------------------------------------- /halfadder/halfadder4/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder4/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder4/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder4/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | // brute force hardcoded 24 | a = 0; 25 | b = 0; 26 | $strobe("%0t sum=%b, cy=%b", $time, sum, cy); 27 | #1; 28 | 29 | a = 0; 30 | b = 1; 31 | $strobe("%0t sum=%b, cy=%b", $time, sum, cy); 32 | #1; 33 | 34 | a = 1; 35 | b = 0; 36 | $strobe("%0t sum=%b, cy=%b", $time, sum, cy); 37 | #1; 38 | 39 | a = 1; 40 | b = 1; 41 | $strobe("%0t sum=%b, cy=%b", $time, sum, cy); 42 | #1; 43 | 44 | a = 0; 45 | b = 0; 46 | $strobe("%0t sum=%b, cy=%b", $time, sum, cy); 47 | #10; 48 | 49 | $finish; 50 | end 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /halfadder/halfadder5/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder5/README.md: -------------------------------------------------------------------------------- 1 | Another way to get a $display to run at the end of the current time period. 2 | Add a `#0` delay before the $display system tasks. 3 | 4 | The `#0` statement will wait for all operations already started in the 5 | same time period to complete before simulation will continue. Taken 6 | literally, this means that *other operations* might also have initiated 7 | a `#0` delay in the same time period! Therefore this does not always 8 | mean that *everything* will finish before the $display() is performed. 9 | 10 | However, it will work for our purposes because we have not scheduled anything 11 | else (other that our simple test bench operations) to run. 12 | -------------------------------------------------------------------------------- /halfadder/halfadder5/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder5/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder5/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder5/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | // brute force hardcoded 24 | a = 0; 25 | b = 0; 26 | #0; 27 | $display("%0t sum=%b, cy=%b", $time, sum, cy); // 0t removes a ton of padding 28 | #1; 29 | 30 | a = 0; 31 | b = 1; 32 | #0 $display("%0t sum=%b, cy=%b", $time, sum, cy); // can also combine the #0 with what follows 33 | #1; 34 | 35 | a = 1; 36 | b = 0; 37 | #0 $display("%0t sum=%b, cy=%b", $time, sum, cy); 38 | #1; 39 | 40 | a = 1; 41 | b = 1; 42 | #0 $display("%0t sum=%b, cy=%b", $time, sum, cy); 43 | #1; 44 | 45 | a = 0; 46 | b = 0; 47 | #0 $display("%0t sum=%b, cy=%b", $time, sum, cy); 48 | #10; 49 | 50 | $finish; 51 | end 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /halfadder/halfadder6/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder6/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate the $monitor as an alternative to $display. 2 | -------------------------------------------------------------------------------- /halfadder/halfadder6/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder6/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder6/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder6/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | // Only one $monitor task allowed, so we can NOT do this: 24 | //$monitor("time:%0t sum = %0d", $time, sum); 25 | //$monitor("time:%0t cy = %0d", $time, cy); 26 | 27 | // ... therefore do this: 28 | $monitor("time:%0t a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 29 | 30 | // $monitor will report changes in all the signals that are listed as 31 | // parameters (except for $time since it always changes) 32 | 33 | a = 0; 34 | b = 0; 35 | #1 36 | 37 | a = 0; 38 | b = 1; 39 | #1 40 | 41 | a = 1; 42 | b = 0; 43 | #1 44 | 45 | a = 1; 46 | b = 1; 47 | #1 48 | 49 | a = 0; 50 | b = 0; 51 | #1 52 | 53 | $finish; 54 | end 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /halfadder/halfadder7/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder7/README.md: -------------------------------------------------------------------------------- 1 | Add 'if' expressions to check expected outputs so that we need not do it manually. 2 | -------------------------------------------------------------------------------- /halfadder/halfadder7/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder7/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder7/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder7/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | initial begin 23 | $monitor("time:%0t a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 24 | 25 | a = 0; 26 | b = 0; 27 | // same game as we saw eariler with #0 $display() 28 | #0 if ( !( sum==0 && cy==0 ) ) begin $display("%s:%0d time:%0t FAILED a=%b, b=%b, sum=%b, cy=%b", `__FILE__, `__LINE__, $time, a, b, sum, cy); $finish; end 29 | #1 30 | 31 | a = 0; 32 | b = 1; 33 | #0 if ( !( sum==1 && cy==0 ) ) begin $display("%s:%0d time:%0t FAILED a=%b, b=%b, sum=%b, cy=%b", `__FILE__, `__LINE__, $time, a, b, sum, cy); $finish; end 34 | #1 35 | 36 | a = 1; 37 | b = 0; 38 | #0 if ( !( sum==1 && cy==0 ) ) begin $display("%s:%0d time:%0t FAILED a=%b, b=%b, sum=%b, cy=%b", `__FILE__, `__LINE__, $time, a, b, sum, cy); $finish; end 39 | #1 40 | 41 | a = 1; 42 | b = 1; 43 | #0 if ( !( sum==0 && cy==1 ) ) begin $display("%s:%0d time:%0t FAILED a=%b, b=%b, sum=%b, cy=%b", `__FILE__, `__LINE__, $time, a, b, sum, cy); $finish; end 44 | #1 45 | 46 | a = 0; 47 | b = 0; 48 | #0 if ( !( sum==0 && cy==0 ) ) begin $display("%s:%0d time:%0t FAILED a=%b, b=%b, sum=%b, cy=%b", `__FILE__, `__LINE__, $time, a, b, sum, cy); $finish; end 49 | #1 50 | 51 | $finish; 52 | end 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /halfadder/halfadder8/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | # a rule to force a simulation but don't bother opening gtkwave 29 | run: top_tb.vvp 30 | vvp top_tb.vvp 31 | 32 | plot: top_tb.vcd 33 | gtkwave $^ 34 | 35 | prog: top.bin 36 | $(FLASH_PROG) $^ 37 | 38 | 39 | # extra dependancies 40 | top.asc: $(PINMAP) 41 | -------------------------------------------------------------------------------- /halfadder/halfadder8/README.md: -------------------------------------------------------------------------------- 1 | Create an ASSERT macro to simplify automatic verification in a test bench. 2 | 3 | Also use a #0.5 delay to ensure the assertion occurs after a time period is completed. 4 | -------------------------------------------------------------------------------- /halfadder/halfadder8/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io -pullup yes a 102 4 | set_io -pullup yes b 105 5 | set_io sum 118 6 | set_io cy 116 7 | -------------------------------------------------------------------------------- /halfadder/halfadder8/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io sum 28 2 | set_io cy 38 3 | 4 | set_io -pullup yes a 2 5 | set_io -pullup yes b 46 6 | -------------------------------------------------------------------------------- /halfadder/halfadder8/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will calculate the sum of a and b. 26 | * 27 | * @warning Keep in mind that the buttons and LEDs on the 2057 (and 28 | * other boards) are low when pressed and high when released and the LEDs 29 | * are lit when the output signal from the FPGA low! 30 | **************************************************************************/ 31 | module top ( 32 | input wire a, 33 | input wire b, 34 | output wire sum, 35 | output wire cy 36 | ); 37 | 38 | assign sum = a ^ b; 39 | assign cy = a & b; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /halfadder/halfadder8/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg a; 6 | reg b; 7 | wire sum; 8 | wire cy; 9 | 10 | top uut ( 11 | .a(a), 12 | .b(b), 13 | .sum(sum), 14 | .cy(cy) 15 | ); 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); // where to write the dump 19 | $dumpvars; // dump EVERYTHING 20 | end 21 | 22 | 23 | // This can not be used any 'ol place in verilog. But is good enough for initial and always blocks. 24 | // NOTE: SystemVerilog provides an assert() so we need not provide our own. 25 | // 26 | // The \ at the end of a line means continuation, just like C/C++ Therefore this macro turns into 27 | // four lines of text that is then compiled. 28 | 29 | `define ASSERT(cond) \ 30 | if (!(cond)) begin \ 31 | $display("%s:%0d time:%0t ASSERTION FAILED in %m: cond", `__FILE__, `__LINE__, $time); \ 32 | $finish; \ 33 | end 34 | 35 | 36 | initial begin 37 | $monitor("time:%0t a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 38 | 39 | a = 0; 40 | b = 0; 41 | #0.5 `ASSERT( sum==0 && cy==0 ); 42 | #0.5; 43 | 44 | a = 0; 45 | b = 1; 46 | #0.5 `ASSERT( sum==1 && cy==0 ); 47 | #0.5; 48 | 49 | a = 1; 50 | b = 0; 51 | #0.5 `ASSERT( sum==1 && cy==0 ); 52 | #0.5; 53 | 54 | a = 1; 55 | b = 1; 56 | #0.5`ASSERT( sum==0 && cy==1 ); 57 | #0.5; 58 | 59 | a = 0; 60 | b = 0; 61 | #0.5 `ASSERT( sum==0 && cy==0 ); 62 | #0.5; 63 | 64 | $finish; 65 | end 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /lib/debounce/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean world 7 | 8 | FILES= \ 9 | debounce.v \ 10 | ../sync/sync.v 11 | 12 | all:: 13 | 14 | debounce_tb.vvp: debounce_tb.v $(FILES) 15 | iverilog -o $@ $^ 16 | 17 | plot: debounce_tb.vcd 18 | gtkwave $^ 19 | -------------------------------------------------------------------------------- /lib/debounce/debounce.v: -------------------------------------------------------------------------------- 1 | // Seen on the Internet 2024-10-12 2 | // https://electronics.stackexchange.com/questions/505911/debounce-circuit-design-in-verilog 3 | 4 | module debounce 5 | #( 6 | parameter MAX_COUNT = 16 7 | ) 8 | ( 9 | input wire clock, 10 | input wire in, // Synchronous and noisy input. 11 | output reg out, // Debounced and filtered output. 12 | output reg edj, // Goes high for 1 clock cycle on either edge of output. Note: used "edj" because "edge" is a keyword. 13 | output reg rise, // Goes high for 1 clock cycle on the rising edge of output. 14 | output reg fall // Goes high for 1 clock cycle on the falling edge of output. 15 | ); 16 | 17 | localparam COUNTER_BITS = $clog2(MAX_COUNT); 18 | 19 | reg [COUNTER_BITS - 1 : 0] counter; 20 | wire w_edj; 21 | wire w_rise; 22 | wire w_fall; 23 | 24 | initial 25 | begin 26 | counter = 0; 27 | out = 0; 28 | end 29 | 30 | always @(posedge clock) 31 | begin 32 | counter <= 0; // Freeze counter by default to reduce switching losses when input and output are equal. 33 | edj <= 0; 34 | rise <= 0; 35 | fall <= 0; 36 | if (counter == MAX_COUNT - 1) // If successfully debounced, notify what happened. 37 | begin 38 | out <= in; 39 | edj <= w_edj; // Goes high for 1 clock cycle on either edge. 40 | rise <= w_rise; // Goes high for 1 clock cycle on the rising edge. 41 | fall <= w_fall; // Goes high for 1 clock cycle on the falling edge. 42 | end 43 | else if (in != out) // Hysteresis. 44 | begin 45 | counter <= counter + 1; // Only increment when input and output differ. 46 | end 47 | end 48 | 49 | // Edge detect. 50 | assign w_edj = in ^ out; 51 | assign w_rise = in & ~out; 52 | assign w_fall = ~in & out; 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /lib/debounce/debounce_tb.v: -------------------------------------------------------------------------------- 1 | // As seen on the Internet 2024-10-12 2 | // https://electronics.stackexchange.com/questions/505911/debounce-circuit-design-in-verilog 3 | // mods by John Winans 4 | 5 | `timescale 1ns/1ps 6 | 7 | module tb; 8 | 9 | reg clock; 10 | reg button; 11 | wire button_sync; 12 | wire button_sync_db; 13 | wire edj; 14 | wire rise; 15 | wire fall; 16 | 17 | sync 18 | #( 19 | .SYNC_LEN(3) 20 | ) 21 | Sync_Inst 22 | ( 23 | .clk(clock), 24 | .in(button), 25 | .out(button_sync) 26 | ); 27 | 28 | debounce 29 | #( 30 | .MAX_COUNT(25000) 31 | ) 32 | Debounce_Inst 33 | ( 34 | .clock(clock), 35 | .in(button_sync), 36 | .out(button_sync_db), 37 | .edj(edj), 38 | .rise(rise), 39 | .fall(fall) 40 | ); 41 | 42 | initial 43 | begin 44 | $dumpfile("debounce_tb.vcd"); 45 | $dumpvars(0,tb); // dump all vars in entire module tree 46 | clock = 0; 47 | end 48 | 49 | always #5 clock = ~clock; 50 | 51 | always 52 | begin 53 | #2 button = 0; #20 button = 1; #20 button = 0; 54 | #22 button = 1; #20 button = 1; #20 button = 0; #20 button = 1; 55 | #22 button = 1; #20 button = 0; #20 button = 0; #20 button = 1; 56 | #22 button = 0; #20 button = 1; #20 button = 1; #20 button = 0; 57 | #80 $finish; 58 | end 59 | 60 | endmodule 61 | 62 | -------------------------------------------------------------------------------- /lib/stretcher/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean world 7 | 8 | FILES= \ 9 | sync_stretch.v 10 | 11 | all:: 12 | 13 | sync_stretch_tb.vvp: sync_stretch_tb.v sync_stretch.v 14 | iverilog -o $@ $^ 15 | 16 | plot: sync_stretch_tb.vcd 17 | gtkwave $^ 18 | -------------------------------------------------------------------------------- /lib/stretcher/README.md: -------------------------------------------------------------------------------- 1 | # A Verilog Synchronizer With a Pulse Stretcher 2 | 3 | Using a pulse strecher can be useful when sending a tick pulse 4 | from one clock domain to another that is not known to be running 5 | at least 150% faster. 6 | 7 | Keep in mind that synchronizer solutions pretty much always have to 8 | be tuned for each application! 9 | 10 | [This code is discussed on YouTube here.](https://youtu.be/-040qY1DETM) 11 | -------------------------------------------------------------------------------- /lib/sync/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean world 7 | 8 | FILES= \ 9 | sync.v 10 | 11 | all:: 12 | 13 | sync_tb.vvp: sync_tb.v sync.v 14 | iverilog -o $@ $^ 15 | 16 | plot: sync_tb.vcd 17 | gtkwave $^ 18 | -------------------------------------------------------------------------------- /lib/sync/README.md: -------------------------------------------------------------------------------- 1 | # Verilog Input Synchronizer 2 | 3 | See: https://youtu.be/egwMrrQBfLI 4 | -------------------------------------------------------------------------------- /lib/sync/sync.v: -------------------------------------------------------------------------------- 1 | // out = in, synchronized to "clk" 2 | 3 | // See: 4 | // https://youtu.be/egwMrrQBfLI 5 | // http://www.sunburst-design.com/papers/CummingsSNUG2008Boston_CDC.pdf 6 | 7 | module sync 8 | #( 9 | parameter SYNC_LEN = 2 // num of bits in sync fifo >= 2 10 | ) ( 11 | input wire clk, // target clock domain 12 | input wire in, // async input 13 | output wire out // sync output 14 | ); 15 | 16 | reg [SYNC_LEN-1:0] sync_fifo; 17 | 18 | always @(posedge clk) 19 | sync_fifo <= {in, sync_fifo[SYNC_LEN-1:1]}; // shift right, discard fifo lsb 20 | 21 | assign out = sync_fifo[0]; // fifo lsb is the 'oldest' value 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /lib/sync/sync_tb.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `timescale 1ns/1ps 23 | `default_nettype none 24 | 25 | module tb ( ); 26 | 27 | reg clk; 28 | reg din; 29 | wire dout; 30 | 31 | initial begin 32 | $dumpfile("sync_tb.vcd"); 33 | $dumpvars; 34 | clk = 0; 35 | din = 0; 36 | end 37 | 38 | sync #( 39 | .SYNC_LEN(3) 40 | ) uut ( 41 | .clk(clk), 42 | .in(din), 43 | .out(dout) 44 | ); 45 | 46 | always #1 clk = ~clk; 47 | 48 | initial begin 49 | #3.9; 50 | din = 1; 51 | #1; 52 | din = 0; 53 | #4; 54 | din = 1; 55 | #5; 56 | din = 0; 57 | #8; 58 | din = 1; 59 | #9; 60 | din = 0; 61 | #5; 62 | $finish; 63 | end 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /minimal/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | minimal1 \ 5 | minimal2 \ 6 | minimal3 7 | 8 | include $(TOP)/Make.rules 9 | -------------------------------------------------------------------------------- /minimal/minimal1/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd $(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /minimal/minimal1/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate a basic module that connects an input (button) to an output (led). 2 | 3 | Note that, by default, the FPGA pullup resistor is not enabled on the button input. 4 | Therefore, it is not stable. 5 | -------------------------------------------------------------------------------- /minimal/minimal1/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | 2 | set_io led1 118 3 | set_io btn1 105 4 | -------------------------------------------------------------------------------- /minimal/minimal1/pinmap-icestick.pcf: -------------------------------------------------------------------------------- 1 | 2 | set_io led1 99 3 | set_io btn1 44 4 | -------------------------------------------------------------------------------- /minimal/minimal1/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 39 # tri-color green 2 | set_io btn1 23 # header pin 3 | -------------------------------------------------------------------------------- /minimal/minimal1/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2020 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | 23 | `default_nettype none 24 | 25 | 26 | 27 | /** 28 | * This will connect btn1 to an led. 29 | **************************************************************************/ 30 | module top ( 31 | input wire btn1, // a single-bit input signal called btn1 32 | output wire led1 // a single-bit output signal called led1 33 | ); 34 | 35 | assign led1 = btn1; // connect the btn1 input to the led1 output 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /minimal/minimal1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg x; 6 | 7 | top uut ( 8 | .btn1(x) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("top_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | end 16 | 17 | initial begin 18 | // note that x does not have a known value here 19 | #1; 20 | x = 0; 21 | #1; 22 | x = 1; 23 | #1; 24 | x = 0; 25 | #1; 26 | 27 | $finish; 28 | end 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /minimal/minimal2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /minimal/minimal2/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate SB_IO to enable a pullup on the button pin. 2 | 3 | Note that inserting an SB_IO like this will prevent the test-bench from compiling. 4 | -------------------------------------------------------------------------------- /minimal/minimal2/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | 2 | set_io led1 118 3 | set_io btn1 105 4 | -------------------------------------------------------------------------------- /minimal/minimal2/pinmap-icestick.pcf: -------------------------------------------------------------------------------- 1 | 2 | set_io led1 99 3 | set_io btn1 44 4 | -------------------------------------------------------------------------------- /minimal/minimal2/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 39 # tri-color green 2 | set_io btn1 23 # header pin 3 | -------------------------------------------------------------------------------- /minimal/minimal2/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2020 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | /** 25 | * This will connect btn1 to an led. 26 | **************************************************************************/ 27 | module top ( 28 | input wire btn1, // a single-bit input signal called btn1 29 | output wire led1 // a single-bit output signal called led1 30 | ); 31 | 32 | wire btn1_pu; 33 | 34 | SB_IO #( 35 | .PIN_TYPE(6'b0000_01), // output = 0, input = 1 36 | .PULLUP(1'b1) // enable the pullup = 1 37 | ) btn1_pullup ( 38 | .PACKAGE_PIN(btn1), // the physical pin number with the pullup on it 39 | .D_IN_0(btn1_pu) // an internal wire for this pin 40 | ); 41 | 42 | assign led1 = btn1_pu; // connect the btn1 input to the led1 output 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /minimal/minimal2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg x; 6 | 7 | top uut ( 8 | .btn1(x) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("top_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | end 16 | 17 | initial begin 18 | // note that x does not have a known value here 19 | #1; 20 | x = 0; 21 | #1; 22 | x = 1; 23 | #1; 24 | x = 0; 25 | #1; 26 | 27 | $finish; 28 | end 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /minimal/minimal3/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | 14 | #top.blif: $(FILES) 15 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | 21 | timing: top.asc 22 | icetime -tmd hx$(DEVICE) $^ 23 | 24 | 25 | top_tb.vvp : top_tb.v $(FILES) 26 | iverilog -o $@ $^ 27 | 28 | plot: top_tb.vcd 29 | gtkwave $^ 30 | 31 | prog: top.bin 32 | $(FLASH_PROG) $^ 33 | 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /minimal/minimal3/README.md: -------------------------------------------------------------------------------- 1 | Demonstrate adding a pullup resistor to the button input via the .pcf file. 2 | 3 | Note that since the .pcf file is not used by test-benches it won't interfere 4 | with our ability to compile and run a it. 5 | -------------------------------------------------------------------------------- /minimal/minimal3/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | # see https://github.com/YosysHQ/nextpnr/blob/master/docs/ice40.md 2 | 3 | set_io led1 118 4 | set_io -pullup yes btn1 105 5 | -------------------------------------------------------------------------------- /minimal/minimal3/pinmap-icestick.pcf: -------------------------------------------------------------------------------- 1 | 2 | set_io led1 99 3 | set_io -pullup yes btn1 44 4 | -------------------------------------------------------------------------------- /minimal/minimal3/pinmap-upduino.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 39 # tri-color green 2 | set_io -pullup yes btn1 23 # header pin 3 | -------------------------------------------------------------------------------- /minimal/minimal3/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2020 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | 23 | `default_nettype none 24 | 25 | 26 | 27 | /** 28 | * This will connect btn1 to an led. 29 | **************************************************************************/ 30 | module top ( 31 | input wire btn1, // a single-bit input signal called btn1 32 | output wire led1 // a single-bit output signal called led1 33 | ); 34 | 35 | assign led1 = btn1; // connect the btn1 input to the led1 output 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /minimal/minimal3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg x; 6 | 7 | top uut ( 8 | .btn1(x) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("top_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | end 16 | 17 | initial begin 18 | // note that x does not have a known value here 19 | #1; 20 | x = 0; 21 | #1; 22 | x = 1; 23 | #1; 24 | x = 0; 25 | #1; 26 | 27 | $finish; 28 | end 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /modules/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | mod0 \ 5 | mod1 6 | 7 | include $(TOP)/Make.rules 8 | -------------------------------------------------------------------------------- /modules/README.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | An overview of instantiating modules with parameters. 4 | 5 | ## Ports 6 | 7 | - input (must be wire) 8 | - output (may be wire or reg) 9 | - inout (must be wire) 10 | 11 | ## Parameters 12 | 13 | - compile-time constants 14 | - can be overridden when a module is instantiated 15 | 16 | ## Localparam 17 | 18 | - compile-time constants 19 | 20 | ## Not covered: 21 | 22 | - defparam 23 | - escaped identifiers (these are horrible, just don't use them) 24 | - split ports ( See STD 1364-2005 Section 12.3.3) 25 | - renaming ports ( See STD 1364-2005 Section 12.3.3) 26 | - concatenating ports ( See STD 1364-2005 Section 12.3.3) 27 | -------------------------------------------------------------------------------- /modules/mod0/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /modules/mod0/README.md: -------------------------------------------------------------------------------- 1 | Module parameters and localparams. 2 | -------------------------------------------------------------------------------- /modules/mod1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /modules/mod1/README.md: -------------------------------------------------------------------------------- 1 | Module parameters and localparams. 2 | -------------------------------------------------------------------------------- /modules/mod1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module tb(); 4 | 5 | reg clk = 0; 6 | wire reset1; 7 | wire reset2; 8 | 9 | initial begin 10 | $dumpfile("top_tb.vcd"); 11 | $dumpvars; 12 | 13 | #5000; // wait a while 14 | $finish; // stop the simulation 15 | end 16 | 17 | always #1 clk = ~clk; 18 | 19 | // positional parameters can be used but can be error-prone during development 20 | por #( .delay(3) ) r1 ( reset1, clk ); // port order matters here 21 | por #( 1000 ) r2 ( .clk(clk), .reset(reset2) ); // port order does not matter here 22 | 23 | endmodule 24 | 25 | // This uses the old-style (annoying and error-prone) way to define a module. 26 | module por ( reset, clk ); 27 | 28 | output reg reset = 1'b1; // we can initialize regs that are ports 29 | input clk; // default type is wire 30 | 31 | parameter delay = 10; // the order of a plurality of parameters matters! 32 | 33 | localparam NUM_BITS = $clog2(delay); 34 | 35 | // an appropriately sized counter 36 | reg [NUM_BITS-1:0] counter = 0; 37 | reg [NUM_BITS-1:0] counter_next = 0; 38 | reg reset_next = 1'b1; 39 | 40 | always @( posedge clk ) begin 41 | counter <= counter_next; 42 | reset <= reset_next; 43 | end 44 | 45 | // Keeping the combinational circuitry for determining the next state 46 | // in its own block can keep things much cleaner in more complex systems. 47 | always @(*) begin 48 | if ( counter == delay-1 ) begin 49 | reset_next = 1'b0; // de-assert the reset signal 50 | counter_next = counter; // do not advance the counter 51 | end else begin 52 | reset_next = 1'b1; // assert the reset signal 53 | counter_next = counter + 1; // advance the delay counter 54 | end 55 | end 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /nonblock/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | nb1 \ 5 | nb2 \ 6 | nb3 7 | 8 | include $(TOP)/Make.rules 9 | -------------------------------------------------------------------------------- /nonblock/nb1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /nonblock/nb1/README.md: -------------------------------------------------------------------------------- 1 | # Edge-sensitive `always` block sensitivity lists. 2 | -------------------------------------------------------------------------------- /nonblock/nb1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module tb(); 4 | 5 | reg clk; 6 | 7 | initial begin 8 | $dumpfile("top_tb.vcd"); 9 | $dumpvars; 10 | 11 | clk = 0; 12 | 13 | #1 clk = 1; 14 | #1 clk = 0; 15 | #1 clk = 1; 16 | #1 clk = 0; 17 | #1 clk = 1; 18 | #1 clk = 0; 19 | 20 | #2; // wait a while 21 | $finish; // stop the simulation 22 | end 23 | 24 | always @(clk) 25 | $display("%2t: @(*) clk is %b", $time, clk); 26 | 27 | always @(posedge clk) 28 | $display("%2t: @(pos) clk is %b", $time, clk); 29 | 30 | always @(negedge clk) 31 | $display("%2t: @(neg) clk is %b", $time, clk); 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /nonblock/nb2/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /nonblock/nb2/README.md: -------------------------------------------------------------------------------- 1 | The quintessential example of a nonblocking assignment. 2 | 3 | Warning: IMHO, this is an almost useless example and risks confusing 4 | the student as to the purpose of the `<=` operator! 5 | -------------------------------------------------------------------------------- /nonblock/nb2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; 6 | reg [7:0] a; 7 | reg [7:0] b; 8 | 9 | initial begin 10 | $dumpfile("top_tb.vcd"); 11 | $dumpvars; 12 | //$monitor("%5d a:%2d b:%2d clk:%b", $time, a, b, clk); 13 | $monitor("%5d a:%2d b:%2d sum:%2d", $time, a, b, sum); 14 | a = 18; 15 | b = 00; 16 | clk = 0; 17 | #100; 18 | $finish; 19 | end 20 | 21 | always #1 clk = ~clk; 22 | 23 | // swap the values of a and b 24 | always @(posedge clk) begin 25 | b <= a; 26 | a <= b; 27 | end 28 | 29 | // lets make it interesting... 30 | // The assignment below gets scheduled in the active queue as a result 31 | // of the nonblocking assignmnet into b. 32 | 33 | wire [7:0] sum; 34 | assign sum = b+1; 35 | 36 | endmodule 37 | -------------------------------------------------------------------------------- /nonblock/nb3/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /nonblock/nb3/README.md: -------------------------------------------------------------------------------- 1 | Variations of `always` block sensitivity lists. 2 | -------------------------------------------------------------------------------- /nonblock/nb3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; 6 | 7 | reg [7:0] a; 8 | reg [7:0] b; 9 | reg [7:0] q; 10 | 11 | initial begin 12 | $dumpfile("top_tb.vcd"); 13 | $dumpvars; 14 | 15 | $monitor("%2d: q:%2d a:%2d b:%2d", $time, q, a, b); 16 | a = 0; 17 | b = 0; 18 | //q = 0; // leave q uninitialized 19 | clk = 1; 20 | 21 | #30; 22 | $finish; 23 | end 24 | 25 | always #1 clk = ~clk; 26 | 27 | always @(posedge clk) 28 | q <= a + b; 29 | always @(posedge clk) 30 | a <= a + 1; 31 | always @(posedge clk) 32 | b <= b + 1; 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /pics/selsig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnwinans/Verilog-Examples/ee3046d41e96a88ded95816f9acb4d71b7dcc648/pics/selsig.png -------------------------------------------------------------------------------- /pics/waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnwinans/Verilog-Examples/ee3046d41e96a88ded95816f9acb4d71b7dcc648/pics/waveform.png -------------------------------------------------------------------------------- /pll/README.md: -------------------------------------------------------------------------------- 1 | 2 | 2025-01-05 jrw 3 | 4 | Note: if you use the software from Lattice, constraints related to 5 | things like which pins can be used to directly-drive a PLL or that 6 | become reserved as a result of choices like what PLL modes have been 7 | selected are more obvious as selections in various config menus 8 | become enabled/disabled as clues for guidance. 9 | 10 | The pin numbers mentioned here are in reference to the TQFP package. 11 | 12 | 13 | The following copied from: https://github.com/YosysHQ/icestorm/issues/273 14 | 15 | If you want to use `ice40_PLL_PAD`, `ice40_PLL_2F_PAD` or `ice40_PLL_2_PAD` you 16 | have to route external clock only to: 17 | 18 | * `IOB_81_GBIN5` - pin 49 19 | * `IOT_198_GBIN0` - pin 129 20 | 21 | I didn't find that information in any vendor PDF's or pinout files, just 22 | figured out it experimentally. 23 | 24 | If you want to use `ice40_PLL_CORE` or `ice40_PLL_2F_CORE` you won't be able to 25 | use PLL dedicated pins as inputs. 26 | 27 | Some additional information from iCE40 sysCLOCK PLL Design and Usage Guide 28 | (FPGA-TN-02052-1.2): 29 | 30 | 5.1.2. iCEcube2 Software 31 | 32 | * If any instance of PLL is placed in the location of the I/O cell, 33 | then, an instance of `SB_GB_IO` cannot be placed in that particular 34 | I/O cell. 35 | 36 | * If an instance of `ice40_PLL_CORE` or `ice40_PLL_2F_CORE` is placed, an 37 | instance of `SB_IO` in output-only mode can be placed in the 38 | associated I/O cell location. 39 | 40 | * If an instance of `ice40_PLL_PAD`, `ice40_PLL_2F_PAD`, `ice40_PLL_2_PAD` 41 | is placed, the associated I/O cell cannot be used by any `SB_IO` 42 | or `SB_GB_IO`. 43 | 44 | * If an instance of `ice40_PLL_2F_CORE`, `ice40_PLL_2F_PAD`, `ice40_PLL_2_PAD` 45 | is placed, an instance of `SB_IO` in output-only mode can be placed 46 | in the right neighboring I/O cell. 47 | 48 | 49 | -------------------------------------------------------------------------------- /pll/example1/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll_25_100.v \ 11 | pll_25_40.v \ 12 | counter.v 13 | 14 | all:: top.bin 15 | 16 | 17 | #top.blif: $(FILES) 18 | # $(COMPILE.v) -p "synth_ice40 -top top -blif $@" $^ 19 | 20 | top.json: $(FILES) 21 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 22 | 23 | timing: top.asc 24 | icetime -tmd $(DEVICE) $^ 25 | 26 | 27 | counter_tb.vvp: counter_tb.v counter.v 28 | iverilog -o $@ $^ 29 | 30 | plot: counter_tb.vcd 31 | gtkwave $^ 32 | 33 | prog: top.bin 34 | $(FLASH_PROG) $^ 35 | 36 | # extra dependancies 37 | top.asc: $(PINMAP) 38 | 39 | -------------------------------------------------------------------------------- /pll/example1/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 PLL Example Files 2 | 3 | This directory contains files to demonstrate the use of the PLL 4 | 5 | To generate a PLL module for a PAD input: 6 | 7 | ``` 8 | icepll -i 25 -p -o 50 -m -n pll_25_50 9 | ``` 10 | 11 | To generate a PLL module for a CORE input (leave off the -p): 12 | ``` 13 | icepll -i 25 -o 50 -m -n pll_25_50 14 | ``` 15 | 16 | Note that this example includes both types of PLL and a commented-out 17 | line in the PCF file to demonstrate what happens when you try to 18 | instantiate a PAD PLL on an invalid pin. 19 | -------------------------------------------------------------------------------- /pll/example1/counter.v: -------------------------------------------------------------------------------- 1 | module counter #( 2 | parameter WIDTH = 8 3 | ) ( 4 | input wire clk, 5 | input wire reset, 6 | output wire [WIDTH-1:0] out 7 | ); 8 | 9 | reg [WIDTH-1:0] counter = 0; 10 | 11 | always @ (posedge clk) 12 | begin 13 | if (reset) 14 | counter <= 0; 15 | else 16 | counter <= counter + 1; 17 | end 18 | 19 | assign out = counter; 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /pll/example1/counter_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // the free running clock 6 | 7 | counter uut ( 8 | .clk(clk) 9 | // don't need to connect every signal here if not want to 10 | ); 11 | 12 | initial begin 13 | $dumpfile("counter_tb.vcd"); // where to write the dump 14 | $dumpvars; // dump EVERYTHING 15 | clk = 0; 16 | end 17 | 18 | always #1 clk = ~clk; 19 | 20 | initial begin 21 | #1000; 22 | //#16000000; 23 | $finish; 24 | end 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /pll/example1/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | #set_io clk25 49 3 | 4 | set_io -pullup yes reset_n 102 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | -------------------------------------------------------------------------------- /pll/example1/pll_25_100.v: -------------------------------------------------------------------------------- 1 | /* 2 | * F_PLLIN: 25.000 MHz (given) 3 | * F_PLLOUT: 100.000 MHz (requested) 4 | * F_PLLOUT: 100.000 MHz (achieved) 5 | * 6 | * FEEDBACK: SIMPLE 7 | * F_PFD: 25.000 MHz 8 | * F_VCO: 800.000 MHz 9 | * 10 | * DIVR: 0 (4'b0000) 11 | * DIVF: 31 (7'b0011111) 12 | * DIVQ: 3 (3'b011) 13 | * 14 | * FILTER_RANGE: 2 (3'b010) 15 | */ 16 | 17 | module pll_25_100( 18 | input clock_in, 19 | output global_clock, 20 | output locked 21 | ); 22 | 23 | wire g_clock_int; 24 | 25 | 26 | SB_PLL40_CORE #( 27 | // SB_PLL40_PAD #( 28 | .FEEDBACK_PATH("SIMPLE"), 29 | .DIVR(4'b0000), 30 | .DIVF(7'b0011111), 31 | .DIVQ(3'b011), 32 | .FILTER_RANGE(3'b010) 33 | ) uut ( 34 | .LOCK(locked), 35 | .RESETB(1'b1), 36 | .BYPASS(1'b0), 37 | .REFERENCECLK(clock_in), 38 | // .PACKAGEPIN(clock_in), 39 | .PLLOUTGLOBAL(g_clock_int) 40 | ); 41 | 42 | SB_GB sbGlobalBuffer_inst( .USER_SIGNAL_TO_GLOBAL_BUFFER(g_clock_int), .GLOBAL_BUFFER_OUTPUT(global_clock) ); 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /pll/example1/pll_25_40.v: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * F_PLLIN: 25.000 MHz (given) 4 | * F_PLLOUT: 40.000 MHz (requested) 5 | * F_PLLOUT: 39.844 MHz (achieved) 6 | * 7 | * FEEDBACK: SIMPLE 8 | * F_PFD: 12.500 MHz 9 | * F_VCO: 637.500 MHz 10 | * 11 | * DIVR: 1 (4'b0001) 12 | * DIVF: 50 (7'b0110010) 13 | * DIVQ: 4 (3'b100) 14 | * 15 | * FILTER_RANGE: 1 (3'b001) 16 | */ 17 | 18 | module pll_25_40( 19 | input clock_in, 20 | output global_clock, 21 | output locked 22 | ); 23 | 24 | wire g_clock_int; 25 | 26 | 27 | // SB_PLL40_CORE #( 28 | SB_PLL40_PAD #( 29 | .FEEDBACK_PATH("SIMPLE"), 30 | .DIVR(4'b0001), 31 | .DIVF(7'b0110010), 32 | .DIVQ(3'b100), 33 | .FILTER_RANGE(3'b001) 34 | ) uut ( 35 | .LOCK(locked), 36 | .RESETB(1'b1), 37 | .BYPASS(1'b0), 38 | // .REFERENCECLK(clock_in), 39 | .PACKAGEPIN(clock_in), 40 | .PLLOUTGLOBAL(g_clock_int) 41 | ); 42 | 43 | SB_GB sbGlobalBuffer_inst( .USER_SIGNAL_TO_GLOBAL_BUFFER(g_clock_int), .GLOBAL_BUFFER_OUTPUT(global_clock) ); 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /pll/example1/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire reset_n, 6 | output wire [7:0] led 7 | ); 8 | 9 | localparam COUNTER_WIDTH = 30; 10 | 11 | wire [COUNTER_WIDTH-1:0] ctr; 12 | wire pll_out; 13 | 14 | pll_25_100 upll( .clock_in(clk25), .global_clock(pll_out) ); 15 | //pll_25_40 upll( .clock_in(clk25), .global_clock(pll_out) ); 16 | 17 | counter #( .WIDTH(COUNTER_WIDTH) ) c ( .clk(pll_out), .reset(~reset_n), .out(ctr) ); 18 | 19 | assign led = ~ctr[COUNTER_WIDTH-1:COUNTER_WIDTH-8]; // LEDs are active-low 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /pll/example2/.gitignore: -------------------------------------------------------------------------------- 1 | pll_25_18432.v 2 | pll_25_65.v 3 | -------------------------------------------------------------------------------- /pll/example2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | counter.v\ 11 | pll_25_65.v \ 12 | pll_25_18432.v 13 | 14 | # FPGA oscillator speed 15 | OSC_CLK=25 16 | 17 | all:: top.bin 18 | 19 | top.json: $(FILES) 20 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 21 | 22 | prog: top.bin 23 | $(FLASH_PROG) $^ 24 | 25 | pll_25_65.v: 26 | icepll -i $(OSC_CLK) -o 65 -m -n pll_25_65 -f $@ 27 | 28 | pll_25_18432.v: 29 | icepll -i $(OSC_CLK) -o 18.432 -m -n pll_25_18432 -f $@ 30 | 31 | # extra dependancies 32 | top.asc: $(PINMAP) 33 | 34 | clean:: 35 | rm -f pll_25_65.v pll_25_18432.v 36 | -------------------------------------------------------------------------------- /pll/example2/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 example with two PLLs 2 | 3 | This example uses a PLL to generate 65MHZ and the second 4 | PLL to generate 18.432 MHZ. 5 | 6 | Note that this includes a forced-on reset to hold a possibly 7 | present 2067-Z8S180 Nouveau CPU board in reset. 8 | -------------------------------------------------------------------------------- /pll/example2/counter.v: -------------------------------------------------------------------------------- 1 | module counter #( 2 | parameter WIDTH = 8 3 | ) ( 4 | input wire clk, 5 | input wire reset, 6 | output wire [WIDTH-1:0] out 7 | ); 8 | 9 | reg [WIDTH-1:0] counter = 0; 10 | 11 | always @ (posedge clk) 12 | begin 13 | if (reset) 14 | counter <= 0; 15 | else 16 | counter <= counter + 1; 17 | end 18 | 19 | assign out = counter; 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /pll/example2/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io clk1 61 # an easily probeable pin 16 | set_io clk2 73 # an easily probeable pin 17 | 18 | # this is here to hold a Nouveau CPU board in reset so that 19 | # nothing strange should happen if it happens to be plugged 20 | # into the FPGA board. 21 | set_io reset_n 28 22 | 23 | -------------------------------------------------------------------------------- /pll/example2/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire clk1, 8 | output wire clk2, 9 | output wire [7:0] led 10 | ); 11 | 12 | localparam COUNTER_WIDTH = 26; 13 | 14 | wire [COUNTER_WIDTH-1:0] c1_out; 15 | wire [COUNTER_WIDTH-1:0] c2_out; 16 | 17 | // use one PLL to generate 65MHZ from 25MHZ 18 | pll_25_65 pll65 (.clock_in(clk25), .clock_out(clk1)); 19 | 20 | // use a second PLL to generate 18.432MHZ from 25MHZ 21 | pll_25_18432 pll_18432 (.clock_in(clk25), .clock_out(clk2)); 22 | 23 | // divide clk1 down to human scale so can see it on an LED 24 | counter #( .WIDTH(COUNTER_WIDTH) ) c1 ( 25 | .clk(clk1), 26 | .reset(~s1_n), 27 | .out(c1_out) 28 | ); 29 | 30 | // divide clk2 down to human scale so can see it on an LED 31 | counter #( .WIDTH(COUNTER_WIDTH) ) c2 ( 32 | .clk(clk2), 33 | .reset(~s1_n), 34 | .out(c2_out) 35 | ); 36 | 37 | assign led[0] = c2_out[COUNTER_WIDTH-1]; 38 | assign led[1] = c1_out[COUNTER_WIDTH-1]; 39 | 40 | assign led[7:2] = ~0; // turn off the rest of the LEDs 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /ps2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | naive 5 | 6 | include $(TOP)/Make.rules 7 | -------------------------------------------------------------------------------- /ps2/naive-reset/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | $(LIB_DIR)/sync/sync.v \ 10 | $(LIB_DIR)/debounce/debounce.v \ 11 | ps2.v 12 | 13 | # FPGA oscillator speed 14 | OSC_CLK=25 15 | 16 | all:: top.bin 17 | 18 | # special case for top.v only used here 19 | top.json: $(FILES) top.v 20 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 21 | 22 | timing: top.asc 23 | icetime -tmd $(DEVICE) $^ 24 | 25 | # special case for ps2_tb.v only used here 26 | ps2_tb.vvp: $(FILES) ps2_tb.v 27 | iverilog -o $@ $^ 28 | 29 | plot: ps2_tb.vcd 30 | gtkwave $^ 31 | 32 | prog: top.bin 33 | $(FLASH_PROG) $^ 34 | 35 | # extra dependancies 36 | top.asc: $(PINMAP) 37 | -------------------------------------------------------------------------------- /ps2/naive-reset/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 naive PS2 interface example Files 2 | 3 | This directory contains a very basic PS2 interface useful for 4 | validating an electrical interface. 5 | -------------------------------------------------------------------------------- /ps2/naive-reset/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io kbclk 60 16 | set_io kbdata 62 17 | 18 | set_io test1 141 19 | set_io test2 143 20 | set_io test3 1 21 | -------------------------------------------------------------------------------- /ps2/naive-reset/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | 5 | output wire test1, 6 | output wire test2, 7 | output wire test3, 8 | 9 | input wire clk25, 10 | input wire s1_n, 11 | input wire s2_n, 12 | inout wire kbclk, // we will use an SB_IO to control direction 13 | inout wire kbdata, // we will use an SB_IO to control direction 14 | output wire [7:0] led 15 | ); 16 | 17 | wire reset_clean; 18 | wire s1_sync; 19 | 20 | wire [8:0] data; // includes the parity bit 21 | 22 | // the 'inside' signals we use for the tri-state logic 23 | wire kbdata_in, kbdata_out; 24 | wire kbclk_in, kbclk_out; 25 | 26 | assign test1 = kbdata_out; 27 | assign test2 = kbclk_out; 28 | assign test3 = kbclk_in; 29 | 30 | // explicitly configure the PS2 IO pins (to make yosys happy) 31 | // See FPGA-TN-02026-3.2 (iCE40 Technology Library), page 83 32 | SB_IO #( 33 | .PIN_TYPE(6'b101001), 34 | .PULLUP(1'b1) 35 | ) io_buf_kbclk ( 36 | .PACKAGE_PIN(kbclk), 37 | .OUTPUT_ENABLE(~kbclk_out), // turn on the output driver if kbclk is low else float 38 | .D_OUT_0(kbclk_out), // when kbclk is low, drive pin to zero 39 | .D_IN_0(kbclk_in) // this lets us look at the pin input 40 | ); 41 | 42 | SB_IO #( 43 | .PIN_TYPE(6'b101001), 44 | .PULLUP(1'b1) 45 | ) io_buf_kbdata ( 46 | .PACKAGE_PIN(kbdata), 47 | .OUTPUT_ENABLE(~kbdata_out), 48 | .D_OUT_0(kbdata_out), 49 | .D_IN_0(kbdata_in) 50 | ); 51 | 52 | sync rsync ( 53 | .clk(clk25), 54 | .in(~s1_n), 55 | .out(s1_sync) 56 | ); 57 | 58 | // 25MHZ/250 = 10 usec = 100KHZ 59 | debounce #( .MAX_COUNT(250) ) deb ( 60 | .clock(clk25), 61 | .in(s1_sync), 62 | .out(reset_clean) 63 | ); 64 | 65 | ps2 kbd ( 66 | .reset(~s1_n), 67 | .ps2_data_in(kbdata_in), 68 | .ps2_data_out(kbdata_out), 69 | .ps2_clk_in(kbclk_in), 70 | .ps2_clk_out(kbclk_out), 71 | .rx_data(data) // note the MSB is pruned 72 | ); 73 | 74 | assign led = ~data[7:0]; 75 | 76 | endmodule 77 | -------------------------------------------------------------------------------- /ps2/naive/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | ps2.v 11 | 12 | # FPGA oscillator speed 13 | OSC_CLK=25 14 | 15 | all:: top.bin 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | timing: top.asc 21 | icetime -tmd $(DEVICE) $^ 22 | 23 | ps2_tb.vvp: ps2_tb.v ps2.v 24 | iverilog -o $@ $^ 25 | 26 | plot: ps2_tb.vcd 27 | gtkwave $^ 28 | 29 | prog: top.bin 30 | $(FLASH_PROG) $^ 31 | 32 | # extra dependancies 33 | top.asc: $(PINMAP) 34 | -------------------------------------------------------------------------------- /ps2/naive/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 naive PS2 interface example Files 2 | 3 | This directory contains a very basic PS2 interface useful for 4 | validating an electrical interface. 5 | -------------------------------------------------------------------------------- /ps2/naive/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io -pullup yes kbclk 60 16 | set_io -pullup yes kbdata 62 17 | -------------------------------------------------------------------------------- /ps2/naive/top.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // 3 | // Copyright (C) 2024 John Winans 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18 | // USA 19 | // 20 | //************************************************************************** 21 | 22 | `default_nettype none 23 | 24 | module top ( 25 | input wire clk25, 26 | input wire s1_n, 27 | input wire s2_n, 28 | input wire kbclk, 29 | input wire kbdata, 30 | output wire [7:0] led 31 | ); 32 | 33 | wire [7:0] data; 34 | 35 | ps2 kbd ( 36 | .reset(~s1_n), 37 | .ps2_data(kbdata), 38 | .ps2_clk(kbclk), 39 | .rx_data(data) // note the MSB is pruned 40 | ); 41 | 42 | assign led = ~data; 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /sb_io/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | bidir \ 5 | tristate_sb_io \ 6 | tristate_ternary 7 | 8 | include $(TOP)/Make.rules 9 | -------------------------------------------------------------------------------- /sb_io/README.md: -------------------------------------------------------------------------------- 1 | # I/O Primitives 2 | 3 | Exmaples that demonstrate features of the SB_IO block and how to use it. 4 | -------------------------------------------------------------------------------- /sb_io/bidir/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | top.json: $(FILES) 14 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 15 | 16 | timing: top.asc 17 | icetime -tmd $(DEVICE) $^ 18 | 19 | prog: top.bin 20 | $(FLASH_PROG) $^ 21 | 22 | # extra dependancies 23 | top.asc: $(PINMAP) 24 | -------------------------------------------------------------------------------- /sb_io/bidir/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 SB_IO test app 2 | 3 | This is used to test the use of an SB_IO to create an open-collector 4 | driver while, at the same time, reading the input value on the same pin. 5 | 6 | This is typical on electrical interfaces such as I2C, one-wire, PS/2,... 7 | -------------------------------------------------------------------------------- /sb_io/bidir/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 118 2 | set_io led2 116 3 | 4 | set_io -pullup yes s1_n 102 5 | set_io -pullup yes s2_n 105 6 | 7 | # Yosys warns that specifying a pullup here might not work on an inout port 8 | 9 | #set_io d_out 143 # pin 143 is on bank 0 10 | set_io -pullup yes d_out 143 # pin 143 is on bank 0 11 | -------------------------------------------------------------------------------- /sb_io/tristate_sb_io/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | top.json: $(FILES) 14 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 15 | 16 | timing: top.asc 17 | icetime -tmd $(DEVICE) $^ 18 | 19 | prog: top.bin 20 | $(FLASH_PROG) $^ 21 | 22 | # extra dependancies 23 | top.asc: $(PINMAP) 24 | -------------------------------------------------------------------------------- /sb_io/tristate_sb_io/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 SB_IO Tristate Output Demonstration 2 | 3 | This demonstrates a tristate output pin by explicitly configuring 4 | an SB_IO block. 5 | -------------------------------------------------------------------------------- /sb_io/tristate_sb_io/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 118 2 | set_io led2 116 3 | 4 | set_io -pullup yes s1_n 102 5 | set_io -pullup yes s2_n 105 6 | 7 | # test cases for each bank (See ice40pinouthx4k.xlsx) 8 | 9 | #set_io d_out 143 # pin 143 is on bank 0 10 | #set_io d_out 82 # pin 82 is on bank 1 11 | #set_io d_out 44 # pin 44 is on bank 2 12 | set_io d_out 1 # pin 1 is on bank 3 13 | -------------------------------------------------------------------------------- /sb_io/tristate_ternary/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v 10 | 11 | all:: top.bin 12 | 13 | top.json: $(FILES) 14 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 15 | 16 | timing: top.asc 17 | icetime -tmd $(DEVICE) $^ 18 | 19 | prog: top.bin 20 | $(FLASH_PROG) $^ 21 | 22 | # extra dependancies 23 | top.asc: $(PINMAP) 24 | -------------------------------------------------------------------------------- /sb_io/tristate_ternary/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 SB_IO Tristate Output Demonstration 2 | 3 | This demonstrates the use of an inferred tristate output pin buffer. 4 | 5 | NOTE: Yosys ignores the pcf pullup resitor parm on inferred tristate output. 6 | -------------------------------------------------------------------------------- /sb_io/tristate_ternary/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io led1 118 2 | set_io led2 116 3 | 4 | set_io -pullup yes s1_n 102 5 | set_io -pullup yes s2_n 105 6 | 7 | set_io -pullup yes d_out 143 8 | -------------------------------------------------------------------------------- /sim/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | sim1 \ 5 | sim2 \ 6 | sim3 \ 7 | sim4 \ 8 | sim5 \ 9 | sim6 10 | 11 | include $(TOP)/Make.rules 12 | -------------------------------------------------------------------------------- /sim/sim1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim1/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | When do the values of things actually change during simulation? 4 | 5 | ## Topics: 6 | 7 | - timescale 8 | - default_nettype 9 | - reg 10 | - wire 11 | - assign 12 | - & ^ (binary operators) 13 | - and(), or() 14 | - initial (process blocks) 15 | - begin / end 16 | - blocking assignment 17 | - \# (timing control) 18 | - $display 19 | - $time 20 | - $finish 21 | -------------------------------------------------------------------------------- /sim/sim2/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim2/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | When do the values of things actually change during simulation? 4 | 5 | ## Topics 6 | 7 | - $strobe 8 | -------------------------------------------------------------------------------- /sim/sim2/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a; 8 | reg b; 9 | 10 | wire sum; 11 | wire cy; 12 | 13 | assign sum = a ^ b; 14 | assign cy = a & b; 15 | 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); 19 | $dumpvars; 20 | end 21 | 22 | initial begin 23 | a = 0; 24 | b = 0; 25 | 26 | // Changing $display to $strobe tells the simuator to wait until 27 | // the current time has advanced. So the printing will wait until 28 | // after all pending changes have completed before the values are printed. 29 | $strobe("%5t: a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 30 | 31 | // We wait before changing the values but not just to delay the printing. 32 | #1; 33 | 34 | a = 0; 35 | b = 1; 36 | 37 | $strobe("%5t: a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 38 | #1; 39 | 40 | a = 1; 41 | b = 0; 42 | 43 | $strobe("%5t: a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 44 | #1; 45 | 46 | a = 1; 47 | b = 1; 48 | 49 | $strobe("%5t: a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 50 | #1; 51 | 52 | a = 0; 53 | b = 0; 54 | $strobe("%5t: a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 55 | #2; 56 | 57 | $finish; // The $finish 'system task' halts the simulation 58 | end 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /sim/sim3/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim3/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | When do the values of things actually change during simulation? 4 | 5 | ## Topics 6 | 7 | - $monitor 8 | -------------------------------------------------------------------------------- /sim/sim3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a; 8 | reg b; 9 | 10 | wire sum; 11 | wire cy; 12 | 13 | assign sum = a ^ b; 14 | assign cy = a & b; 15 | 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); 19 | $dumpvars; 20 | end 21 | 22 | initial begin 23 | // Another way to print things when they change is to use $monitor() 24 | 25 | // Only one $monitor task allowed, so we can NOT do this: 26 | //$monitor("time:%0t sum = %0d", $time, sum); 27 | //$monitor("time:%0t cy = %0d", $time, cy); 28 | 29 | // ... therefore do this: 30 | $monitor("time:%5t a=%b, b=%b, sum=%b, cy=%b", $time, a, b, sum, cy); 31 | 32 | // $monitor will report changes in all the signals that are listed as 33 | // parameters (except for $time since it always changes) 34 | 35 | a = 0; 36 | b = 0; 37 | 38 | // NOTE: the monitor will fire here... because a and b changed from x to 0 ! 39 | #1; 40 | 41 | a = 0; 42 | b = 0; 43 | // NOTE: no monitor will fire here... because nothing changed !! 44 | #1; 45 | 46 | a = 0; 47 | b = 1; 48 | #1; 49 | 50 | a = 1; 51 | b = 0; 52 | #1; 53 | 54 | a = 1; 55 | b = 1; 56 | #1; 57 | 58 | a = 0; 59 | b = 0; 60 | #2; 61 | 62 | $finish; // The $finish 'system task' halts the simulation 63 | end 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /sim/sim4/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim4/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | When do the values of things actually change during simulation? 4 | 5 | ## Topics 6 | 7 | - #0 8 | - ? : 9 | -------------------------------------------------------------------------------- /sim/sim4/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a; 8 | reg b; 9 | 10 | wire sum; 11 | wire cy; 12 | 13 | assign sum = a ^ b; 14 | assign cy = a & b; 15 | 16 | initial begin 17 | $dumpfile("top_tb.vcd"); 18 | $dumpvars; 19 | end 20 | 21 | initial begin 22 | a = 0; 23 | b = 0; 24 | 25 | // 1364-2005 11.3: An explicit zero delay (#0) requires that the 26 | // process be suspended and added as an inactive event for the 27 | // current time so that the process is resumed in the next simulation 28 | // cycle in the current time. 29 | // 30 | // This means that using #0 will cause everything else that is ALREADY 31 | // scheduled to finish 'now' to be completed before proceeding. 32 | // #0 is a request to move myself to the back of a queue. As long as 33 | // nothing else gets put in that queue before the time advances then 34 | // all will be fine. But if something in the queue now causes more 35 | // things to get in the queue then those new things will happen 36 | // after the $display() 37 | // 38 | // In this simple application using #0 like this is OK. 39 | #0 $display("%5t: a=%b, b=%b, sum=%b, cy=%b %s", $time, a, b, sum, cy, (sum==0 && cy==0)? "pass" : "fail" ); 40 | #1; 41 | 42 | a = 0; 43 | b = 1; 44 | 45 | #0 $display("%5t: a=%b, b=%b, sum=%b, cy=%b %s", $time, a, b, sum, cy, (sum==1 && cy==0)? "pass" : "fail" ); 46 | #1; 47 | 48 | a = 1; 49 | b = 0; 50 | 51 | #0 $display("%5t: a=%b, b=%b, sum=%b, cy=%b %s", $time, a, b, sum, cy, (sum==1 && cy==0)? "pass" : "fail" ); 52 | #1; 53 | 54 | a = 1; 55 | b = 1; 56 | 57 | #0 $display("%5t: a=%b, b=%b, sum=%b, cy=%b %s", $time, a, b, sum, cy, (sum==0 && cy==1)? "pass" : "fail" ); 58 | #1; 59 | 60 | a = 0; 61 | b = 0; 62 | #0 $display("%5t: a=%b, b=%b, sum=%b, cy=%b %s", $time, a, b, sum, cy, (sum==0 && cy==0)? "pass" : "fail" ); 63 | #2; 64 | 65 | $finish; // The $finish 'system task' halts the simulation 66 | end 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /sim/sim5/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim5/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | Creating an ASSERT macro with conditional expression to clean up test bench clutter. 4 | 5 | ## Topics 6 | 7 | - `define 8 | - ? : 9 | -------------------------------------------------------------------------------- /sim/sim5/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a; 8 | reg b; 9 | 10 | wire sum; 11 | wire cy; 12 | 13 | assign sum = a ^ b; 14 | assign cy = a & b; 15 | 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); 19 | $dumpvars; 20 | end 21 | 22 | 23 | // Since this test bench is simple and all checks use the same values, 24 | // we can use a macro to print and check everything to reduce visual clutter. 25 | 26 | `define ASSERT(cond) $display("%s:%0d %m time:%3t a=%b, b=%b, sum=%b, cy=%b %0s", `__FILE__, `__LINE__, $time, a, b, sum, cy, (cond) ? "passed" : "ASSERTION (cond) FAILED!" ); 27 | 28 | 29 | initial begin 30 | a = 0; 31 | b = 0; 32 | 33 | #1; 34 | `ASSERT( sum==0 && cy==0 ); 35 | 36 | a = 0; 37 | b = 1; 38 | 39 | #1; 40 | `ASSERT( sum==1 && cy==0 ); 41 | 42 | a = 1; 43 | b = 0; 44 | 45 | #1; 46 | `ASSERT( sum==1 && cy==0 ); 47 | 48 | a = 1; 49 | b = 1; 50 | 51 | #1; 52 | `ASSERT( sum==0 && cy==1 ); 53 | 54 | a = 0; 55 | b = 0; 56 | 57 | #1; 58 | `ASSERT( sum==0 && cy==0 ); 59 | 60 | #2; 61 | $finish; 62 | end 63 | 64 | endmodule 65 | -------------------------------------------------------------------------------- /sim/sim6/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /sim/sim6/README.md: -------------------------------------------------------------------------------- 1 | # Veriolog Simulation Timing 2 | 3 | Creating an ASSERT macro to halt simulation upon first detected failure. 4 | 5 | ## Topics 6 | 7 | - if conditional expression 8 | - multiline macros 9 | -------------------------------------------------------------------------------- /sim/sim6/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a; 8 | reg b; 9 | 10 | wire sum; 11 | wire cy; 12 | 13 | assign sum = a ^ b; 14 | assign cy = a & b; 15 | 16 | 17 | initial begin 18 | $dumpfile("top_tb.vcd"); 19 | $dumpvars; 20 | end 21 | 22 | 23 | // We can run silently when the assertions are passing 24 | // and then halt the simulation immediately upon a failure. 25 | 26 | `define ASSERT(cond) \ 27 | if ( ~(cond) ) begin \ 28 | $display("%s:%0d %m time:%5t ASSERTION FAILED: cond", `__FILE__, `__LINE__, $time ); \ 29 | $finish; \ 30 | end 31 | 32 | initial begin 33 | // We can add a monitor if we want to watch changes too 34 | //$monitor("time:%5t ", $time, a, b, sum, cy ); // this will print the values smashed together 35 | //$monitor("time:%5t a=%b b=%b sum=%b cy=%b", $time, a, b, sum, cy ); 36 | 37 | a = 0; 38 | b = 0; 39 | 40 | #1; 41 | `ASSERT( sum==0 && cy==0 ); 42 | 43 | a = 0; 44 | b = 1; 45 | 46 | #1; 47 | `ASSERT( sum==1 && cy==0 ); 48 | 49 | a = 1; 50 | b = 0; 51 | 52 | #1; 53 | `ASSERT( sum==1 && cy==0 ); 54 | 55 | a = 1; 56 | b = 1; 57 | 58 | #1; 59 | `ASSERT( sum==0 && cy==1 ); 60 | 61 | a = 0; 62 | b = 0; 63 | 64 | #1 65 | `ASSERT( sum==0 && cy==0 ); 66 | 67 | #2; 68 | $finish; 69 | end 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /types/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | types1 \ 5 | types2 \ 6 | types3 \ 7 | types4 8 | 9 | include $(TOP)/Make.rules 10 | -------------------------------------------------------------------------------- /types/types1/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /types/types1/README.md: -------------------------------------------------------------------------------- 1 | # vectors 2 | 3 | ## Topics 4 | 5 | - vector 6 | - concatenation operator `{}` 7 | - big & little bit-ordering 8 | - bit-ranges `[n:m]` 9 | -------------------------------------------------------------------------------- /types/types1/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | // Verilog treats a vector as a binary integer! 8 | 9 | // little-endian (use this unless you have a good reason not to) 10 | reg [3:0] v; // a vector of 4 bits v[3] is the MSB 11 | 12 | // big-endian (this looks right, but is "backwards") 13 | reg [0:3] b; // a vector of 4 bits v[0] is the MSB 14 | 15 | initial begin 16 | $dumpfile("top_tb.vcd"); 17 | $dumpvars; 18 | 19 | $display(v); // default = decimal 20 | $display("%b", v); // binary as needed based on the size of v 21 | #1; 22 | 23 | v[0] = 1; // v[0] is the LSB 24 | $display("%b %h %d", v, v, v); // note the big-X this time 25 | #1; 26 | 27 | v = 0; // can set all bits in a vector at once 28 | $display("%b %h %d", v, v, v); 29 | #1; 30 | 31 | v[3] = 1; // v[3] is the MSB 32 | $display("%b %h %d", v, v, v); 33 | #1; 34 | 35 | 36 | $display(); 37 | b = 0; 38 | $display("%b %h %d", b, b, b); 39 | #1; 40 | b[0] = 1; // b[0] is the MSB 41 | $display("%b %h %d", b, b, b); 42 | #1; 43 | b[2] = 1; 44 | $display("%b %h %d", b, b, b); 45 | #1; 46 | 47 | $display(); 48 | v = b; // what will this do? 49 | $display("v=b:"); 50 | $display("%b %h %d", v, v, v); 51 | #1; 52 | 53 | //v = b[3:0]; // this won't compile 54 | 55 | v[3:0] = { b[3], b[2], b[1], b[0] }; // {} is the concatenation operator 56 | $display("%b %h %d", v, v, v); 57 | #1; 58 | 59 | v = 0; 60 | v[3:2] = 3; // assign a range of to two bits 'd3 = 'b11 61 | $display("%b %h %d", v, v, v); 62 | 63 | #30; 64 | $finish; 65 | end 66 | 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /types/types2/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /types/types2/README.md: -------------------------------------------------------------------------------- 1 | # vectors & integer numbers 2 | 3 | ## Topics 4 | 5 | - vector 6 | - replication operator `{n{...}}` 7 | - sized integers `n'n` 8 | - based integers `'bn` 9 | - $signed() 10 | - 2's complement + and - are supported 11 | -------------------------------------------------------------------------------- /types/types3/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /types/types3/README.md: -------------------------------------------------------------------------------- 1 | # arrays 2 | 3 | ## Topics 4 | 5 | - arrays (are not vectors) 6 | - for loop 7 | - type integer 8 | -------------------------------------------------------------------------------- /types/types3/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg a [3:0]; // one array of 4 bits 8 | reg b [3:0][3:0]; // 4 arrays of 4 bits 9 | 10 | integer i; // this is used in the for loops below 11 | 12 | initial begin 13 | $dumpfile("top_tb.vcd"); 14 | //$dumpvars; // this will not dump the arrays :-( 15 | $dumpvars( 0, a[0], a[1], a[2], a[3] ); // this will warn but it is OK 16 | 17 | //a = 0; // XXX can not set all at once 18 | 19 | #1; 20 | a[0] = 1; 21 | $display(a[0], a[1], a[2], a[3]); 22 | #1; 23 | 24 | a[1] = 0; 25 | $display(a[0], a[1], a[2], a[3]); 26 | #1; 27 | 28 | a[2] = 1; 29 | a[3] = 0; 30 | $display(a[0], a[1], a[2], a[3]); 31 | 32 | #1; 33 | 34 | $display(); // skip a line 35 | 36 | //b[0] = 1; // can not set a row at once 37 | b[0][0] = 1; 38 | // we don't have a ++ :-( 39 | for (i=0; i<4; i=i+1) $display(b[i][0], b[i][1], b[i][2], b[i][3]); 40 | $display(); 41 | 42 | b[0][1] = 1; 43 | for (i=0; i<4; i=i+1) $display(b[i][0], b[i][1], b[i][2], b[i][3]); 44 | $display(); 45 | 46 | b[1][2] = 1; 47 | for (i=0; i<4; i=i+1) $display(b[i][0], b[i][1], b[i][2], b[i][3]); 48 | $display(); 49 | 50 | #30; 51 | $finish; 52 | end 53 | 54 | 55 | endmodule 56 | -------------------------------------------------------------------------------- /types/types4/Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile suitable for simulation only 2 | 3 | TOP=../.. 4 | 5 | -include $(TOP)/Make.local 6 | include $(TOP)/Make.rules 7 | 8 | .PHONY: all clean world run plot 9 | 10 | all:: run 11 | 12 | top_tb.vvp : top_tb.v $(FILES) 13 | iverilog -o $@ $^ 14 | 15 | # Run a simulation. But don't plot it. 16 | run: top_tb.vvp 17 | vvp top_tb.vvp 18 | 19 | plot: top_tb.vcd 20 | gtkwave $^ 21 | -------------------------------------------------------------------------------- /types/types4/README.md: -------------------------------------------------------------------------------- 1 | # arrays of vectors 2 | 3 | ## Topics 4 | 5 | - note: Verilog thinks of this as a memory 6 | - indexing the array and the bit-ranges of the vectors 7 | -------------------------------------------------------------------------------- /types/types4/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns/1ns 2 | 3 | `default_nettype none 4 | 5 | module tb(); 6 | 7 | reg [3:0] aa [3:0]; 8 | 9 | initial begin 10 | $dumpfile("top_tb.vcd"); 11 | //$dumpvars; // this will not dump the arrays :-( 12 | $dumpvars( 0, aa[0], aa[1], aa[2], aa[3] ); // this will warn but it is OK 13 | 14 | //aa = 0; // XXX can not set all at once 15 | 16 | #1; 17 | aa[0] = 12; // set vector 0 all at once 18 | $display("%b ", aa[0], aa[0], aa[1], aa[2], aa[3]); 19 | #1; 20 | 21 | aa[0][3] = 0; // clear the MSB of vector zero 22 | $display("%b ", aa[0], aa[0], aa[1], aa[2], aa[3]); 23 | #1; 24 | 25 | $display(); 26 | 27 | aa[2][2] = 0; // a[2] will be an upper-case X because not all bits are set 28 | $display(aa[0], aa[1], aa[2], aa[3]); 29 | #1; 30 | 31 | aa[2][0] = 1; 32 | aa[2][1] = 1; 33 | aa[2][3] = 0; 34 | $display(aa[0], aa[1], aa[2], aa[3]); 35 | 36 | #30; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | SUBDIRS= \ 4 | bars \ 5 | bars-1024x768 \ 6 | bars-640x350 \ 7 | bars-720x400 \ 8 | sync \ 9 | vdp \ 10 | vdp-1280x1024div4 \ 11 | vdp-640x480div2 12 | 13 | DOESNT_WORK= \ 14 | bars-1280x1024 \ 15 | 16 | include $(TOP)/Make.rules 17 | 18 | -------------------------------------------------------------------------------- /vga/bars-1024x768/.gitignore: -------------------------------------------------------------------------------- 1 | pll.v 2 | -------------------------------------------------------------------------------- /vga/bars-1024x768/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vgasync.v 12 | 13 | # FPGA oscillator speed 14 | OSC_CLK=25 15 | 16 | all:: top.bin 17 | 18 | top.json: $(FILES) 19 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 20 | 21 | timing: top.asc 22 | icetime -tmd $(DEVICE) $^ 23 | 24 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 25 | iverilog -o $@ $^ 26 | 27 | plot: vgasync_tb.vcd 28 | gtkwave $^ 29 | 30 | prog: top.bin 31 | $(FLASH_PROG) $^ 32 | 33 | pll.v: 34 | icepll -i 25 -o 65 -m -f $@ 35 | 36 | # extra dependancies 37 | top.asc: $(PINMAP) 38 | 39 | clean:: 40 | rm -f pll.v 41 | -------------------------------------------------------------------------------- /vga/bars-1024x768/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA 1024x768 color bars example Files 2 | 3 | This example uses a PLL to generate the 65MHZ clock required for 4 | XGA Signal 1024 x 768 @ 60 Hz timing using the parameters found 5 | at [tinyvga.com](http://tinyvga.com/vga-timing/1024x768@60Hz) 6 | 7 | 1024 x 768 @ 60 Hz timing 8 | 9 | General timing 10 | Screen refresh rate 60 Hz 11 | Vertical refresh 48.363095238095 kHz 12 | Pixel freq. 65.0 MHz 13 | 14 | Horizontal timing (line) 15 | Polarity of horizontal sync pulse is negative. 16 | 17 | Scanline part Pixels Time [µs] 18 | Visible area 1024 15.753846153846 19 | Front porch 24 0.36923076923077 20 | Sync pulse 136 2.0923076923077 21 | Back porch 160 2.4615384615385 22 | Whole line 1344 20.676923076923 23 | 24 | Vertical timing (frame) 25 | Polarity of vertical sync pulse is negative. 26 | 27 | Frame part Lines Time [ms] 28 | Visible area 768 15.879876923077 29 | Front porch 3 0.062030769230769 30 | Sync pulse 6 0.12406153846154 31 | Back porch 29 0.59963076923077 32 | Whole frame 806 16.6656 33 | 34 | 35 | 36 | The Makefile includes a recipie to generate a module with the 37 | settings we need by using the `icepll` command. 38 | 39 | Note: When using the 25MHZ reference clock found on 40 | the [2057-ICE40HX4K-TQ144-breakout](https://github.com/johnwinans/2057-ICE40HX4K-TQ144-breakout) 41 | project board, the PLL can not generate the exact frequency we want. 42 | But it can generate one close enough to work on modern video monitors. 43 | 44 | Note: Because the logic in `top.v` that determines the color bits is 45 | combinational, the way that the Verilog choses to implement it can 46 | result glitches and/or hesitations when the colors transition. 47 | (I can see a narrow vertical glitch on the left edge of my screen.) 48 | -------------------------------------------------------------------------------- /vga/bars-1024x768/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/bars-1024x768/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire clk65; 16 | wire vga_vid; 17 | wire vga_hsync; 18 | wire vga_vsync; 19 | wire [$clog2(1344)-1:0] vga_col; // big enough to hold the counter value 20 | wire [$clog2(806)-1:0] vga_row; // big enough to hold the counter value 21 | 22 | // use a PLL to generate 65MHZ from 25MHZ 23 | pll pll65 (.clock_in(clk25), .clock_out(clk65)); 24 | 25 | vgasync #( 26 | .HVID(1024), 27 | .HFP(24), 28 | .HS(136), 29 | .HBP(160), 30 | .VVID(768), 31 | .VFP(3), 32 | .VS(6), 33 | .VBP(29) 34 | ) vga ( 35 | .clk(clk65), 36 | .reset(~s1_n), 37 | .hsync(vga_hsync), 38 | .vsync(vga_vsync), 39 | .col(vga_col), 40 | .row(vga_row), 41 | .vid_active(vga_vid) 42 | ); 43 | 44 | 45 | // Note: Because the following logic is combinational, the way 46 | // that the compiler choses to implement it can cause glitches 47 | // and/or hesitations when the colors transition. 48 | 49 | 50 | // draw different patterns depending on the row 51 | assign {red,grn,blu} = vga_vid ? (( vga_row > 300) ? vga_col[8:6] : ( vga_row > 290) ? 0 : ( vga_row > 200) ? vga_col[5:3] : ( vga_row > 190) ? 0 : vga_col[2:0] ) : 0; 52 | 53 | // draw same pattern on every row 54 | // assign {red,grn,blu} = vga_vid ? vga_col[8:6] : 0; 55 | 56 | // draw full screen white 57 | // assign {red,grn,blu} = vga_vid ? {3{vga_vid}} : 0; // all three on at same time 58 | 59 | assign hsync = ~vga_hsync; // Polarity of horizontal sync pulse is negative. 60 | assign vsync = ~vga_vsync; // Polarity of vertical sync pulse is negative. 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /vga/bars-1024x768/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/.gitignore: -------------------------------------------------------------------------------- 1 | pll.v 2 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vgasync.v 12 | 13 | 14 | # FPGA oscillator speed 15 | OSC_CLK=25 16 | OSC_TARGET=108 17 | 18 | # Override the default nextpnr rule in the Make.rules file to test using the 19 | # --freq option (that I should migrate into the default rules file... I know.) 20 | %.asc : %.json 21 | $(NEXTPNR) --freq $(OSC_TARGET) --$(DEVICE) --package $(PACKAGE) --pcf $(PINMAP) --asc $@ --json $< 22 | 23 | 24 | 25 | all:: top.bin 26 | 27 | top.json: $(FILES) 28 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 29 | 30 | timing: top.asc 31 | icetime -tmd $(DEVICE) $^ 32 | 33 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 34 | iverilog -o $@ $^ 35 | 36 | plot: vgasync_tb.vcd 37 | gtkwave $^ 38 | 39 | prog: top.bin 40 | $(FLASH_PROG) $^ 41 | 42 | pll.v: 43 | icepll -i $(OSC_CLK) -o $(OSC_TARGET) -m -f $@ 44 | 45 | # extra dependancies 46 | top.asc: $(PINMAP) 47 | 48 | clean:: 49 | rm -f pll.v 50 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA 1280x1024 color bars example Files 2 | 3 | WARNING: This fails to compile into a design that can operate at 4 | the required 108MHZ due to the propagation delay in the carry chains 5 | of the row and column counters! 6 | 7 | Note that the horizontal and vertical sync pulse polarities for this mode are positive. 8 | 9 | This example uses a PLL to generate the 108MHZ clock required for 10 | VESA Signal 1280 x 1024 @ 60 Hz timing 11 | using the parameters found 12 | at [tinyvga.com](http://tinyvga.com/vga-timing/1280x1024@60Hz) 13 | 14 | The Makefile includes a recipie to generate a module with the 15 | settings we need by using the `icepll` command. 16 | 17 | Note: When using the 25MHZ reference clock found on 18 | the [2057-ICE40HX4K-TQ144-breakout](https://github.com/johnwinans/2057-ICE40HX4K-TQ144-breakout) 19 | project board, the PLL can not generate the exact frequency we want. 20 | But it can generate one close enough to work on modern video monitors. 21 | 22 | Note: This example includes an overriden recipie when running `nextpnr` 23 | in order to insert `--freq 108` for the timing assessment calculation. 24 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire clk108; 16 | wire vga_vid; 17 | wire vga_hsync; 18 | wire vga_vsync; 19 | wire [$clog2(1688)-1:0] vga_col; // big enough to hold the counter value 20 | wire [$clog2(1066)-1:0] vga_row; // big enough to hold the counter value 21 | 22 | // use a PLL to generate 65MHZ from 25MHZ 23 | pll pll108 (.clock_in(clk25), .clock_out(clk108)); 24 | 25 | vgasync #( 26 | .HVID(1280), 27 | .HFP(48), 28 | .HS(112), 29 | .HBP(248), 30 | .VVID(1024), 31 | .VFP(1), 32 | .VS(3), 33 | .VBP(38) 34 | ) vga ( 35 | .clk(clk108), 36 | .reset(~s1_n), 37 | .hsync(vga_hsync), 38 | .vsync(vga_vsync), 39 | .col(vga_col), 40 | .row(vga_row), 41 | .vid_active(vga_vid) 42 | ); 43 | 44 | 45 | // Note: Because the following logic is combinational, the way 46 | // that the compiler choses to implement it can cause glitches 47 | // and/or hesitations when the colors transition. 48 | 49 | 50 | // draw different patterns depending on the row 51 | assign {red,grn,blu} = vga_vid ? (( vga_row > 300) ? vga_col[8:6] : ( vga_row > 290) ? 0 : ( vga_row > 200) ? vga_col[5:3] : ( vga_row > 190) ? 0 : vga_col[2:0] ) : 0; 52 | 53 | // draw same pattern on every row 54 | // assign {red,grn,blu} = vga_vid ? vga_col[8:6] : 0; 55 | 56 | // draw full screen white 57 | // assign {red,grn,blu} = vga_vid ? {3{vga_vid}} : 0; // all three on at same time 58 | 59 | assign hsync = ~vga_hsync; 60 | assign vsync = vga_vsync; // the sync pulse is positive for VESA Signal 720 x 400 @ 85Hz 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /vga/bars-1280x1024/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/bars-640x350/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | vgasync.v 11 | 12 | # FPGA oscillator speed 13 | OSC_CLK=25 14 | 15 | all:: top.bin 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | timing: top.asc 21 | icetime -tmd $(DEVICE) $^ 22 | 23 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 24 | iverilog -o $@ $^ 25 | 26 | plot: vgasync_tb.vcd 27 | gtkwave $^ 28 | 29 | prog: top.bin 30 | $(FLASH_PROG) $^ 31 | 32 | # extra dependancies 33 | top.asc: $(PINMAP) 34 | -------------------------------------------------------------------------------- /vga/bars-640x350/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA color bars example Files for 640x350 @ 70HZ 2 | 3 | This directory contains files to generate color bars. 4 | 5 | This timing can be useful to render 6 | 7 | By propagating the column and row counter values out of the sync generator 8 | they can be used to generate patterns on the RGB color outputs. 9 | 10 | See: http://www.tinyvga.com/vga-timing/640x350@70Hz 11 | 12 | 640 x 350 @ 70 Hz timing 13 | 14 | General timing 15 | Screen refresh rate 70 Hz 16 | Vertical refresh 31.46875 kHz 17 | Pixel freq. 25.175 MHz 18 | Horizontal timing (line) 19 | Polarity of horizontal sync pulse is positive. 20 | 21 | Scanline part Pixels Time [µs] 22 | Visible area 640 25.422045680238 23 | Front porch 16 0.63555114200596 24 | Sync pulse 96 3.8133068520357 25 | Back porch 48 1.9066534260179 26 | Whole line 800 31.777557100298 27 | Vertical timing (frame) 28 | Polarity of vertical sync pulse is negative. 29 | 30 | Frame part Lines Time [ms] 31 | Visible area 350 11.122144985104 32 | Front porch 37 1.175769612711 33 | Sync pulse 2 0.063555114200596 34 | Back porch 60 1.9066534260179 35 | Whole frame 449 14.268123138034 36 | 37 | Note: We can not get an optimal clock speed of 25.175 from the 38 | PLL when using a 25MHZ oscillator. So this will run at 25MHZ, which 39 | I hope is close enough to work OK. 40 | 41 | 42 | 43 | 31.5MHZ is also viable. 44 | 45 | See: http://www.tinyvga.com/vga-timing/640x350@85Hz 46 | 47 | 640 x 350 @ 85 Hz timing 48 | 49 | General timing 50 | Screen refresh rate 85 Hz 51 | Vertical refresh 37.860576923077 kHz 52 | Pixel freq. 31.5 MHz 53 | Horizontal timing (line) 54 | Polarity of horizontal sync pulse is positive. 55 | 56 | Scanline part Pixels Time [µs] 57 | Visible area 640 20.31746031746 58 | Front porch 32 1.015873015873 59 | Sync pulse 64 2.031746031746 60 | Back porch 96 3.047619047619 61 | Whole line 832 26.412698412698 62 | Vertical timing (frame) 63 | Polarity of vertical sync pulse is negative. 64 | 65 | Frame part Lines Time [ms] 66 | Visible area 350 9.2444444444444 67 | Front porch 32 0.84520634920635 68 | Sync pulse 3 0.079238095238095 69 | Back porch 60 1.5847619047619 70 | Whole frame 445 11.753650793651 71 | -------------------------------------------------------------------------------- /vga/bars-640x350/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/bars-640x350/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire vga_vid; 16 | wire vga_hsync; 17 | wire vga_vsync; 18 | wire [9:0] vga_col; 19 | wire [8:0] vga_row; 20 | 21 | vgasync vga ( 22 | .clk(clk25), 23 | .reset(~s1_n), 24 | .hsync(vga_hsync), 25 | .vsync(vga_vsync), 26 | .col(vga_col), 27 | .row(vga_row), 28 | .vid_active(vga_vid) 29 | ); 30 | 31 | // draw different patterns depending on the row 32 | // assign {red,grn,blu} = vga_vid ? (( vga_row > 300) ? vga_col[8:6] : ( vga_row > 290) ? 0 : ( vga_row > 200) ? vga_col[5:3] : ( vga_row > 190) ? 0 : vga_col[2:0] ) : 0; 33 | 34 | // draw same pattern on every row 35 | assign {red,grn,blu} = vga_vid ? vga_col[8:6] : 0; 36 | 37 | // draw full screen white 38 | // assign {red,grn,blu} = vga_vid ? {3{vga_vid}} : 0; // all three on at same time 39 | 40 | // assign red = vga_vid; 41 | // assign grn = vga_vid; 42 | // assign blu = vga_vid; 43 | 44 | assign hsync = vga_hsync; // Polarity of horizontal sync pulse is positive. 45 | assign vsync = ~vga_vsync; // Polarity of vertical sync pulse is negative. 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /vga/bars-640x350/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/bars-720x400/.gitignore: -------------------------------------------------------------------------------- 1 | pll.v 2 | -------------------------------------------------------------------------------- /vga/bars-720x400/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vgasync.v 12 | 13 | # FPGA oscillator speed 14 | OSC_CLK=25 15 | 16 | all:: top.bin 17 | 18 | top.json: $(FILES) 19 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 20 | 21 | timing: top.asc 22 | icetime -tmd $(DEVICE) $^ 23 | 24 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 25 | iverilog -o $@ $^ 26 | 27 | plot: vgasync_tb.vcd 28 | gtkwave $^ 29 | 30 | prog: top.bin 31 | $(FLASH_PROG) $^ 32 | 33 | pll.v: 34 | icepll -i 25 -o 35.5 -m -f $@ 35 | 36 | # extra dependancies 37 | top.asc: $(PINMAP) 38 | 39 | clean:: 40 | rm -f pll.v 41 | -------------------------------------------------------------------------------- /vga/bars-720x400/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA 720x400 color bars example Files 2 | 3 | This resolution was designed for using 9x16 tiles for text characters. 4 | 5 | Note that the vertical sync pulse polarity for this mode is positive. 6 | 7 | This example uses a PLL to generate the 35.5MHZ clock required for 8 | VESA Signal 720 x 400 @ 85 Hz timing 9 | using the parameters found 10 | at [tinyvga.com](http://tinyvga.com/vga-timing/720x400@85Hz) 11 | 12 | The Makefile includes a recipie to generate a module with the 13 | settings we need by using the `icepll` command. 14 | 15 | Note: When using the 25MHZ reference clock found on 16 | the [2057-ICE40HX4K-TQ144-breakout](https://github.com/johnwinans/2057-ICE40HX4K-TQ144-breakout) 17 | project board, the PLL can not generate the exact frequency we want. 18 | But it can generate one close enough to work on modern video monitors. 19 | 20 | My Samsung SyncMaster 910v video monitor does not like this mode. 21 | It flashes a box on the screen suggesting the use of 1280x1024 @60Hz 22 | for optimal clarity. 23 | -------------------------------------------------------------------------------- /vga/bars-720x400/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/bars-720x400/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire clk355; 16 | wire vga_vid; 17 | wire vga_hsync; 18 | wire vga_vsync; 19 | wire [$clog2(936)-1:0] vga_col; // big enough to hold the counter value 20 | wire [$clog2(446)-1:0] vga_row; // big enough to hold the counter value 21 | 22 | // use a PLL to generate 65MHZ from 25MHZ 23 | pll pll355 (.clock_in(clk25), .clock_out(clk355)); 24 | 25 | vgasync #( 26 | .HVID(720), 27 | .HFP(36), 28 | .HS(72), 29 | .HBP(108), 30 | .VVID(400), 31 | .VFP(1), 32 | .VS(3), 33 | .VBP(42) 34 | ) vga ( 35 | .clk(clk355), 36 | .reset(~s1_n), 37 | .hsync(vga_hsync), 38 | .vsync(vga_vsync), 39 | .col(vga_col), 40 | .row(vga_row), 41 | .vid_active(vga_vid) 42 | ); 43 | 44 | 45 | // Note: Because the following logic is combinational, the way 46 | // that the compiler choses to implement it can cause glitches 47 | // and/or hesitations when the colors transition. 48 | 49 | 50 | // draw different patterns depending on the row 51 | assign {red,grn,blu} = vga_vid ? (( vga_row > 300) ? vga_col[8:6] : ( vga_row > 290) ? 0 : ( vga_row > 200) ? vga_col[5:3] : ( vga_row > 190) ? 0 : vga_col[2:0] ) : 0; 52 | 53 | // draw same pattern on every row 54 | // assign {red,grn,blu} = vga_vid ? vga_col[8:6] : 0; 55 | 56 | // draw full screen white 57 | // assign {red,grn,blu} = vga_vid ? {3{vga_vid}} : 0; // all three on at same time 58 | 59 | assign hsync = ~vga_hsync; 60 | assign vsync = vga_vsync; // the sync pulse is positive for VESA Signal 720 x 400 @ 85Hz 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /vga/bars-720x400/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/bars/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | vgasync.v 11 | 12 | # FPGA oscillator speed 13 | OSC_CLK=25 14 | 15 | all:: top.bin 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | timing: top.asc 21 | icetime -tmd $(DEVICE) $^ 22 | 23 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 24 | iverilog -o $@ $^ 25 | 26 | plot: vgasync_tb.vcd 27 | gtkwave $^ 28 | 29 | prog: top.bin 30 | $(FLASH_PROG) $^ 31 | 32 | # extra dependancies 33 | top.asc: $(PINMAP) 34 | -------------------------------------------------------------------------------- /vga/bars/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA color bars example Files 2 | 3 | This directory contains files to generate color bars. 4 | 5 | By propagating the column and row counter values out of the sync generator 6 | they can be used to generate patterns on the RGB color outputs. 7 | -------------------------------------------------------------------------------- /vga/bars/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/bars/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire vga_vid; 16 | wire vga_hsync; 17 | wire vga_vsync; 18 | wire [9:0] vga_col; // up to 639 19 | wire [8:0] vga_row; // up to 479 20 | 21 | vgasync vga ( 22 | .clk(clk25), 23 | .reset(~s1_n), 24 | .hsync(vga_hsync), 25 | .vsync(vga_vsync), 26 | .col(vga_col), 27 | .row(vga_row), 28 | .vid_active(vga_vid) 29 | ); 30 | 31 | // draw different patterns depending on the row 32 | // assign {red,grn,blu} = vga_vid ? (( vga_row > 300) ? vga_col[8:6] : ( vga_row > 290) ? 0 : ( vga_row > 200) ? vga_col[5:3] : ( vga_row > 190) ? 0 : vga_col[2:0] ) : 0; 33 | 34 | // draw same pattern on every row 35 | assign {red,grn,blu} = vga_vid ? vga_col[8:6] : 0; 36 | 37 | // draw full screen white 38 | // assign {red,grn,blu} = vga_vid ? {3{vga_vid}} : 0; // all three on at same time 39 | 40 | // assign red = vga_vid; 41 | // assign grn = vga_vid; 42 | // assign blu = vga_vid; 43 | 44 | assign hsync = ~vga_hsync; 45 | assign vsync = ~vga_vsync; 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /vga/bars/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/sync/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | vgasync.v 11 | 12 | # FPGA oscillator speed 13 | OSC_CLK=25 14 | 15 | all:: top.bin 16 | 17 | top.json: $(FILES) 18 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $^ 19 | 20 | timing: top.asc 21 | icetime -tmd $(DEVICE) $^ 22 | 23 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 24 | iverilog -o $@ $^ 25 | 26 | plot: vgasync_tb.vcd 27 | gtkwave $^ 28 | 29 | prog: top.bin 30 | $(FLASH_PROG) $^ 31 | 32 | # extra dependancies 33 | top.asc: $(PINMAP) 34 | -------------------------------------------------------------------------------- /vga/sync/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA sync example Files 2 | 3 | This directory contains files to generate VGA sync signals 4 | -------------------------------------------------------------------------------- /vga/sync/pinmap-2057.pcf: -------------------------------------------------------------------------------- 1 | set_io clk25 52 2 | 3 | set_io -pullup yes s1_n 102 4 | set_io -pullup yes s2_n 105 5 | 6 | set_io led[0] 118 7 | set_io led[1] 116 8 | set_io led[2] 115 9 | set_io led[3] 114 10 | set_io led[4] 113 11 | set_io led[5] 112 12 | set_io led[6] 110 13 | set_io led[7] 107 14 | 15 | set_io red 120 16 | set_io grn 122 17 | set_io blu 128 18 | 19 | set_io hsync 104 20 | set_io vsync 106 21 | -------------------------------------------------------------------------------- /vga/sync/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module top ( 4 | input wire clk25, 5 | input wire s1_n, 6 | input wire s2_n, 7 | output wire red, 8 | output wire grn, 9 | output wire blu, 10 | output wire hsync, 11 | output wire vsync, 12 | output wire [7:0] led 13 | ); 14 | 15 | wire vga_vid; 16 | wire vga_hsync; 17 | wire vga_vsync; 18 | 19 | vgasync vga ( 20 | .clk(clk25), 21 | .reset(~s1_n), 22 | .hsync(vga_hsync), 23 | .vsync(vga_vsync), 24 | .vid_active(vga_vid) 25 | ); 26 | 27 | assign red = vga_vid; 28 | assign grn = vga_vid; 29 | assign blu = vga_vid; 30 | assign hsync = ~vga_hsync; 31 | assign vsync = ~vga_vsync; 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /vga/sync/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/vdp-1280x1024div4/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | pll.v 3 | -------------------------------------------------------------------------------- /vga/vdp-1280x1024div4/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vdp_timing_test.v \ 12 | vdp_table_test.v \ 13 | vgasync.v 14 | 15 | DEPS=\ 16 | pinmap-2057.pcf \ 17 | rom_color.hex \ 18 | rom_name.hex \ 19 | rom_pattern.hex 20 | 21 | 22 | # FPGA oscillator speed 23 | OSC_CLK=25 24 | PX_CLK=27 25 | 26 | # FREQ is used for the timing nextpnr verification check 27 | FREQ=$(PX_CLK) 28 | 29 | all:: top.bin 30 | 31 | top.json: $(FILES) $(DEPS) 32 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $(FILES) 33 | 34 | timing: top.asc 35 | icetime -tmd $(DEVICE) $^ 36 | 37 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 38 | iverilog -o $@ $^ 39 | 40 | plot: vgasync_tb.vcd 41 | gtkwave $^ 42 | 43 | vdp_table_test_tb.vvp: vdp_table_test_tb.v vdp_table_test.v vgasync.v 44 | iverilog -o $@ $^ 45 | 46 | plotv: vdp_table_test_tb.vcd 47 | gtkwave $^ 48 | 49 | prog: top.bin 50 | $(FLASH_PROG) $^ 51 | 52 | pll.v: 53 | icepll -i $(OSC_CLK) -o $(PX_CLK) -m -f $@ 54 | 55 | # extra dependancies 56 | top.asc: $(PINMAP) 57 | 58 | clean:: 59 | rm -f pll.v 60 | -------------------------------------------------------------------------------- /vga/vdp-1280x1024div4/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA 1280x1024 with 4x4 scaled pixels 2 | 3 | Parameters can be found at [tinyvga.com](http://tinyvga.com/vga-timing/1024x768@60Hz) 4 | 5 | The pixel clock runs at 1/4 of its normal rate thus stretching every 6 | horizontal pixel out by 4:1. 7 | -------------------------------------------------------------------------------- /vga/vdp-1280x1024div4/rom_color.hex: -------------------------------------------------------------------------------- 1 | 07 46 75 23 34 45 56 67 78 89 9a ab bc cd ee ff 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 2 | -------------------------------------------------------------------------------- /vga/vdp-1280x1024div4/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /vga/vdp-640x480div2/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | pll.v 3 | -------------------------------------------------------------------------------- /vga/vdp-640x480div2/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vdp_table_test.v \ 12 | vgasync.v 13 | 14 | DEPS=\ 15 | pinmap-2057.pcf \ 16 | rom_color.hex \ 17 | rom_name.hex \ 18 | rom_pattern.hex 19 | 20 | 21 | # FPGA oscillator speed 22 | OSC_CLK=25 23 | PX_CLK=25 24 | 25 | # FREQ is used for the timing nextpnr verification check 26 | FREQ=$(PX_CLK) 27 | 28 | all:: top.bin 29 | 30 | top.json: $(FILES) $(DEPS) 31 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $(FILES) 32 | 33 | timing: top.asc 34 | icetime -tmd $(DEVICE) $^ 35 | 36 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 37 | iverilog -o $@ $^ 38 | 39 | plot: vgasync_tb.vcd 40 | gtkwave $^ 41 | 42 | vdp_table_test_tb.vvp: vdp_table_test_tb.v vdp_table_test.v vgasync.v 43 | iverilog -o $@ $^ 44 | 45 | plotv: vdp_table_test_tb.vcd 46 | gtkwave $^ 47 | 48 | prog: top.bin 49 | $(FLASH_PROG) $^ 50 | 51 | pll.v: 52 | icepll -i $(OSC_CLK) -o $(PX_CLK) -m -f $@ 53 | 54 | # extra dependancies 55 | top.asc: $(PINMAP) 56 | 57 | clean:: 58 | rm -f pll.v 59 | -------------------------------------------------------------------------------- /vga/vdp-640x480div2/README.md: -------------------------------------------------------------------------------- 1 | # ICE40 VGA 640x480 2 | 3 | Parameters can be found at [tinyvga.com](http://tinyvga.com/vga-timing/1024x768@60Hz) 4 | 5 | 6 | -------------------------------------------------------------------------------- /vga/vdp-640x480div2/rom_color.hex: -------------------------------------------------------------------------------- 1 | 07 46 75 07 34 45 56 67 78 89 9a ab bc cd ee ff 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 2 | -------------------------------------------------------------------------------- /vga/vdp-640x480div2/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HRB(2), 13 | .HFP(2), 14 | .HS(3), 15 | .HBP(4), 16 | .HLB(2), 17 | .VVID(3), 18 | .VBB(2), 19 | .VFP(4), 20 | .VS(2), 21 | .VBP(3), 22 | .VTB(2) 23 | ) uut ( 24 | .clk(clk), 25 | .reset(reset) 26 | ); 27 | 28 | initial begin 29 | $dumpfile("vgasync_tb.vcd"); 30 | $dumpvars; 31 | clk = 0; 32 | end 33 | 34 | always #1 clk = ~clk; 35 | 36 | initial begin 37 | reset = 1; 38 | #4; 39 | reset = 0; 40 | #100000; 41 | $finish; 42 | end 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /vga/vdp/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | pll.v 3 | -------------------------------------------------------------------------------- /vga/vdp/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | 3 | -include $(TOP)/Make.local 4 | include $(TOP)/Make.rules 5 | 6 | .PHONY: all clean burn world timings 7 | 8 | FILES= \ 9 | top.v \ 10 | pll.v \ 11 | vdp_timing_test.v \ 12 | vdp_table_test.v \ 13 | vgasync.v 14 | 15 | DEPS=\ 16 | pinmap-2057.pcf \ 17 | rom_color.hex \ 18 | rom_name.hex \ 19 | rom_pattern.hex 20 | 21 | 22 | # FPGA oscillator speed 23 | OSC_CLK=25 24 | #PX_CLK=65 25 | PX_CLK=16.250 26 | 27 | # FREQ is used for the timing nextpnr verification check 28 | FREQ=$(PX_CLK) 29 | 30 | all:: top.bin 31 | 32 | top.json: $(FILES) $(DEPS) 33 | $(COMPILE.v) -p "synth_ice40 -top top -json $@" $(FILES) 34 | 35 | timing: top.asc 36 | icetime -tmd $(DEVICE) $^ 37 | 38 | vgasync_tb.vvp: vgasync_tb.v vgasync.v 39 | iverilog -o $@ $^ 40 | 41 | plot: vgasync_tb.vcd 42 | gtkwave $^ 43 | 44 | vdp_table_test_tb.vvp: vdp_table_test_tb.v vdp_table_test.v vgasync.v 45 | iverilog -o $@ $^ 46 | 47 | plotv: vdp_table_test_tb.vcd 48 | gtkwave $^ 49 | 50 | prog: top.bin 51 | $(FLASH_PROG) $^ 52 | 53 | pll.v: 54 | icepll -i $(OSC_CLK) -o $(PX_CLK) -m -f $@ 55 | 56 | # extra dependancies 57 | top.asc: $(PINMAP) 58 | 59 | clean:: 60 | rm -f pll.v 61 | -------------------------------------------------------------------------------- /vga/vdp/rom_color.hex: -------------------------------------------------------------------------------- 1 | 07 46 75 23 34 45 56 67 78 89 9a ab bc cd ee ff 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 2 | -------------------------------------------------------------------------------- /vga/vdp/rom_name.hex: -------------------------------------------------------------------------------- 1 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 2 | 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 3 | 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 4 | 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 5 | 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 7 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 11 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 13 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 15 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 17 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 19 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 21 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 23 | 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 | 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 25 | -------------------------------------------------------------------------------- /vga/vdp/vgasync_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 100ns/1ps 2 | 3 | module tb(); 4 | 5 | reg clk; // pixel clock 6 | reg reset; 7 | 8 | vgasync 9 | #( 10 | // artifically small screen to make easy to see waveforms 11 | .HVID(5), 12 | .HFP(2), 13 | .HS(3), 14 | .HBP(4), 15 | .VVID(3), 16 | .VFP(1), 17 | .VS(2), 18 | .VBP(3) 19 | ) uut ( 20 | .clk(clk), 21 | .reset(reset) 22 | ); 23 | 24 | initial begin 25 | $dumpfile("vgasync_tb.vcd"); 26 | $dumpvars; 27 | clk = 0; 28 | end 29 | 30 | always #1 clk = ~clk; 31 | 32 | initial begin 33 | reset = 1; 34 | #4; 35 | reset = 0; 36 | #10000; 37 | $finish; 38 | end 39 | 40 | endmodule 41 | --------------------------------------------------------------------------------