├── README.md ├── project_0 ├── CMakeLists.txt ├── LED_top.v ├── Makefile ├── iCE40.pcf └── readme.txt ├── project_00 ├── LED_top.v ├── Makefile ├── iCE40.pcf └── readme.txt ├── project_02 ├── .project ├── LED_top.v ├── Makefile ├── blinker.v ├── iCE40.pcf └── readme.txt ├── project_03 ├── Makefile ├── PWM.v ├── PWM_top.v ├── iCE40.pcf └── readme.txt ├── project_04 ├── Makefile ├── PWM.v ├── PWM_top.v ├── counter.v ├── iCE40.pcf └── readme.txt ├── project_05 ├── LED_wave.v ├── Makefile ├── PWM_top.v ├── iCE40.pcf └── readme.txt ├── project_05_PLL ├── LED_wave.v ├── Makefile ├── PWM_top.v └── iCE40.pcf ├── project_08 ├── Makefile ├── button_top.v ├── iCE40.pcf └── readme.txt ├── project_10 ├── Makefile ├── counter.v ├── iCE40.pcf ├── servo.v └── servo_top.v ├── project_10_vga ├── Makefile ├── vga.pcf └── vga.v ├── project_17 ├── Makefile ├── iCE40.pcf ├── readme.txt ├── timing.v └── timing_top.v └── project_18 ├── Makefile ├── iCE40.pcf ├── readme.txt ├── timing.v └── timing_top.v /README.md: -------------------------------------------------------------------------------- 1 | verilog files for iCE40HX8K Breakout Board, build with IceStorm. 2 | These files are designed to be used with verilog tutorials 3 | see bottom-left here: 4 | 5 | https://embeddedmicro.com/tutorials/mojo/creating-a-project 6 | 7 | Install IceStorm: http://www.clifford.at/icestorm/ 8 | 9 | Clone the repository: 10 | 11 | git clone https://github.com/peepo/verilog_tutorials_BB 12 | 13 | Download [user guide](http://www.latticesemi.com/~/media/LatticeSemi/Documents/UserManuals/EI/EB85.pdf?document_id=50373) 14 | 15 | read pages 5-6 16 | NB: make upload uses -S to program SRAM so please remove J7 jumper and rotate 2xJ6 jumpers 17 | 18 | Build one of the examples: 19 | 20 | cd project 21 | make 22 | make upload 23 | 24 | Projects: 25 | 26 | |Project|name|brief|description| 27 | |----|----|----|----| 28 | |0|LED| 29 | |00|LED|with +out| 30 | |000|switch|tbc| 31 | |1|button|button| 32 | |2|Sync Logic|LED blink|1Hz| 33 | |3|PWM1|LEDs fade|4x, 6x with clk_50 from divider 34 | |4|PWM2|LEDs clk |8 LEDs fade in and out together ~1.5hz ?anomalous 35 | |5|PWM3|LEDs wave|8 LEDs fade in and out in sequence 12MHz 36 | |5_PLL|PWM4|LEDs PLL|8 LEDs fade in and out in sequence 25/48/96MHz 37 | |6|_tb1|testbench|basic and 38 | |7|_tb2|testbench clk|pwm for a couple of values 39 | |8|ext button|ext button|6,800Ω connects +ive to input and switch, -ive to other end 40 | |9|metastability|ext button|with debounce 41 | |10|PWM5|servo|arm swings through range: red-TP1 brown-TP3 orange-P16 42 | |10_vga|colour|VGA PLL| display bars 640x480 43 | ||Hello World|AVR|rely on AVR microcontroller in mojo, PIC is competitor 44 | ||----|--|mimas, XuLA2 have PIC18F14K50, 45 | ||SPI-|--|logipi may not have microcontroller? has spansion flash 46 | ||LogiCore|RAM|no project... 47 | |17|Timing|12Mhz|Total path delay: 84.10 ns (11.89 MHz)? 48 | |18|Timing_pipeline|12Mhz|Total path delay: 37.28 ns (26.83 MHz) 49 | |19|FSM |LEDs 2x|left_PWM & right_PWM, maybe also 5x states, ie forward.... 50 | ||Memory mapping|AVR|ibid 51 | ||SDRAM|N/A|MimasV2possibly or XuLA2 SDRAM before writing to SDcard 52 | ||Embedded processor|N/A|skipping for moment. 53 | 54 | --- 55 | 56 | please send comments, and report bugs to the current maintainer: Jonathan Chetwynd 57 | 58 | jay@peepo.com 59 | 60 | you may like these other excellent verilog tutorials: 61 | 62 | https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki 63 | 64 | https://nandland.com/verilog/tutorials/tutorial-introduction-to-verilog-for-beginners.html 65 | 66 | --- 67 | -------------------------------------------------------------------------------- /project_0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(LED 2 | 3 | ) 4 | target_link_libraries(LED 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /project_0/LED_top.v: -------------------------------------------------------------------------------- 1 | module LED_top( 2 | output [7:0]LED 3 | ); 4 | assign LED[7:1] = 7'b0; 5 | assign LED[0] = 1'b1; 6 | endmodule 7 | -------------------------------------------------------------------------------- /project_0/Makefile: -------------------------------------------------------------------------------- 1 | 2 | LED.bin: LED_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif LED.blif" LED_top.v 4 | arachne-pnr -d 8k -p iCE40.pcf LED.blif -o LED.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack LED.txt LED.bin 7 | 8 | upload: 9 | iceprog -S LED.bin 10 | 11 | clean: 12 | rm -f LED.blif LED.txt LED.ex LED.bin 13 | -------------------------------------------------------------------------------- /project_0/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | -------------------------------------------------------------------------------- /project_0/readme.txt: -------------------------------------------------------------------------------- 1 | turn LED D9 on 2 | -------------------------------------------------------------------------------- /project_00/LED_top.v: -------------------------------------------------------------------------------- 1 | module LED_top( 2 | output out, 3 | output [7:0]LED 4 | ); 5 | assign LED[7:1] = 7'b0; 6 | assign LED[0] = 1'b1; 7 | assign out = 1'b1; 8 | endmodule 9 | -------------------------------------------------------------------------------- /project_00/Makefile: -------------------------------------------------------------------------------- 1 | 2 | LED.bin: LED_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif LED.blif" LED_top.v 4 | arachne-pnr -d 8k -p iCE40.pcf LED.blif -o LED.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack LED.txt LED.bin 7 | 8 | upload: 9 | iceprog -S LED.bin 10 | 11 | clean: 12 | rm -f LED.blif LED.txt LED.ex LED.bin 13 | -------------------------------------------------------------------------------- /project_00/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # wire out: to be for switch with resistor see PULLDOWN 14 | set_io out P16 15 | -------------------------------------------------------------------------------- /project_00/readme.txt: -------------------------------------------------------------------------------- 1 | turn LED D9 on, and make P16 +ive 2 | -------------------------------------------------------------------------------- /project_02/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mojo-Demo 4 | 5 | 6 | 7 | 8 | 9 | net.sourceforge.veditor.simulateBuilder 10 | 11 | 12 | net.sourceforge.veditor.simulateBuilder.00000000Default.CleanCommand 13 | echo 'Clean' 14 | 15 | 16 | net.sourceforge.veditor.simulateBuilder.00000000Default.buildOrder 17 | 0 18 | 19 | 20 | net.sourceforge.veditor.simulateBuilder.00000000Default.command 21 | echo 'No Build Configuration Specified' 22 | 23 | 24 | net.sourceforge.veditor.simulateBuilder.00000000Default.enable 25 | false 26 | 27 | 28 | net.sourceforge.veditor.simulateBuilder.00000000Default.name 29 | Default 30 | 31 | 32 | net.sourceforge.veditor.simulateBuilder.00000000Default.parser 33 | 34 | 35 | 36 | net.sourceforge.veditor.simulateBuilder.00000000Default.workFolder 37 | 38 | 39 | 40 | 41 | 42 | 43 | net.sourceforge.veditor.HdlNature 44 | 45 | 46 | -------------------------------------------------------------------------------- /project_02/LED_top.v: -------------------------------------------------------------------------------- 1 | module LED_top( 2 | // 50MHz clock input 3 | input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | // Outputs to the 8 onboard LEDs 7 | output[7:0]LED, 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | // these signals should be high-z when not used 13 | //assign sw1 = 1'bz; 14 | //assign sw2 = 1'bz; 15 | //assign sw3 = 1'bz; 16 | 17 | assign LED[7:1] = 7'b0; 18 | 19 | 20 | 21 | blinker awesome_blinker ( 22 | .clk(clk), 23 | .rst(rst), 24 | .blink(LED[0]) 25 | ); 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /project_02/Makefile: -------------------------------------------------------------------------------- 1 | 2 | LED.bin: LED_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif LED.blif" LED_top.v blinker.v 4 | arachne-pnr -d 8k -p iCE40.pcf LED.blif -o LED.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack LED.txt LED.bin 7 | 8 | upload: 9 | iceprog -S LED.bin 10 | 11 | clean: 12 | rm -f LED.blif LED.txt LED.ex LED.bin 13 | -------------------------------------------------------------------------------- /project_02/blinker.v: -------------------------------------------------------------------------------- 1 | 2 | module blinker( 3 | input clk, 4 | input rst, 5 | output blink 6 | ); 7 | 8 | reg [24:0] counter_d, counter_q; 9 | 10 | assign blink = counter_q[24]; 11 | 12 | always @(counter_q) begin 13 | counter_d = counter_q + 1'b1; 14 | end 15 | 16 | always @(posedge clk) begin 17 | if (rst) begin 18 | counter_q <= 25'b0; 19 | end else begin 20 | counter_q <= counter_d; 21 | end 22 | end 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /project_02/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # Onboard 12Mhz oscillator 14 | set_io clk J3 15 | -------------------------------------------------------------------------------- /project_02/readme.txt: -------------------------------------------------------------------------------- 1 | blink LED D9 using 12Mhz internal oscillator 2 | -------------------------------------------------------------------------------- /project_03/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PWM.bin: PWM_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif PWM.blif" PWM_top.v PWM.v 4 | arachne-pnr -d 8k -p iCE40.pcf PWM.blif -o PWM.txt 5 | # icebox_explain PWM.txt > PWM.ex 6 | icepack PWM.txt PWM.bin 7 | 8 | upload: 9 | iceprog -S PWM.bin 10 | 11 | clean: 12 | rm -f PWM.blif PWM.txt PWM.ex PWM.bin 13 | -------------------------------------------------------------------------------- /project_03/PWM.v: -------------------------------------------------------------------------------- 1 | module pwm #(parameter CTR_LEN = 8) ( 2 | input clk, 3 | input rst, 4 | input [CTR_LEN - 1 : 0] compare, 5 | output pwm 6 | ); 7 | 8 | reg pwm_d, pwm_q; 9 | reg [CTR_LEN - 1: 0] ctr_d, ctr_q; 10 | 11 | assign pwm = pwm_q; 12 | 13 | always @(*) begin 14 | ctr_d = ctr_q + 1'b1; 15 | 16 | if (compare > ctr_q) 17 | pwm_d = 1'b1; 18 | else 19 | pwm_d = 1'b0; 20 | end 21 | 22 | always @(posedge clk) begin 23 | if (rst) begin 24 | ctr_q <= 1'b0; 25 | end else begin 26 | ctr_q <= ctr_d; 27 | end 28 | 29 | pwm_q <= pwm_d; 30 | end 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /project_03/PWM_top.v: -------------------------------------------------------------------------------- 1 | module ice40_top( 2 | // 12MHz clock input 3 | input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | // Outputs to the 8 onboard LEDs 7 | output[7:0]LED 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | genvar i; 13 | generate 14 | for (i = 0; i < 8; i=i+1) begin: pwm_gen_loop 15 | pwm #(.CTR_LEN(3)) pwm ( 16 | .rst(rst), 17 | .clk(clk), 18 | .compare(i), 19 | .pwm(LED[i]) 20 | ); 21 | end 22 | endgenerate 23 | 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /project_03/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # Onboard 12Mhz oscillator 14 | set_io clk J3 15 | -------------------------------------------------------------------------------- /project_03/readme.txt: -------------------------------------------------------------------------------- 1 | fade LEDs D9-D2 2 | -------------------------------------------------------------------------------- /project_04/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PWM.bin: PWM_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif PWM.blif" PWM_top.v PWM.v counter.v 4 | arachne-pnr -d 8k -p iCE40.pcf PWM.blif -o PWM.txt 5 | # icebox_explain PWM.txt > PWM.ex 6 | icepack PWM.txt PWM.bin 7 | 8 | upload: 9 | iceprog -S PWM.bin 10 | 11 | clean: 12 | rm -f PWM.blif PWM.txt PWM.ex PWM.bin 13 | -------------------------------------------------------------------------------- /project_04/PWM.v: -------------------------------------------------------------------------------- 1 | module pwm #(parameter CTR_LEN = 8) ( 2 | input clk, 3 | input rst, 4 | input [CTR_LEN - 1 : 0] compare, 5 | output pwm 6 | ); 7 | 8 | reg pwm_d, pwm_q; 9 | reg [CTR_LEN - 1: 0] ctr_d, ctr_q; 10 | 11 | assign pwm = pwm_q; 12 | 13 | always @(*) begin 14 | ctr_d = ctr_q + 1'b1; 15 | 16 | if (compare > ctr_q) 17 | pwm_d = 1'b1; 18 | else 19 | pwm_d = 1'b0; 20 | end 21 | 22 | always @(posedge clk) begin 23 | if (rst) begin 24 | ctr_q <= 1'b0; 25 | end else begin 26 | ctr_q <= ctr_d; 27 | end 28 | 29 | pwm_q <= pwm_d; 30 | end 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /project_04/PWM_top.v: -------------------------------------------------------------------------------- 1 | module iCE40_top( 2 | // 12MHz clock input 3 | input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | // Outputs to the 8 onboard LEDs 7 | output[7:0]LED, 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | 13 | 14 | assign LED = {8{pwm}}; 15 | 16 | wire [7:0] compare; 17 | wire pwm; 18 | 19 | counter fancyCounter ( 20 | .rst(rst), 21 | .clk(clk), 22 | .value(compare) 23 | ); 24 | 25 | pwm #(.CTR_LEN(8)) fancyPWM ( 26 | .rst(rst), 27 | .clk(clk), 28 | .compare(compare), 29 | .pwm(pwm) 30 | ); 31 | 32 | 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /project_04/counter.v: -------------------------------------------------------------------------------- 1 | module counter ( 2 | input clk, 3 | input rst, 4 | output reg [7:0] value 5 | ); 6 | 7 | reg[24:0] ctr_d, ctr_q; 8 | 9 | always @(ctr_q) begin 10 | ctr_d = ctr_q + 1'b1; 11 | 12 | if (ctr_q[24]) 13 | value = ~ctr_q[23:16]; 14 | else 15 | value = ctr_q[23:16]; 16 | 17 | end 18 | 19 | always @(posedge clk) begin 20 | if (rst) begin 21 | ctr_q <= 1'b0; 22 | end else begin 23 | ctr_q <= ctr_d; 24 | end 25 | end 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /project_04/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # Onboard 12Mhz oscillator 14 | set_io clk J3 15 | -------------------------------------------------------------------------------- /project_04/readme.txt: -------------------------------------------------------------------------------- 1 | fade & animate LEDs D9-D2 using 12Mhz internal oscillator 2 | -------------------------------------------------------------------------------- /project_05/LED_wave.v: -------------------------------------------------------------------------------- 1 | module led_wave #( 2 | parameter CTR_LEN = 25 3 | )( 4 | input wire clk, 5 | input wire rst, 6 | output reg[7:0] led 7 | ); 8 | 9 | reg[CTR_LEN-1:0] ctr_d, ctr_q = {CTR_LEN{1'b0}}; 10 | reg[3:0] i; 11 | reg[7:0] acmp; 12 | reg[8:0] result; 13 | 14 | always @(ctr_q) begin 15 | ctr_d = ctr_q + 1'b1; 16 | 17 | for (i = 0; i < 8; i = i + 1) begin 18 | result = ctr_q[CTR_LEN-1:CTR_LEN-9] + i * 8'd64; 19 | 20 | if (result[8]) 21 | acmp = ~result[7:0]; 22 | else 23 | acmp = result[7:0]; 24 | 25 | led[i] = acmp > ctr_q[7:0]; 26 | end 27 | end 28 | 29 | always @(posedge clk) begin 30 | if (rst) begin 31 | ctr_q <= {CTR_LEN{1'b0}}; 32 | end else begin 33 | ctr_q <= ctr_d; 34 | end 35 | end 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /project_05/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PWM.bin: PWM_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif PWM.blif" PWM_top.v LED_wave.v 4 | arachne-pnr -d 8k -p iCE40.pcf PWM.blif -o PWM.txt 5 | # icebox_explain PWM.txt > PWM.ex 6 | icepack PWM.txt PWM.bin 7 | 8 | upload: 9 | iceprog -S PWM.bin 10 | 11 | clean: 12 | rm -f PWM.blif PWM.txt PWM.ex PWM.bin 13 | -------------------------------------------------------------------------------- /project_05/PWM_top.v: -------------------------------------------------------------------------------- 1 | module iCE40_top( 2 | // 12MHz clock input 3 | input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | // Outputs to the 8 onboard LEDs 7 | output[7:0]LED, 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | led_wave #(.CTR_LEN(25)) wave( 13 | .rst(rst), 14 | .clk(clk), 15 | .led(LED) 16 | ); 17 | 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /project_05/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # Onboard 12Mhz oscillator 14 | set_io clk J3 15 | -------------------------------------------------------------------------------- /project_05/readme.txt: -------------------------------------------------------------------------------- 1 | fade & animate LEDs D9-D2 in wave using 12 MHz oscillator 2 | -------------------------------------------------------------------------------- /project_05_PLL/LED_wave.v: -------------------------------------------------------------------------------- 1 | module led_wave #( 2 | parameter CTR_LEN = 25 3 | )( 4 | input wire clk, 5 | input wire rst, 6 | output reg[7:0] led 7 | ); 8 | 9 | reg[CTR_LEN-1:0] ctr_d, ctr_q = {CTR_LEN{1'b0}}; 10 | reg[3:0] i; 11 | reg[7:0] acmp; 12 | reg[8:0] result; 13 | 14 | always @(ctr_q) begin 15 | ctr_d = ctr_q + 1'b1; 16 | 17 | for (i = 0; i < 8; i = i + 1) begin 18 | result = ctr_q[CTR_LEN-1:CTR_LEN-9] + i * 8'd64; 19 | 20 | if (result[8]) 21 | acmp = ~result[7:0]; 22 | else 23 | acmp = result[7:0]; 24 | 25 | led[i] = acmp > ctr_q[7:0]; 26 | end 27 | end 28 | 29 | always @(posedge clk) begin 30 | if (rst) begin 31 | ctr_q <= {CTR_LEN{1'b0}}; 32 | end else begin 33 | ctr_q <= ctr_d; 34 | end 35 | end 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /project_05_PLL/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PWM.bin: PWM_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif PWM.blif" PWM_top.v LED_wave.v 4 | arachne-pnr -d 8k -p iCE40.pcf PWM.blif -o PWM.txt 5 | # icebox_explain PWM.txt > PWM.ex 6 | icepack PWM.txt PWM.bin 7 | 8 | upload: 9 | iceprog -S PWM.bin 10 | 11 | clean: 12 | rm -f PWM.blif PWM.txt PWM.ex PWM.bin 13 | -------------------------------------------------------------------------------- /project_05_PLL/PWM_top.v: -------------------------------------------------------------------------------- 1 | module iCE40_top( 2 | // 12MHz clock input 3 | input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | // Outputs to the 8 onboard LEDs 7 | output[7:0]LED, 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | wire clk_25; 13 | 14 | //https://github.com/SubProto/icestick-vga-test/blob/master/vga.v 15 | SB_PLL40_CORE #(.FEEDBACK_PATH("SIMPLE"), 16 | .PLLOUT_SELECT("GENCLK"), 17 | .DIVR(4'b0000), 18 | // .DIVF(7'b1000010), //25Mhz 19 | .DIVF(7'b0111111), // 48/96MHz 20 | // .DIVQ(3'b101), //25Mhz 21 | // .DIVQ(3'b100), //48Mhz 22 | .DIVQ(3'b011), //96Mhz 23 | 24 | .FILTER_RANGE(3'b001), // wfm without PLL is broken 25 | ) uut ( 26 | .REFERENCECLK(clk), 27 | .PLLOUTCORE(clk_25), 28 | // .LOCK(P16), 29 | .RESETB(1'b1), 30 | .BYPASS(1'b0) 31 | ); 32 | 33 | led_wave #(.CTR_LEN(25)) wave( 34 | .rst(rst), 35 | .clk(clk_25), 36 | .led(LED) 37 | ); 38 | 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /project_05_PLL/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # Onboard 12Mhz oscillator 14 | set_io clk J3 15 | -------------------------------------------------------------------------------- /project_08/Makefile: -------------------------------------------------------------------------------- 1 | 2 | button.bin: button_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif button.blif" button_top.v 4 | arachne-pnr -d 8k -p iCE40.pcf button.blif -o button.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack button.txt button.bin 7 | 8 | upload: 9 | iceprog -S button.bin 10 | 11 | clean: 12 | rm -f button.blif button.txt button.ex button.bin 13 | -------------------------------------------------------------------------------- /project_08/button_top.v: -------------------------------------------------------------------------------- 1 | module iCE40_top( 2 | // 12MHz clock input 3 | // input clk, 4 | // Input from buttons (active low) 5 | // input [3:0]sw_n, 6 | input ext_button, 7 | // Outputs to the 8 onboard LEDs 8 | output[7:0]LED, 9 | ); 10 | 11 | assign LED[6:0] = 7'b0; 12 | assign LED[7] = ext_button; 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /project_08/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # Onboard LEDs 4 | set_io LED[0] B5 5 | set_io LED[1] B4 6 | set_io LED[2] A2 7 | set_io LED[3] A1 8 | set_io LED[4] C5 9 | set_io LED[5] C4 10 | set_io LED[6] B3 11 | set_io LED[7] C3 12 | 13 | # wire out: to be for switch with resistor see PULLDOWN 14 | set_io ext_button P16 15 | -------------------------------------------------------------------------------- /project_08/readme.txt: -------------------------------------------------------------------------------- 1 | use physical wires 6,800Ω resistor connects +TP1 to input:P16 and off-board button or switch, ground to other end. 2 | https://learn.sparkfun.com/tutorials/pull-up-resistors 3 | then, 4 | Press button to turn LED D9 on. 5 | -------------------------------------------------------------------------------- /project_10/Makefile: -------------------------------------------------------------------------------- 1 | 2 | servo.bin: servo_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif servo.blif" servo_top.v servo.v counter.v 4 | arachne-pnr -d 8k -p iCE40.pcf servo.blif -o servo.txt 5 | # icebox_explain servo.txt > servo.ex 6 | icepack servo.txt servo.bin 7 | 8 | upload: 9 | iceprog -S servo.bin 10 | 11 | clean: 12 | rm -f servo.blif servo.txt servo.ex servo.bin 13 | -------------------------------------------------------------------------------- /project_10/counter.v: -------------------------------------------------------------------------------- 1 | module counter #(parameter CTR_LEN = 27)( 2 | input clk, 3 | input rst, 4 | output reg [7:0] value 5 | ); 6 | 7 | reg[CTR_LEN-1:0] ctr_d, ctr_q; 8 | 9 | always @(ctr_q) begin 10 | ctr_d = ctr_q + 1'b1; 11 | 12 | if (ctr_q[CTR_LEN-1]) 13 | value = ~ctr_q[CTR_LEN-2:CTR_LEN-9]; 14 | else 15 | value = ctr_q[CTR_LEN-2:CTR_LEN-9]; 16 | 17 | end 18 | 19 | always @(posedge clk) begin 20 | if (rst) begin 21 | ctr_q <= 1'b0; 22 | end else begin 23 | ctr_q <= ctr_d; 24 | end 25 | end 26 | 27 | endmodule -------------------------------------------------------------------------------- /project_10/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | # wire out: to be for servo 4 | set_io servo P16 5 | 6 | # Onboard 12Mhz oscillator 7 | set_io clk J3 8 | -------------------------------------------------------------------------------- /project_10/servo.v: -------------------------------------------------------------------------------- 1 | module servo ( 2 | input clk, 3 | input rst, 4 | input [7:0] position, 5 | output servo 6 | ); 7 | 8 | reg pwm_d, pwm_q; 9 | reg [19:0] ctr_d, ctr_q; 10 | 11 | assign servo = pwm_q; 12 | 13 | always @(*) begin 14 | ctr_d = ctr_q + 1'b1; 15 | 16 | if (position + 9'd165 > ctr_q[19:8]) 17 | pwm_d = 1'b1; 18 | else 19 | pwm_d = 1'b0; 20 | end 21 | 22 | always @(posedge clk) begin 23 | if (rst) begin 24 | ctr_q <= 1'b0; 25 | end else begin 26 | ctr_q <= ctr_d; 27 | end 28 | 29 | pwm_q <= pwm_d; 30 | end 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /project_10/servo_top.v: -------------------------------------------------------------------------------- 1 | module servo_top( 2 | // 50MHz clock input 3 | input clk, 4 | // Input from reset button (active low) 5 | // input [3:0]sw_n, 6 | // pwm driver for servo 7 | output servo 8 | ); 9 | 10 | wire rst = 1'b0;//~sw_n[3]; // make reset active high 11 | 12 | wire [7:0] servo_position; 13 | 14 | wire clk_50; 15 | 16 | //https://github.com/SubProto/icestick-vga-test/blob/master/vga.v 17 | SB_PLL40_CORE #(.FEEDBACK_PATH("SIMPLE"), 18 | .PLLOUT_SELECT("GENCLK"), 19 | .DIVR(4'b0000), 20 | .DIVF(7'b1000010), //50Mhz 21 | .DIVQ(3'b100), //50Mhz 22 | 23 | .FILTER_RANGE(3'b001), // wfm without PLL is broken 24 | ) uut ( 25 | .REFERENCECLK(clk), 26 | .PLLOUTCORE(clk_50), 27 | // .LOCK(P16), 28 | .RESETB(1'b1), 29 | .BYPASS(1'b0) 30 | ); 31 | 32 | counter #(.CTR_LEN(28)) servoCounter ( 33 | .clk(clk_50), 34 | .rst(rst), 35 | .value(servo_position) 36 | ); 37 | 38 | servo myServoController ( 39 | .clk(clk_50), 40 | .rst(rst), 41 | .position(servo_position), 42 | .servo(servo) 43 | ); 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /project_10_vga/Makefile: -------------------------------------------------------------------------------- 1 | 2 | vga.bin: vga.v vga.pcf 3 | yosys -q -p "synth_ice40 -blif vga.blif" vga.v 4 | arachne-pnr -d 8k -p vga.pcf vga.blif -o vga.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack vga.txt vga.bin 7 | 8 | upload: 9 | iceprog -S vga.bin 10 | 11 | clean: 12 | rm -f vga.blif vga.txt vga.ex vga.bin 13 | -------------------------------------------------------------------------------- /project_10_vga/vga.pcf: -------------------------------------------------------------------------------- 1 | set_io b0 H16 # white 2 | set_io b1 J15 3 | set_io g0 G14 # grey 4 | set_io g1 K14 5 | set_io r0 K15 # purple 6 | set_io r1 M16 7 | set_io hsync N16 # blue 8 | set_io vsync P16 # yellow 9 | # gnd green 10 | #set_io D1 99 11 | #set_io D2 98 12 | #set_io D3 97 13 | #set_io D4 96 14 | #set_io D5 95 15 | set_io pclk J3 16 | -------------------------------------------------------------------------------- /project_10_vga/vga.v: -------------------------------------------------------------------------------- 1 | 2 | // https://github.com/SubProto/icestick-vga-test 3 | // adapted from NERP demo vga640x480.v 4 | 5 | module vga( 6 | input wire pclk, //pll clock: 25.13MHz 7 | input wire clr, //asynchronous reset 8 | output wire hsync, //horizontal sync out 9 | output wire vsync, //vertical sync out 10 | output wire r0, 11 | output wire r1, 12 | output wire g0, 13 | output wire g1, 14 | output wire b0, 15 | output wire b1, 16 | output wire D1, 17 | output wire D2, 18 | output wire D3, 19 | output wire D4, 20 | output wire D5, 21 | ); 22 | 23 | wire clk; 24 | 25 | SB_PLL40_CORE #(.FEEDBACK_PATH("SIMPLE"), 26 | .PLLOUT_SELECT("GENCLK"), 27 | .DIVR(4'b0001), 28 | .DIVF(7'b1000010), 29 | .DIVQ(3'b100), 30 | .FILTER_RANGE(3'b001), 31 | ) uut ( 32 | .REFERENCECLK(pclk), 33 | .PLLOUTCORE(clk), 34 | .LOCK(D5), 35 | .RESETB(1'b1), 36 | .BYPASS(1'b0) 37 | ); 38 | 39 | // video structure constants 40 | parameter hpixels = 800; // horizontal pixels per line 41 | parameter vlines = 521; // vertical lines per frame 42 | parameter hpulse = 96; // hsync pulse length 43 | parameter vpulse = 2; // vsync pulse length 44 | parameter hbp = 144; // end of horizontal back porch 45 | parameter hfp = 784; // beginning of horizontal front porch 46 | parameter vbp = 31; // end of vertical back porch 47 | parameter vfp = 511; // beginning of vertical front porch 48 | // active horizontal video is therefore: 784 - 144 = 640 49 | // active vertical video is therefore: 511 - 31 = 480 50 | 51 | // registers for storing the horizontal & vertical counters 52 | reg [9:0] hc; 53 | reg [9:0] vc; 54 | 55 | always @(posedge clk or posedge clr) 56 | begin 57 | // reset condition 58 | if (clr == 1) 59 | begin 60 | hc <= 0; 61 | vc <= 0; 62 | end 63 | else 64 | begin 65 | // keep counting until the end of the line 66 | if (hc < hpixels - 1) 67 | hc <= hc + 1; 68 | else 69 | // When we hit the end of the line, reset the horizontal 70 | // counter and increment the vertical counter. 71 | // If vertical counter is at the end of the frame, then 72 | // reset that one too. 73 | begin 74 | hc <= 0; 75 | if (vc < vlines - 1) 76 | vc <= vc + 1; 77 | else 78 | vc <= 0; 79 | end 80 | 81 | end 82 | end 83 | 84 | assign hsync = (hc < hpulse) ? 0:1; 85 | assign vsync = (vc < vpulse) ? 0:1; 86 | 87 | assign D1 = 0; 88 | assign D2 = 0; 89 | assign D3 = 0; 90 | assign D4 = 0; 91 | 92 | always @(hc,vc) 93 | begin 94 | // first check if we're within vertical active video range 95 | if (vc >= vbp && vc < vfp) 96 | begin 97 | // now display different colors every 80 pixels 98 | // while we're within the active horizontal range 99 | // ----------------- 100 | // display white bar 101 | if (hc >= hbp && hc < (hbp+80)) 102 | begin 103 | r0 = 1; 104 | r1 = 1; 105 | g0 = 1; 106 | g1 = 1; 107 | b0 = 1; 108 | b1 = 1; 109 | end 110 | // display yellow bar 111 | else if (hc >= (hbp+80) && hc < (hbp+160)) 112 | begin 113 | r0 = 1; 114 | r1 = 1; 115 | g0 = 1; 116 | g1 = 1; 117 | b0 = 0; 118 | b1 = 0; 119 | end 120 | // display cyan bar 121 | else if (hc >= (hbp+160) && hc < (hbp+240)) 122 | begin 123 | r0 = 0; 124 | r1 = 0; 125 | g0 = 1; 126 | g1 = 1; 127 | b0 = 1; 128 | b1 = 1; 129 | end 130 | // display green bar 131 | else if (hc >= (hbp+240) && hc < (hbp+320)) 132 | begin 133 | r0 = 0; 134 | r1 = 0; 135 | g0 = 1; 136 | g1 = 1; 137 | b0 = 0; 138 | b1 = 0; 139 | end 140 | // display magenta bar 141 | else if (hc >= (hbp+320) && hc < (hbp+400)) 142 | begin 143 | r0 = 1; 144 | r1 = 1; 145 | g0 = 0; 146 | g1 = 0; 147 | b0 = 1; 148 | b1 = 1; 149 | end 150 | // display red bar 151 | else if (hc >= (hbp+400) && hc < (hbp+480)) 152 | begin 153 | r0 = 1; 154 | r1 = 1; 155 | g0 = 0; 156 | g1 = 0; 157 | b0 = 0; 158 | b1 = 0; 159 | end 160 | // display blue bar 161 | else if (hc >= (hbp+480) && hc < (hbp+560)) 162 | begin 163 | r0 = 0; 164 | r1 = 0; 165 | g0 = 0; 166 | g1 = 0; 167 | b0 = 1; 168 | b1 = 1; 169 | end 170 | // display black bar 171 | else if (hc >= (hbp+560) && hc < (hbp+640)) 172 | begin 173 | r0 = 0; 174 | r1 = 0; 175 | g0 = 0; 176 | g1 = 0; 177 | b0 = 0; 178 | b1 = 0; 179 | end 180 | // we're outside active horizontal range so display black 181 | else 182 | begin 183 | r0 = 0; 184 | r1 = 0; 185 | g0 = 0; 186 | g1 = 0; 187 | b0 = 0; 188 | b1 = 0; 189 | end 190 | end 191 | // we're outside active vertical range so display black 192 | else 193 | begin 194 | r0 = 0; 195 | r1 = 0; 196 | g0 = 0; 197 | g1 = 0; 198 | b0 = 0; 199 | b1 = 0; 200 | end 201 | end 202 | 203 | endmodule 204 | 205 | -------------------------------------------------------------------------------- /project_17/Makefile: -------------------------------------------------------------------------------- 1 | 2 | timing.bin: timing_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif timing.blif" timing_top.v timing.v 4 | arachne-pnr -d 8k -p iCE40.pcf timing.blif -o timing.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack timing.txt timing.bin 7 | iceunpack timing.bin timing.asc 8 | icetime -mit timing.asc 9 | 10 | upload: 11 | iceprog -S timing.bin 12 | 13 | clean: 14 | rm -f timing.blif timing.txt timing.ex timing.bin timing.asc 15 | -------------------------------------------------------------------------------- /project_17/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | set_io a[0] T1 4 | set_io a[1] R2 5 | set_io a[2] R3 6 | set_io a[3] T5 7 | set_io a[4] T6 8 | set_io a[5] T7 9 | set_io a[6] T9 10 | set_io a[7] P8 11 | set_io a[8] M1 12 | 13 | set_io b[0] T10 14 | set_io b[1] T11 15 | set_io b[2] N10 16 | set_io b[3] N12 17 | set_io b[4] T13 18 | set_io b[5] T15 19 | set_io b[6] R16 20 | set_io b[7] T2 21 | set_io b[8] N2 22 | 23 | set_io c[0] T3 24 | set_io c[1] R4 25 | set_io c[2] R5 26 | set_io c[3] R6 27 | set_io c[4] T8 28 | set_io c[5] R9 29 | set_io c[6] P9 30 | set_io c[7] R10 31 | set_io c[8] P10 32 | set_io c[9] M11 33 | set_io c[10] P13 34 | set_io c[11] T14 35 | set_io c[12] T16 36 | set_io c[13] B1 37 | set_io c[14] C1 38 | set_io c[15] D1 39 | set_io c[16] E2 40 | set_io c[17] F2 41 | set_io c[18] G2 42 | set_io c[19] H2 43 | set_io c[20] J2 44 | set_io c[21] K3 45 | set_io c[22] L3 46 | set_io c[23] M2 47 | set_io c[24] N3 48 | set_io c[25] P1 49 | set_io c[26] B2 50 | set_io c[27] C2 51 | set_io c[28] D2 52 | set_io c[29] F1 53 | set_io c[30] G1 54 | set_io c[31] H1 55 | set_io c[32] R1 56 | set_io c[33] J1 57 | set_io c[34] K1 58 | set_io c[35] L1 59 | 60 | # Onboard 12Mhz oscillator 61 | set_io clk J3 62 | -------------------------------------------------------------------------------- /project_17/readme.txt: -------------------------------------------------------------------------------- 1 | timing is broken ie less than clk 12MHz: 2 | Total path delay: 84.10 ns (11.89 MHz) 3 | 4 | 5 | see Makefile 6 | -------------------------------------------------------------------------------- /project_17/timing.v: -------------------------------------------------------------------------------- 1 | 2 | module timing( 3 | input clk, 4 | input rst, 5 | input [8:0] a, 6 | input [8:0] b, 7 | output [35:0] c 8 | ); 9 | 10 | reg [8:0] a_d, a_q, b_d, b_q; 11 | reg [35:0] c_d, c_q; 12 | 13 | assign c = c_q; 14 | 15 | always @(counter_q) begin 16 | a_d = a; 17 | b_d = b; 18 | c_d = a_q * (a_q * a_q) * (a_q * a_q) * (b_q * b_q) * (b_q * b_q); 19 | end 20 | 21 | always @(posedge clk) begin 22 | a_q <= a_d; 23 | b_q <= b_d; 24 | c_q <= c_d; 25 | end 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /project_17/timing_top.v: -------------------------------------------------------------------------------- 1 | module timing_top( 2 | // 12MHz clock input 3 | input clk, 4 | input [8:0] a, 5 | input [8:0] b, 6 | output [35:0] c 7 | ); 8 | 9 | wire rst = 1'b0; 10 | 11 | timing broken ( 12 | .clk(clk), 13 | .rst(rst), 14 | .a(a), 15 | .b(b), 16 | .c(c) 17 | ); 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /project_18/Makefile: -------------------------------------------------------------------------------- 1 | 2 | timing.bin: timing_top.v iCE40.pcf 3 | yosys -q -p "synth_ice40 -blif timing.blif" timing_top.v timing.v 4 | arachne-pnr -d 8k -p iCE40.pcf timing.blif -o timing.txt 5 | # icebox_explain rot.txt > rot.ex 6 | icepack timing.txt timing.bin 7 | iceunpack timing.bin timing.asc 8 | icetime -mit timing.asc 9 | 10 | upload: 11 | iceprog -S timing.bin 12 | 13 | clean: 14 | rm -f timing.blif timing.txt timing.ex timing.bin timing.asc 15 | -------------------------------------------------------------------------------- /project_18/iCE40.pcf: -------------------------------------------------------------------------------- 1 | # User Constraint File for iCE40hx8k Breakout Board 2 | 3 | set_io a[0] T1 4 | set_io a[1] R2 5 | set_io a[2] R3 6 | set_io a[3] T5 7 | set_io a[4] T6 8 | set_io a[5] T7 9 | set_io a[6] T9 10 | set_io a[7] P8 11 | set_io a[8] M1 12 | 13 | set_io b[0] T10 14 | set_io b[1] T11 15 | set_io b[2] N10 16 | set_io b[3] N12 17 | set_io b[4] T13 18 | set_io b[5] T15 19 | set_io b[6] R16 20 | set_io b[7] T2 21 | set_io b[8] N2 22 | 23 | set_io c[0] T3 24 | set_io c[1] R4 25 | set_io c[2] R5 26 | set_io c[3] R6 27 | set_io c[4] T8 28 | set_io c[5] R9 29 | set_io c[6] P9 30 | set_io c[7] R10 31 | set_io c[8] P10 32 | set_io c[9] M11 33 | set_io c[10] P13 34 | set_io c[11] T14 35 | set_io c[12] T16 36 | set_io c[13] B1 37 | set_io c[14] C1 38 | set_io c[15] D1 39 | set_io c[16] E2 40 | set_io c[17] F2 41 | set_io c[18] G2 42 | set_io c[19] H2 43 | set_io c[20] J2 44 | set_io c[21] K3 45 | set_io c[22] L3 46 | set_io c[23] M2 47 | set_io c[24] N3 48 | set_io c[25] P1 49 | set_io c[26] B2 50 | set_io c[27] C2 51 | set_io c[28] D2 52 | set_io c[29] F1 53 | set_io c[30] G1 54 | set_io c[31] H1 55 | set_io c[32] R1 56 | set_io c[33] J1 57 | set_io c[34] K1 58 | set_io c[35] L1 59 | 60 | # Onboard 12Mhz oscillator 61 | set_io clk J3 62 | -------------------------------------------------------------------------------- /project_18/readme.txt: -------------------------------------------------------------------------------- 1 | using pipeline so timing is not broken: 2 | Total path delay: 37.28 ns (26.83 MHz) 3 | 4 | see Makefile 5 | -------------------------------------------------------------------------------- /project_18/timing.v: -------------------------------------------------------------------------------- 1 | 2 | module pipeline( 3 | input clk, 4 | input rst, 5 | input [8:0] a, 6 | input [8:0] b, 7 | output [35:0] c 8 | ); 9 | 10 | reg [8:0] a_d, a_q, b_d, b_q; 11 | reg [35:0] c_d, c_q; 12 | 13 | reg [17:0] temp1_d, temp1_q; 14 | reg [17:0] temp2_d, temp2_q; 15 | 16 | assign c = c_q; 17 | 18 | always @(counter_q) begin 19 | a_d = a; 20 | b_d = b; 21 | temp1_d = (a_q * a_q) * (a_q * a_q); 22 | temp2_d = (b_q * b_q) * (b_q * b_q); 23 | c_d = a_q * temp1_q * temp2_q; 24 | end 25 | 26 | always @(posedge clk) begin 27 | a_q <= a_d; 28 | b_q <= b_d; 29 | c_q <= c_d; 30 | temp1_q <= temp1_d; 31 | temp2_q <= temp2_d; 32 | end 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /project_18/timing_top.v: -------------------------------------------------------------------------------- 1 | module timing_top( 2 | // 12MHz clock input 3 | input clk, 4 | input [8:0] a, 5 | input [8:0] b, 6 | output [35:0] c 7 | ); 8 | 9 | wire rst = 1'b0; 10 | 11 | timing pipeline ( 12 | .clk(clk), 13 | .rst(rst), 14 | .a(a), 15 | .b(b), 16 | .c(c) 17 | ); 18 | 19 | endmodule 20 | --------------------------------------------------------------------------------