├── .gitignore ├── Makefile ├── README.md ├── main.mk ├── scripts ├── glitch.py └── requirements.txt ├── sim ├── cmd_tb.v ├── delay_tb.v ├── fifo_tb.v ├── pattern_tb.v └── top_tb.v ├── src ├── cmd.v ├── delay.v ├── fifo.v ├── fifo_sync_ram.v ├── pattern.v ├── pulse.v ├── ram_sdp.v ├── resetter.v ├── seven_seg_hex.v ├── seven_seg_mux.v ├── top.v ├── trigger.v ├── uart_defs.v ├── uart_rx.v └── uart_tx.v └── syn └── icebreaker.pcf /.gitignore: -------------------------------------------------------------------------------- 1 | *.asc 2 | *.bin 3 | *.json 4 | *.log 5 | *.rpt 6 | *.vcd 7 | obj_dir/ 8 | *_tb* 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJ = glitcher 2 | ADD_SRC = src/top.v src/cmd.v src/delay.v src/fifo.v src/fifo_sync_ram.v src/pattern.v src/pulse.v src/ram_sdp.v src/resetter.v src/trigger.v src/uart_defs.v src/uart_rx.v src/uart_tx.v src/seven_seg_hex.v src/seven_seg_mux.v 3 | ADD_CLEAN = *.vcd *_tb base.log 4 | 5 | PIN_DEF = syn/icebreaker.pcf 6 | DEVICE = up5k 7 | 8 | include main.mk 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # icebreaker-glitcher 2 | 3 | ## FPGA-based glitcher for the Icebreaker board 4 | 5 | The pinout on the board is as follows: 6 | * PMOD 1A: Seven segment displaying pulse width 7 | * PMOD 1B: Seven segment displaying delay 8 | * PMOB 2: To target board 9 | * pin 1: o_board_rx - Target rx 10 | * pin 2: o_board_tx - Target tx 11 | * pin 3: o_board_rst - Target reset, connect to the JTAG reset pin 12 | * pin 4: vout - Voltage select signal 13 | 14 | The python control script is in the scripts directory: 15 | * scripts/glitch.py 16 | -------------------------------------------------------------------------------- /main.mk: -------------------------------------------------------------------------------- 1 | 2 | all: $(PROJ).rpt $(PROJ).bin 3 | 4 | %.blif: $(ADD_SRC) $(ADD_DEPS) $(ADD_BOARD_SRC) 5 | yosys -ql $*.log -p 'synth_ice40 -top top -blif $@' $(ADD_SRC) $(ADD_BOARD_SRC) 6 | 7 | %.json: $(ADD_SRC) $(ADD_DEPS) $(ADD_BOARD_SRC) 8 | yosys -ql $*.log -p 'synth_ice40 -top top -json $@' $(ADD_SRC) $(ADD_BOARD_SRC) 9 | 10 | ifeq ($(USE_ARACHNEPNR),) 11 | %.asc: $(PIN_DEF) %.json 12 | nextpnr-ice40 --$(DEVICE) --json $(filter-out $<,$^) --package sg48 --pcf $< --asc $@ 13 | else 14 | %.asc: $(PIN_DEF) %.blif 15 | arachne-pnr -d $(subst up,,$(subst hx,,$(subst lp,,$(DEVICE)))) -o $@ -p $^ 16 | endif 17 | 18 | 19 | %.bin: %.asc 20 | icepack $< $@ 21 | 22 | %.rpt: %.asc 23 | icetime -d $(DEVICE) -mtr $@ $< 24 | 25 | %_tb: sim/%_tb.v $(ADD_SRC) $(ADD_TB_SRC) 26 | iverilog -o $@ $^ 27 | 28 | %_tb.vcd: %_tb 29 | vvp -N $< +vcd=$@ 30 | 31 | %_syn.v: %.blif 32 | yosys -p 'read_blif -wideports $^; write_verilog $@' 33 | 34 | %_syntb: sim/%_tb.v %_syn.v 35 | iverilog -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v` 36 | 37 | %_syntb.vcd: %_syntb 38 | vvp -N $< +vcd=$@ 39 | 40 | prog: $(PROJ).bin 41 | iceprog $< 42 | 43 | sudo-prog: $(PROJ).bin 44 | @echo 'Executing prog as root!!!' 45 | sudo iceprog $< 46 | 47 | clean: 48 | rm -f $(PROJ).blif $(PROJ).asc $(PROJ).rpt $(PROJ).bin $(PROJ).json $(PROJ).log $(ADD_CLEAN) 49 | 50 | .SECONDARY: 51 | .PHONY: all prog clean 52 | -------------------------------------------------------------------------------- /scripts/glitch.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to test serial devices 3 | """ 4 | 5 | import struct 6 | import time 7 | import sys 8 | import re 9 | 10 | from pylibftdi import Device, Driver, INTERFACE_B 11 | from sty import fg 12 | # cb = colour bracket, ci colour info, cv colour value, cc colour clean 13 | cc, cb, ci, cv = fg.rs, fg.da_white, fg.green, fg.yellow 14 | 15 | CMD_FPGA_RESET = b"\x00\xff" 16 | CMD_BOARD_RESET = b"\x00\xfe" 17 | CMD_GLITCH = b"\x00\xfc" 18 | 19 | passthrough = False 20 | 21 | def expect_read(dev, expected): 22 | result = b"" 23 | # Don"t attempt to read more than 10 times 24 | for i in range(0, 10): 25 | result += dev.read(len(expected)) 26 | if expected in result: 27 | # print("[=] Expected = " + repr(expected) + " got " + repr(result)) 28 | return None; 29 | 30 | print("[!] Expected = " + repr(expected) + " got " + repr(result)) 31 | raise Exception 32 | # return result 33 | 34 | 35 | def synchronize(): 36 | while True: 37 | try: 38 | # Detect baud rate 39 | board_write(b"?") 40 | 41 | # Wait for "Synchronized\r\n" 42 | expect_read(dev, b"Synchronized\r\n") 43 | 44 | # Reply "Synchronized\r\n" 45 | board_write(b"Synchronized\r\n") 46 | 47 | # Verify "Synchronized\rOK\r\n" 48 | expect_read(dev, b"Synchronized\rOK\r\n") 49 | 50 | # Set a clock rate (value doesn't matter) 51 | board_write(b"12000\r\n") 52 | 53 | # Verify OK 54 | expect_read(dev, b"12000\rOK\r\n") 55 | except Exception: 56 | reset_board() 57 | continue 58 | 59 | break 60 | print(f"{cv}Synced{cc}!") 61 | 62 | 63 | def read_address(address, length): 64 | cmd = "R {:d} {:d}\r\n".format(address, length).encode("ascii") 65 | board_write(cmd) 66 | 67 | result = b"" 68 | # Don't attempt to read more than 10 times 69 | for i in range(0, 10): 70 | result += dev.read(61) 71 | if b"\r\n" in result: 72 | break 73 | 74 | # Check if command succeeded. 75 | if b"\r0" in result: 76 | board_write(b"OK\r\n") 77 | try: 78 | expect_read(dev, b"OK\r\n") 79 | except Exception: 80 | return None 81 | else: 82 | return result 83 | 84 | return None 85 | 86 | 87 | def test_crp(): 88 | result = read_address(0, 4) 89 | if result: 90 | print("DEVICE UNLOCKED") 91 | print(repr(result)) 92 | return result 93 | 94 | print("device is locked.") 95 | return None 96 | 97 | 98 | def reset_fpga(): 99 | global passthrough 100 | print("Resetting fpga") 101 | passthrough = False 102 | dev.write(CMD_FPGA_RESET) 103 | 104 | 105 | def reset_board(): 106 | print("Resetting target") 107 | dev.write(CMD_BOARD_RESET) 108 | 109 | 110 | def glitch(): 111 | dev.write(CMD_GLITCH) 112 | 113 | 114 | def board_write(msg): 115 | # print("Writing [" + repr(msg) + "]") 116 | if not passthrough: 117 | length = struct.pack("B", len(msg)) 118 | msg = length + msg 119 | dev.write(msg) 120 | 121 | 122 | def enable_passthrough(): 123 | global passthrough 124 | passthrough = True 125 | dev.write("\x00\xfd") 126 | 127 | 128 | #8'h40: 129 | # state <= STATE_PWM; 130 | def get_cmd_pwm(pwm_value): 131 | return b"\x00\x40" + struct.pack("B", int(pwm_value, 2)) 132 | 133 | #8'h10: 134 | # state <= STATE_PATTERN0; 135 | def get_cmd_pulse_width(width): 136 | if(width < 256): 137 | return b"\x00\x10" + struct.pack("B", width) 138 | else: 139 | print("ERROR, invalid pulse_width") 140 | exit(1) 141 | 142 | #8'h11: 143 | # state <= STATE_PATTERN1; 144 | def get_cmd_pulse_cnt(cnt): 145 | if(cnt < 256): 146 | return b"\x00\x11" + struct.pack("B", cnt) 147 | else: 148 | print("ERROR, invalid pulse_cnt") 149 | exit(1) 150 | 151 | 152 | def get_cmd_delay(delay): 153 | delay0 = delay & 0xff 154 | delay1 = (delay >> 8) & 0xff 155 | delay2 = (delay >> 16) & 0xff 156 | delay3 = (delay >> 24) & 0xff 157 | delay4 = (delay >> 32) & 0xff 158 | delay5 = (delay >> 40) & 0xff 159 | delay6 = (delay >> 48) & 0xff 160 | delay7 = (delay >> 56) & 0xff 161 | 162 | result = b"\x00\x20" 163 | result += struct.pack("B", delay0) 164 | result += b"\x00\x21" 165 | result += struct.pack("B", delay1) 166 | result += b"\x00\x22" 167 | result += struct.pack("B", delay2) 168 | result += b"\x00\x23" 169 | result += struct.pack("B", delay3) 170 | result += b"\x00\x24" 171 | result += struct.pack("B", delay4) 172 | result += b"\x00\x25" 173 | result += struct.pack("B", delay5) 174 | result += b"\x00\x26" 175 | result += struct.pack("B", delay6) 176 | result += b"\x00\x27" 177 | result += struct.pack("B", delay7) 178 | return result 179 | 180 | 181 | def line_parse(s): 182 | # return everything between 0 and the \r\n, following the UU data 183 | match = re.findall(r"\$.*\r\n", s.decode("ascii"))[0] 184 | return match[1:-2] 185 | 186 | 187 | def uu_decode_line(uudata): 188 | result = uu_decode(uudata[:4]) 189 | result.append(uu_decode(uudata[4:])[0]) 190 | return result 191 | 192 | 193 | def uu_decode(uudata): 194 | data = [ord(c) for c in uudata] 195 | s0 = 0; 196 | s1 = 0; 197 | s2 = 0; 198 | 199 | s0 = ((data[0]-32)<<2) & 0xff 200 | s0 = s0 | (((data[1]-32)>>4) & 0x03) 201 | 202 | s1 = ((data[1]-32)<<4) & 0xf0 203 | s1 = s1 | (((data[2]-32)>>2) & 0x0f) 204 | 205 | s2 =((data[2]-32)<<6) & 0xC0 206 | s2 = s2 | (((data[3]-32)) & 0x3F) 207 | return [s0, s1, s2] 208 | 209 | 210 | def unlock(delay_range, width_range): 211 | for delay in delay_range: 212 | for width in width_range: 213 | sys.stdout.write(f"{cb}[{ci}width{cc}:{cv}{width:04d}{cc}, {ci}delay{cc}:{cv}{delay:04d}{cb}]{cc}\n") 214 | cmd = get_cmd_pulse_width(width) 215 | cmd += get_cmd_pulse_cnt(0) 216 | cmd += get_cmd_delay(delay) 217 | cmd += CMD_GLITCH 218 | dev.write(cmd) 219 | 220 | synchronize() 221 | 222 | crp = test_crp() 223 | if crp: 224 | return crp 225 | 226 | raise Exception("No luck") 227 | 228 | if __name__ == "__main__": 229 | with Device(mode="b", interface_select=INTERFACE_B) as dev: 230 | dev.baudrate = 115200 231 | reset_fpga() 232 | reset_board() 233 | synchronize() 234 | reset_board() 235 | 236 | unlock(delay_range=(200, 500), width_range=(10, 25)) 237 | 238 | f = open("workfile", "wb") 239 | 240 | for i in range(0, 0x8000): 241 | address = i * 4 242 | result = read_address(address, 4) 243 | if result: 244 | data = uu_decode_line(line_parse(result)) 245 | output = "[0x%06x]: " % address 246 | output += "".join(["%02X " % x for x in data]) 247 | print(output) 248 | f.write(bytearray(data)) 249 | else: 250 | print("[!!!] Error") 251 | 252 | exit(0) 253 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | pylibftdi==0.17.0 2 | sty==1.0.0b12 3 | -------------------------------------------------------------------------------- /sim/cmd_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module cmd_tb(); 4 | 5 | reg tb_clk = 1'b1; 6 | 7 | wire tb_uart; 8 | 9 | cmd tb_cmd ( 10 | .clk(tb_clk), 11 | .din(tb_uart) 12 | ); 13 | 14 | initial 15 | begin 16 | $dumpfile("cmd_tb.vcd"); 17 | $dumpvars(0, cmd_tb); 18 | end 19 | 20 | always 21 | begin 22 | #41.6 tb_clk <= ~tb_clk; 23 | end 24 | 25 | reg [7:0] tx_data; 26 | reg tx_en = 1'b0; 27 | wire tx_rdy; 28 | 29 | uart_tx txi ( 30 | .clk(tb_clk), 31 | .rst(1'b0), 32 | .dout(tb_uart), 33 | .data_in(tx_data), 34 | .en(tx_en), 35 | .rdy(tx_rdy) 36 | ); 37 | 38 | initial 39 | begin 40 | // Reset 41 | #1000; 42 | @(posedge tb_clk); 43 | // -- cmd 44 | tx_data <= 8'h00; 45 | tx_en <= 1'b1; 46 | @(posedge tb_clk); 47 | tx_en <= 1'b0; 48 | wait(!tx_rdy); 49 | @(posedge tb_clk); 50 | wait(tx_rdy); 51 | @(posedge tb_clk); 52 | // -- cmd reset 53 | tx_data <= 8'hff; 54 | tx_en <= 1'b1; 55 | @(posedge tb_clk); 56 | tx_en <= 1'b0; 57 | wait(!tx_rdy); 58 | @(posedge tb_clk); 59 | wait(tx_rdy); 60 | 61 | // Check rst ok 62 | #1000 63 | @(posedge tb_clk); 64 | // -- 5 bytes of data 65 | tx_data <= 8'd5; 66 | tx_en <= 1'b1; 67 | @(posedge tb_clk); 68 | tx_en <= 1'b0; 69 | wait(!tx_rdy); 70 | @(posedge tb_clk); 71 | wait(tx_rdy); 72 | 73 | @(posedge tb_clk); 74 | tx_data <= 8'haa; 75 | tx_en <= 1'b1; 76 | @(posedge tb_clk); 77 | tx_en <= 1'b0; 78 | wait(!tx_rdy); 79 | @(posedge tb_clk); 80 | wait(tx_rdy); 81 | @(posedge tb_clk); 82 | tx_data <= 8'h55; 83 | tx_en <= 1'b1; 84 | @(posedge tb_clk); 85 | tx_en <= 1'b0; 86 | wait(!tx_rdy); 87 | @(posedge tb_clk); 88 | wait(tx_rdy); 89 | @(posedge tb_clk); 90 | tx_data <= 8'h00; 91 | tx_en <= 1'b1; 92 | @(posedge tb_clk); 93 | tx_en <= 1'b0; 94 | wait(!tx_rdy); 95 | @(posedge tb_clk); 96 | wait(tx_rdy); 97 | @(posedge tb_clk); 98 | tx_data <= 8'hff; 99 | tx_en <= 1'b1; 100 | @(posedge tb_clk); 101 | tx_en <= 1'b0; 102 | wait(!tx_rdy); 103 | @(posedge tb_clk); 104 | wait(tx_rdy); 105 | @(posedge tb_clk); 106 | tx_data <= 8'hf0; 107 | tx_en <= 1'b1; 108 | @(posedge tb_clk); 109 | tx_en <= 1'b0; 110 | wait(!tx_rdy); 111 | @(posedge tb_clk); 112 | wait(tx_rdy); 113 | 114 | // Send data ok 115 | 116 | // Set pulse width 117 | #100000; 118 | @(posedge tb_clk); 119 | // -- cmd 120 | tx_data <= 8'h00; 121 | tx_en <= 1'b1; 122 | @(posedge tb_clk); 123 | tx_en <= 1'b0; 124 | wait(!tx_rdy); 125 | @(posedge tb_clk); 126 | wait(tx_rdy); 127 | @(posedge tb_clk); 128 | // -- cmd pulse width 129 | tx_data <= 8'h10; 130 | tx_en <= 1'b1; 131 | @(posedge tb_clk); 132 | tx_en <= 1'b0; 133 | wait(!tx_rdy); 134 | @(posedge tb_clk); 135 | wait(tx_rdy); 136 | @(posedge tb_clk); 137 | // -- pulse width 0xAA 138 | tx_data <= 8'haa; 139 | tx_en <= 1'b1; 140 | @(posedge tb_clk); 141 | tx_en <= 1'b0; 142 | wait(!tx_rdy); 143 | @(posedge tb_clk); 144 | 145 | // Set pattern ok 146 | 147 | #100000; 148 | @(posedge tb_clk); 149 | // -- cmd 150 | tx_data <= 8'h00; 151 | tx_en <= 1'b1; 152 | @(posedge tb_clk); 153 | tx_en <= 1'b0; 154 | wait(!tx_rdy); 155 | @(posedge tb_clk); 156 | wait(tx_rdy); 157 | @(posedge tb_clk); 158 | // -- cmd pulse count 159 | tx_data <= 8'h11; 160 | tx_en <= 1'b1; 161 | @(posedge tb_clk); 162 | tx_en <= 1'b0; 163 | wait(!tx_rdy); 164 | @(posedge tb_clk); 165 | wait(tx_rdy); 166 | @(posedge tb_clk); 167 | // -- pulse count 0x55 168 | tx_data <= 8'h55; 169 | tx_en <= 1'b1; 170 | @(posedge tb_clk); 171 | tx_en <= 1'b0; 172 | wait(!tx_rdy); 173 | @(posedge tb_clk); 174 | wait(tx_rdy); 175 | @(posedge tb_clk); 176 | 177 | #80000 $finish; 178 | end 179 | 180 | endmodule 181 | -------------------------------------------------------------------------------- /sim/delay_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module delay_tb(); 4 | 5 | reg tb_clk = 1'b1; 6 | reg tb_en = 1'b0; 7 | 8 | delay tb_delay ( 9 | .clk(tb_clk), 10 | .rst(1'b0), 11 | .en(tb_en), 12 | .delay(64'd99) 13 | ); 14 | 15 | initial 16 | begin 17 | $dumpfile("delay_tb.vcd"); 18 | $dumpvars(0, delay_tb); 19 | end 20 | 21 | always 22 | begin 23 | #41.6 tb_clk <= ~tb_clk; 24 | end 25 | 26 | initial 27 | begin 28 | #800 tb_en <= 1'b1; 29 | #80 tb_en <= 1'b0; 30 | 31 | #10000 $finish; 32 | end 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /sim/fifo_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module fifo_tb(); 4 | 5 | reg tb_clk = 1'b1; 6 | reg tb_rst = 1'b0; 7 | reg tb_wen = 1'b0; 8 | reg tb_ren = 1'b0; 9 | reg [7:0] tb_data = 8'haa; 10 | 11 | fifo tb_fifo ( 12 | .clk(tb_clk), 13 | .rst(tb_rst), 14 | .data_in(tb_data), 15 | .wen(tb_wen), 16 | .ren(tb_ren) 17 | ); 18 | 19 | initial 20 | begin 21 | $dumpfile("fifo_tb.vcd"); 22 | $dumpvars(0, fifo_tb); 23 | end 24 | 25 | always 26 | begin 27 | #41.6 tb_clk <= ~tb_clk; 28 | end 29 | 30 | initial 31 | begin 32 | #800 ; 33 | @(posedge tb_clk); 34 | tb_rst <= 1'b1; 35 | @(posedge tb_clk); 36 | tb_rst <= 1'b0; 37 | #800 ; 38 | @(posedge tb_clk); 39 | tb_wen <= 1'b1; 40 | @(posedge tb_clk); 41 | tb_wen <= 1'b0; 42 | #800 ; 43 | @(posedge tb_clk); 44 | tb_ren <= 1'b1; 45 | @(posedge tb_clk); 46 | tb_ren <= 1'b0; 47 | 48 | #800 $finish; 49 | end 50 | 51 | endmodule 52 | -------------------------------------------------------------------------------- /sim/pattern_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module pattern_tb(); 4 | 5 | reg tb_clk = 1'b1; 6 | reg tb_en = 1'b0; 7 | reg tb_rst = 1'b0; 8 | reg [7:0] tb_data = 8'h55; 9 | 10 | wire rdy; 11 | 12 | pattern tb_pattern ( 13 | .clk(tb_clk), 14 | .rst(tb_rst), 15 | .en(tb_en), 16 | .pattern(tb_data), 17 | .pattern_cnt(8'd0), 18 | .rdy(rdy) 19 | ); 20 | 21 | initial 22 | begin 23 | $dumpfile("pattern_tb.vcd"); 24 | $dumpvars(0, pattern_tb); 25 | end 26 | 27 | always 28 | begin 29 | #41.6 tb_clk <= ~tb_clk; 30 | end 31 | 32 | initial 33 | begin 34 | #200 tb_rst <= 1'b1; 35 | #10 tb_rst <= 1'b0; 36 | #100 tb_en <= 1'b1; 37 | #10 tb_en <= 1'b0; 38 | @(posedge tb_clk); 39 | wait(rdy); 40 | @(posedge tb_clk); 41 | tb_en <= 1'b1; 42 | tb_data <= 8'haa; 43 | @(posedge tb_clk); 44 | tb_en <= 1'b0; 45 | 46 | #100 $finish; 47 | end 48 | 49 | endmodule 50 | -------------------------------------------------------------------------------- /sim/top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module top_tb(); 4 | 5 | reg tb_clk = 1'b1; 6 | 7 | wire tb_uart; 8 | wire board_rst; 9 | 10 | top tb_top ( 11 | .ext_clk(tb_clk), 12 | .ftdi_rx(tb_uart), 13 | .o_board_rst(board_rst) 14 | ); 15 | 16 | initial 17 | begin 18 | $dumpfile("top_tb.vcd"); 19 | $dumpvars(0, top_tb); 20 | end 21 | 22 | always 23 | begin 24 | #41.6 tb_clk <= ~tb_clk; 25 | end 26 | 27 | reg [7:0] tx_data; 28 | reg tx_en = 1'b0; 29 | wire tx_rdy; 30 | 31 | uart_tx txi ( 32 | .clk(tb_clk), 33 | .rst(1'b0), 34 | .dout(tb_uart), 35 | .data_in(tx_data), 36 | .en(tx_en), 37 | .rdy(tx_rdy) 38 | ); 39 | 40 | initial 41 | begin 42 | // Reset FPGA 43 | #1000; 44 | @(posedge tb_clk); 45 | // -- cmd 46 | tx_data <= 8'h00; 47 | tx_en <= 1'b1; 48 | @(posedge tb_clk); 49 | tx_en <= 1'b0; 50 | wait(!tx_rdy); 51 | @(posedge tb_clk); 52 | wait(tx_rdy); 53 | @(posedge tb_clk); 54 | // -- cmd rst 55 | tx_data <= 8'hff; 56 | tx_en <= 1'b1; 57 | @(posedge tb_clk); 58 | tx_en <= 1'b0; 59 | wait(!tx_rdy); 60 | @(posedge tb_clk); 61 | wait(tx_rdy); 62 | 63 | // Reset the target board 64 | #1000; 65 | @(posedge tb_clk); 66 | // -- cmd 67 | tx_data <= 8'h00; 68 | tx_en <= 1'b1; 69 | @(posedge tb_clk); 70 | tx_en <= 1'b0; 71 | wait(!tx_rdy); 72 | @(posedge tb_clk); 73 | wait(tx_rdy); 74 | @(posedge tb_clk); 75 | // -- cmd rst board 76 | tx_data <= 8'hfe; 77 | tx_en <= 1'b1; 78 | @(posedge tb_clk); 79 | tx_en <= 1'b0; 80 | wait(!tx_rdy); 81 | @(posedge tb_clk); 82 | wait(tx_rdy); 83 | 84 | // Configure width 85 | #1000 86 | @(posedge tb_clk); 87 | // -- cmd 88 | tx_data <= 8'h00; 89 | tx_en <= 1'b1; 90 | @(posedge tb_clk); 91 | tx_en <= 1'b0; 92 | wait(!tx_rdy); 93 | @(posedge tb_clk); 94 | wait(tx_rdy); 95 | @(posedge tb_clk); 96 | // -- cmd width 97 | tx_data <= 8'h10; 98 | tx_en <= 1'b1; 99 | @(posedge tb_clk); 100 | tx_en <= 1'b0; 101 | wait(!tx_rdy); 102 | @(posedge tb_clk); 103 | wait(tx_rdy); 104 | @(posedge tb_clk); 105 | // -- width value 106 | tx_data <= 8'h02; 107 | tx_en <= 1'b1; 108 | @(posedge tb_clk); 109 | tx_en <= 1'b0; 110 | wait(!tx_rdy); 111 | @(posedge tb_clk); 112 | wait(tx_rdy); 113 | @(posedge tb_clk); 114 | 115 | // Configure pulse count 116 | #1000 117 | @(posedge tb_clk); 118 | // -- cmd 119 | tx_data <= 8'h00; 120 | tx_en <= 1'b1; 121 | @(posedge tb_clk); 122 | tx_en <= 1'b0; 123 | wait(!tx_rdy); 124 | @(posedge tb_clk); 125 | wait(tx_rdy); 126 | @(posedge tb_clk); 127 | // -- cmd pulse count 128 | tx_data <= 8'h11; 129 | tx_en <= 1'b1; 130 | @(posedge tb_clk); 131 | tx_en <= 1'b0; 132 | wait(!tx_rdy); 133 | @(posedge tb_clk); 134 | wait(tx_rdy); 135 | @(posedge tb_clk); 136 | // -- pulse count 0 137 | tx_data <= 8'h00; 138 | tx_en <= 1'b1; 139 | @(posedge tb_clk); 140 | tx_en <= 1'b0; 141 | wait(!tx_rdy); 142 | @(posedge tb_clk); 143 | wait(tx_rdy); 144 | @(posedge tb_clk); 145 | 146 | // Configure delay count (We should set each byte irl) 147 | #1000 148 | @(posedge tb_clk); 149 | // -- cmd 150 | tx_data <= 8'h00; 151 | tx_en <= 1'b1; 152 | @(posedge tb_clk); 153 | tx_en <= 1'b0; 154 | wait(!tx_rdy); 155 | @(posedge tb_clk); 156 | wait(tx_rdy); 157 | @(posedge tb_clk); 158 | // -- cmd delay0 159 | tx_data <= 8'h20; 160 | tx_en <= 1'b1; 161 | @(posedge tb_clk); 162 | tx_en <= 1'b0; 163 | wait(!tx_rdy); 164 | @(posedge tb_clk); 165 | wait(tx_rdy); 166 | @(posedge tb_clk); 167 | // -- delay 200 168 | tx_data <= 8'd200; 169 | tx_en <= 1'b1; 170 | @(posedge tb_clk); 171 | tx_en <= 1'b0; 172 | wait(!tx_rdy); 173 | @(posedge tb_clk); 174 | wait(tx_rdy); 175 | @(posedge tb_clk); 176 | 177 | // Enable glitch 178 | @(posedge tb_clk); 179 | // -- cmd 180 | tx_data <= 8'h00; 181 | tx_en <= 1'b1; 182 | @(posedge tb_clk); 183 | tx_en <= 1'b0; 184 | wait(!tx_rdy); 185 | @(posedge tb_clk); 186 | wait(tx_rdy); 187 | @(posedge tb_clk); 188 | //-- cmd glitch enable 189 | tx_data <= 8'hfc; 190 | tx_en <= 1'b1; 191 | @(posedge tb_clk); 192 | tx_en <= 1'b0; 193 | wait(!tx_rdy); 194 | @(posedge tb_clk); 195 | wait(tx_rdy); 196 | 197 | // send "?" through 198 | #1000 199 | @(posedge tb_clk); 200 | // -- length 1 201 | tx_data <= 8'h01; 202 | tx_en <= 1'b1; 203 | @(posedge tb_clk); 204 | tx_en <= 1'b0; 205 | wait(!tx_rdy); 206 | @(posedge tb_clk); 207 | wait(tx_rdy); 208 | 209 | @(posedge tb_clk); 210 | tx_data <= 8'h3f; // '?' 211 | tx_en <= 1'b1; 212 | @(posedge tb_clk); 213 | tx_en <= 1'b0; 214 | wait(!tx_rdy); 215 | @(posedge tb_clk); 216 | wait(tx_rdy); 217 | 218 | // send "Synchronized\r\n" through 219 | #1000 220 | @(posedge tb_clk); 221 | // -- length 14 222 | tx_data <= 8'h0e; 223 | tx_en <= 1'b1; 224 | @(posedge tb_clk); 225 | tx_en <= 1'b0; 226 | wait(!tx_rdy); 227 | @(posedge tb_clk); 228 | wait(tx_rdy); 229 | 230 | @(posedge tb_clk); 231 | tx_data <= 8'h53; // 'S' 232 | tx_en <= 1'b1; 233 | @(posedge tb_clk); 234 | tx_en <= 1'b0; 235 | wait(!tx_rdy); 236 | @(posedge tb_clk); 237 | wait(tx_rdy); 238 | 239 | @(posedge tb_clk); 240 | tx_data <= 8'h79; // 'y' 241 | tx_en <= 1'b1; 242 | @(posedge tb_clk); 243 | tx_en <= 1'b0; 244 | wait(!tx_rdy); 245 | @(posedge tb_clk); 246 | wait(tx_rdy); 247 | 248 | @(posedge tb_clk); 249 | tx_data <= 8'h6e; // 'n' 250 | tx_en <= 1'b1; 251 | @(posedge tb_clk); 252 | tx_en <= 1'b0; 253 | wait(!tx_rdy); 254 | @(posedge tb_clk); 255 | wait(tx_rdy); 256 | 257 | @(posedge tb_clk); 258 | tx_data <= 8'h63; // 'c' 259 | tx_en <= 1'b1; 260 | @(posedge tb_clk); 261 | tx_en <= 1'b0; 262 | wait(!tx_rdy); 263 | @(posedge tb_clk); 264 | wait(tx_rdy); 265 | 266 | @(posedge tb_clk); 267 | tx_data <= 8'h68; // 'h' 268 | tx_en <= 1'b1; 269 | @(posedge tb_clk); 270 | tx_en <= 1'b0; 271 | wait(!tx_rdy); 272 | @(posedge tb_clk); 273 | wait(tx_rdy); 274 | 275 | @(posedge tb_clk); 276 | tx_data <= 8'h72; // 'r' 277 | tx_en <= 1'b1; 278 | @(posedge tb_clk); 279 | tx_en <= 1'b0; 280 | wait(!tx_rdy); 281 | @(posedge tb_clk); 282 | wait(tx_rdy); 283 | 284 | @(posedge tb_clk); 285 | tx_data <= 8'h6f; // 'o' 286 | tx_en <= 1'b1; 287 | @(posedge tb_clk); 288 | tx_en <= 1'b0; 289 | wait(!tx_rdy); 290 | @(posedge tb_clk); 291 | wait(tx_rdy); 292 | 293 | @(posedge tb_clk); 294 | tx_data <= 8'h6e; // 'n' 295 | tx_en <= 1'b1; 296 | @(posedge tb_clk); 297 | tx_en <= 1'b0; 298 | wait(!tx_rdy); 299 | @(posedge tb_clk); 300 | wait(tx_rdy); 301 | 302 | @(posedge tb_clk); 303 | tx_data <= 8'h69; // 'i' 304 | tx_en <= 1'b1; 305 | @(posedge tb_clk); 306 | tx_en <= 1'b0; 307 | wait(!tx_rdy); 308 | @(posedge tb_clk); 309 | wait(tx_rdy); 310 | 311 | @(posedge tb_clk); 312 | tx_data <= 8'h7a; // 'z' 313 | tx_en <= 1'b1; 314 | @(posedge tb_clk); 315 | tx_en <= 1'b0; 316 | wait(!tx_rdy); 317 | @(posedge tb_clk); 318 | wait(tx_rdy); 319 | 320 | @(posedge tb_clk); 321 | tx_data <= 8'h65; // 'e' 322 | tx_en <= 1'b1; 323 | @(posedge tb_clk); 324 | tx_en <= 1'b0; 325 | wait(!tx_rdy); 326 | @(posedge tb_clk); 327 | wait(tx_rdy); 328 | 329 | @(posedge tb_clk); 330 | tx_data <= 8'h64; // 'd' 331 | tx_en <= 1'b1; 332 | @(posedge tb_clk); 333 | tx_en <= 1'b0; 334 | wait(!tx_rdy); 335 | @(posedge tb_clk); 336 | wait(tx_rdy); 337 | 338 | @(posedge tb_clk); 339 | tx_data <= 8'h0d; // '\r' 340 | tx_en <= 1'b1; 341 | @(posedge tb_clk); 342 | tx_en <= 1'b0; 343 | wait(!tx_rdy); 344 | @(posedge tb_clk); 345 | wait(tx_rdy); 346 | 347 | @(posedge tb_clk); 348 | tx_data <= 8'h0a; // '\n' 349 | tx_en <= 1'b1; 350 | @(posedge tb_clk); 351 | tx_en <= 1'b0; 352 | wait(!tx_rdy); 353 | @(posedge tb_clk); 354 | wait(tx_rdy); 355 | 356 | // Reset board 357 | @(posedge tb_clk); 358 | // -- cmd 359 | tx_data <= 8'h00; 360 | tx_en <= 1'b1; 361 | @(posedge tb_clk); 362 | tx_en <= 1'b0; 363 | wait(!tx_rdy); 364 | @(posedge tb_clk); 365 | wait(tx_rdy); 366 | @(posedge tb_clk); 367 | //-- cmd board reset 368 | tx_data <= 8'hfe; 369 | tx_en <= 1'b1; 370 | @(posedge tb_clk); 371 | tx_en <= 1'b0; 372 | wait(!tx_rdy); 373 | @(posedge tb_clk); 374 | wait(tx_rdy); 375 | 376 | // Glitch enable 377 | @(posedge tb_clk); 378 | // -- cmd 379 | tx_data <= 8'h00; 380 | tx_en <= 1'b1; 381 | @(posedge tb_clk); 382 | tx_en <= 1'b0; 383 | wait(!tx_rdy); 384 | @(posedge tb_clk); 385 | wait(tx_rdy); 386 | @(posedge tb_clk); 387 | //-- cmd glith enable 388 | tx_data <= 8'hfc; 389 | tx_en <= 1'b1; 390 | @(posedge tb_clk); 391 | tx_en <= 1'b0; 392 | wait(!tx_rdy); 393 | @(posedge tb_clk); 394 | wait(tx_rdy); 395 | 396 | wait(board_rst); 397 | #80000 $finish; 398 | end 399 | 400 | endmodule 401 | -------------------------------------------------------------------------------- /src/cmd.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module cmd ( 35 | input wire clk, 36 | input wire din, 37 | output reg rst = 1'b0, 38 | output reg board_rst = 1'b0, 39 | output reg [7:0] pulse_width = 8'd0, 40 | output reg [7:0] pulse_cnt = 8'd0, 41 | output reg [63:0] delay = 64'd0, 42 | output reg [7:0] pwm = 8'hff, 43 | output reg glitch_en = 1'b0, 44 | output reg passthrough = 1'b0, 45 | output wire dout 46 | ); 47 | 48 | parameter [3:0] STATE_IDLE = 4'h0; 49 | parameter [3:0] STATE_SPECIAL = 4'h1; 50 | parameter [3:0] STATE_DATA = 4'h2; 51 | parameter [3:0] STATE_DELAY0 = 4'h3; 52 | parameter [3:0] STATE_DELAY1 = 4'h4; 53 | parameter [3:0] STATE_DELAY2 = 4'h5; 54 | parameter [3:0] STATE_DELAY3 = 4'h6; 55 | parameter [3:0] STATE_DELAY4 = 4'h7; 56 | parameter [3:0] STATE_DELAY5 = 4'h8; 57 | parameter [3:0] STATE_DELAY6 = 4'h9; 58 | parameter [3:0] STATE_DELAY7 = 4'hA; 59 | parameter [3:0] STATE_PULSE_WIDTH = 4'hB; 60 | parameter [3:0] STATE_PULSE_CNT = 4'hC; 61 | parameter [3:0] STATE_PWM = 4'hD; 62 | 63 | reg [3:0] state = STATE_IDLE; 64 | 65 | wire [7:0] rx_data; 66 | wire rx_valid; 67 | 68 | uart_rx rxi ( 69 | .clk(clk), 70 | .rst(rst), 71 | .din(din), 72 | .data_out(rx_data), 73 | .valid(rx_valid) 74 | ); 75 | 76 | wire tx_en; 77 | wire [7:0] tx_data; 78 | wire tx_rdy; 79 | 80 | uart_tx txi ( 81 | .clk(clk), 82 | .rst(rst), 83 | .dout(dout), 84 | .data_in(tx_data), 85 | .en(!fifo_empty), 86 | .rdy(tx_rdy) 87 | ); 88 | 89 | reg fifo_en = 1'b0; 90 | reg [7:0] fifo_data; 91 | wire fifo_empty; 92 | 93 | fifo fifoi ( 94 | .clk(clk), 95 | .rst(rst), 96 | .data_in(fifo_data), 97 | .wen(fifo_en), 98 | .ren(tx_rdy), 99 | .empty(fifo_empty), 100 | .data_out(tx_data) 101 | ); 102 | 103 | reg [7:0] byte_cnt = 8'd0; 104 | 105 | always @(posedge clk) 106 | begin 107 | rst <= 1'b0; 108 | 109 | if(rst) 110 | begin 111 | state <= STATE_IDLE; 112 | pulse_width <= 8'd0; 113 | pulse_cnt <= 8'd0; 114 | delay <= 64'd0; 115 | pwm <= 8'hff; 116 | passthrough <= 1'b0; 117 | end 118 | else begin 119 | state <= state; 120 | glitch_en <= 1'b0; 121 | byte_cnt <= byte_cnt; 122 | fifo_data <= fifo_data; 123 | fifo_en <= 1'b0; 124 | board_rst <= 1'b0; 125 | passthrough <= passthrough; 126 | 127 | case(state) 128 | STATE_IDLE: 129 | begin 130 | if(rx_valid) 131 | begin 132 | state <= STATE_DATA; 133 | byte_cnt <= rx_data; 134 | if(rx_data == 8'h00) 135 | begin 136 | state <= STATE_SPECIAL; 137 | end 138 | end 139 | end 140 | STATE_SPECIAL: 141 | begin 142 | if(rx_valid) 143 | begin 144 | state <= STATE_IDLE; 145 | case(rx_data) 146 | 8'h10: 147 | begin 148 | state <= STATE_PULSE_WIDTH; 149 | end 150 | 8'h11: 151 | begin 152 | state <= STATE_PULSE_CNT; 153 | end 154 | 8'h20: 155 | begin 156 | state <= STATE_DELAY0; 157 | end 158 | 8'h21: 159 | begin 160 | state <= STATE_DELAY1; 161 | end 162 | 8'h22: 163 | begin 164 | state <= STATE_DELAY2; 165 | end 166 | 8'h23: 167 | begin 168 | state <= STATE_DELAY3; 169 | end 170 | 8'h24: 171 | begin 172 | state <= STATE_DELAY4; 173 | end 174 | 8'h25: 175 | begin 176 | state <= STATE_DELAY5; 177 | end 178 | 8'h26: 179 | begin 180 | state <= STATE_DELAY6; 181 | end 182 | 8'h27: 183 | begin 184 | state <= STATE_DELAY7; 185 | end 186 | 8'h40: 187 | begin 188 | state <= STATE_PWM; 189 | end 190 | 8'hfc: 191 | begin 192 | glitch_en <= 1'b1; 193 | end 194 | 8'hfd: 195 | begin 196 | passthrough <= 1'b1; 197 | end 198 | 8'hfe: 199 | begin 200 | board_rst <= 1'b1; 201 | end 202 | 8'hff: 203 | begin 204 | rst <= 1'b1; 205 | end 206 | default: 207 | $display ("cmd: Invalid command byte 0x%X", rx_data); 208 | endcase 209 | end 210 | end 211 | STATE_DATA: 212 | begin 213 | if(rx_valid) 214 | begin 215 | byte_cnt <= byte_cnt - 1'b1; 216 | fifo_en <= 1'b1; 217 | fifo_data <= rx_data; 218 | 219 | if(byte_cnt == 8'd1) 220 | begin 221 | state <= STATE_IDLE; 222 | end 223 | end 224 | end 225 | STATE_DELAY0: 226 | begin 227 | if(rx_valid) 228 | begin 229 | delay[7:0] <= rx_data; 230 | state <= STATE_IDLE; 231 | end 232 | end 233 | STATE_DELAY1: 234 | begin 235 | if(rx_valid) 236 | begin 237 | delay[15:8] <= rx_data; 238 | state <= STATE_IDLE; 239 | end 240 | end 241 | STATE_DELAY2: 242 | begin 243 | if(rx_valid) 244 | begin 245 | delay[23:16] <= rx_data; 246 | state <= STATE_IDLE; 247 | end 248 | end 249 | STATE_DELAY3: 250 | begin 251 | if(rx_valid) 252 | begin 253 | delay[31:24] <= rx_data; 254 | state <= STATE_IDLE; 255 | end 256 | end 257 | STATE_DELAY4: 258 | begin 259 | if(rx_valid) 260 | begin 261 | delay[39:32] <= rx_data; 262 | state <= STATE_IDLE; 263 | end 264 | end 265 | STATE_DELAY5: 266 | begin 267 | if(rx_valid) 268 | begin 269 | delay[47:40] <= rx_data; 270 | state <= STATE_IDLE; 271 | end 272 | end 273 | STATE_DELAY6: 274 | begin 275 | if(rx_valid) 276 | begin 277 | delay[55:48] <= rx_data; 278 | state <= STATE_IDLE; 279 | end 280 | end 281 | STATE_DELAY7: 282 | begin 283 | if(rx_valid) 284 | begin 285 | delay[63:56] <= rx_data; 286 | state <= STATE_IDLE; 287 | end 288 | end 289 | STATE_PULSE_WIDTH: 290 | begin 291 | if(rx_valid) 292 | begin 293 | pulse_width <= rx_data; 294 | state <= STATE_IDLE; 295 | end 296 | end 297 | STATE_PULSE_CNT: 298 | begin 299 | if(rx_valid) 300 | begin 301 | pulse_cnt <= rx_data; 302 | state <= STATE_IDLE; 303 | end 304 | end 305 | STATE_PWM: 306 | begin 307 | if(rx_valid) 308 | begin 309 | pwm <= rx_data; 310 | state <= STATE_IDLE; 311 | end 312 | end 313 | default: 314 | $display ("cmd: Invalid state 0x%X", state); 315 | endcase 316 | end 317 | end 318 | 319 | endmodule 320 | -------------------------------------------------------------------------------- /src/delay.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module delay( 35 | input wire clk, 36 | input wire rst, 37 | input wire en, 38 | input wire [63:0] delay, 39 | output reg rdy = 1'b1 40 | ); 41 | 42 | parameter STATE_IDLE = 1'b0; 43 | parameter STATE_RUN = 1'b1; 44 | 45 | reg state = STATE_IDLE; 46 | 47 | reg [63:0] cnt; 48 | 49 | always @(posedge clk) 50 | begin 51 | if (rst) 52 | begin 53 | // reset 54 | state <= STATE_IDLE; 55 | rdy <= rdy; 56 | end 57 | else 58 | begin 59 | state <= state; 60 | rdy <= 1'b0; 61 | cnt <= cnt + 1'b1; 62 | 63 | case(state) 64 | STATE_IDLE: 65 | begin 66 | if(en) 67 | begin 68 | cnt <= 64'd0; 69 | state <= STATE_RUN; 70 | rdy <= 1'b0; 71 | end 72 | end 73 | STATE_RUN: 74 | begin 75 | if(cnt == delay) 76 | begin 77 | state <= STATE_IDLE; 78 | rdy <= 1'b1; 79 | end 80 | end 81 | endcase 82 | end 83 | end 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /src/fifo.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module fifo ( 35 | input wire clk, 36 | input wire rst, 37 | input wire [7:0] data_in, 38 | input wire wen, 39 | input wire ren, 40 | output wire [7:0] data_out, 41 | output wire full, 42 | output wire empty 43 | ); 44 | 45 | fifo_sync_ram #( 46 | .WIDTH(8) 47 | ) fifoi 48 | ( 49 | .clk(clk), 50 | .rst(rst), 51 | .wr_data(data_in), 52 | .wr_ena(wen), 53 | .wr_full(full), 54 | .rd_data(data_out), 55 | .rd_ena(ren), 56 | .rd_empty(empty) 57 | ); 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /src/fifo_sync_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | * fifo_sync_ram.v 3 | * 4 | * vim: ts=4 sw=4 5 | * 6 | * Copyright (C) 2019 Sylvain Munaut 7 | * All rights reserved. 8 | * 9 | * BSD 3-clause, see LICENSE.bsd 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions are met: 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of the nor the 19 | * names of its contributors may be used to endorse or promote products 20 | * derived from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 26 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | `default_nettype none 34 | 35 | module fifo_sync_ram #( 36 | parameter integer DEPTH = 256, 37 | parameter integer WIDTH = 16 38 | )( 39 | input wire [WIDTH-1:0] wr_data, 40 | input wire wr_ena, 41 | output wire wr_full, 42 | 43 | output wire [WIDTH-1:0] rd_data, 44 | input wire rd_ena, 45 | output wire rd_empty, 46 | output reg rd_valid, 47 | 48 | input wire clk, 49 | input wire rst 50 | ); 51 | 52 | localparam AWIDTH = $clog2(DEPTH); 53 | 54 | 55 | // Signals 56 | // ------- 57 | 58 | // RAM 59 | reg [AWIDTH-1:0] ram_wr_addr; 60 | wire [ WIDTH-1:0] ram_wr_data; 61 | wire ram_wr_ena; 62 | 63 | reg [AWIDTH-1:0] ram_rd_addr; 64 | wire [ WIDTH-1:0] ram_rd_data; 65 | wire ram_rd_ena; 66 | 67 | // Fill-level 68 | reg [AWIDTH:0] level; 69 | (* keep="true" *) wire lvl_dec; 70 | (* keep="true" *) wire lvl_mov; 71 | wire lvl_empty; 72 | 73 | // Full 74 | wire full_nxt; 75 | reg full; 76 | 77 | 78 | // Fill level counter 79 | // ------------------ 80 | // (counts the number of used words - 1) 81 | 82 | always @(posedge clk or posedge rst) 83 | if (rst) 84 | level <= {(AWIDTH+1){1'b1}}; 85 | else 86 | level <= level + { {AWIDTH{lvl_dec}}, lvl_mov }; 87 | 88 | assign lvl_dec = ram_rd_ena & ~ram_wr_ena; 89 | assign lvl_mov = ram_rd_ena ^ ram_wr_ena; 90 | assign lvl_empty = level[AWIDTH]; 91 | 92 | 93 | // Full flag generation 94 | // -------------------- 95 | 96 | assign full_nxt = level == { 1'b0, {(AWIDTH-2){1'b1}}, 2'b01 }; 97 | 98 | always @(posedge clk or posedge rst) 99 | if (rst) 100 | full <= 1'b0; 101 | else 102 | full <= (full | (wr_ena & ~rd_ena & full_nxt)) & ~(rd_ena & ~wr_ena); 103 | 104 | assign wr_full = full; 105 | 106 | 107 | // Write 108 | // ----- 109 | 110 | always @(posedge clk or posedge rst) 111 | if (rst) 112 | ram_wr_addr <= 0; 113 | else if (ram_wr_ena) 114 | ram_wr_addr <= ram_wr_addr + 1; 115 | 116 | assign ram_wr_data = wr_data; 117 | assign ram_wr_ena = wr_ena; 118 | 119 | 120 | // Read 121 | // ---- 122 | 123 | always @(posedge clk or posedge rst) 124 | if (rst) 125 | ram_rd_addr <= 0; 126 | else if (ram_rd_ena) 127 | ram_rd_addr <= ram_rd_addr + 1; 128 | 129 | assign ram_rd_ena = (rd_ena | ~rd_valid) & ~lvl_empty; 130 | 131 | always @(posedge clk or posedge rst) 132 | if (rst) 133 | rd_valid <= 1'b0; 134 | else if (rd_ena | ~rd_valid) 135 | rd_valid <= ~lvl_empty; 136 | 137 | assign rd_data = ram_rd_data; 138 | assign rd_empty = ~rd_valid; 139 | 140 | 141 | // RAM 142 | // --- 143 | 144 | ram_sdp #( 145 | .AWIDTH(AWIDTH), 146 | .DWIDTH(WIDTH) 147 | ) ram_I ( 148 | .wr_addr(ram_wr_addr), 149 | .wr_data(ram_wr_data), 150 | .wr_ena(ram_wr_ena), 151 | .rd_addr(ram_rd_addr), 152 | .rd_data(ram_rd_data), 153 | .rd_ena(ram_rd_ena), 154 | .clk(clk) 155 | ); 156 | 157 | endmodule // fifo_sync_ram 158 | -------------------------------------------------------------------------------- /src/pattern.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module pattern ( 35 | input wire clk, 36 | input wire rst, 37 | input wire en, 38 | input wire [7:0] pattern, 39 | input wire [7:0] pattern_cnt, 40 | output reg dout = 1'b1, 41 | output reg rdy = 1'b1 42 | ); 43 | 44 | parameter STATE_IDLE = 1'b0; 45 | parameter STATE_RUN = 1'b1; 46 | 47 | reg state = STATE_IDLE; 48 | 49 | reg [7:0] cnt; 50 | reg [7:0] data; 51 | 52 | reg [2:0] bit_cnt; 53 | reg [7:0] byte_cnt; 54 | 55 | always @(posedge clk) begin 56 | if (rst) 57 | begin 58 | // reset 59 | state <= STATE_IDLE; 60 | rdy <= 1'b1; 61 | end 62 | else 63 | begin 64 | state <= state; 65 | cnt <= cnt; 66 | data <= data; 67 | bit_cnt <= bit_cnt; 68 | dout <= dout; 69 | rdy <= rdy; 70 | 71 | case(state) 72 | STATE_IDLE: 73 | begin 74 | dout <= 1'b1; 75 | if(en) 76 | begin 77 | data <= pattern; 78 | cnt <= pattern_cnt; 79 | bit_cnt <= 3'd0; 80 | byte_cnt <= 8'd0; 81 | state <= STATE_RUN; 82 | rdy <= 1'b0; 83 | end 84 | end 85 | STATE_RUN: 86 | begin 87 | bit_cnt <= bit_cnt + 1'b1; 88 | data <= {data[0], data[7:1]}; 89 | dout <= data[0]; 90 | 91 | if(bit_cnt == 3'd7) 92 | begin 93 | byte_cnt <= byte_cnt + 1'b1; 94 | bit_cnt <= 8'd0; 95 | if(byte_cnt == cnt) 96 | begin 97 | state <= STATE_IDLE; 98 | rdy <= 1'b1; 99 | end 100 | end 101 | end 102 | endcase 103 | end 104 | end 105 | 106 | endmodule 107 | -------------------------------------------------------------------------------- /src/pulse.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module pulse( 35 | input wire clk, 36 | input wire rst, 37 | input wire en, 38 | input wire [7:0] width_in, 39 | input wire [7:0] cnt_in, 40 | output reg pulse_o = 1'b1, 41 | output reg pulse_rdy = 1'b1 42 | ); 43 | 44 | parameter STATE_IDLE = 2'd0; 45 | parameter STATE_RUN = 2'd1; 46 | parameter STATE_WAIT_NO_ENABLE = 2'd2; 47 | 48 | reg [1:0] state = STATE_IDLE; 49 | 50 | reg [7:0] width_data; 51 | reg [7:0] width; 52 | reg [7:0] cnt_data; 53 | reg [7:0] cnt; 54 | 55 | // Because of the state change, the width takes one more cycle that its 56 | // setting. At 12MHz this matters. 57 | 58 | always @(posedge clk) begin 59 | if (rst) 60 | begin 61 | pulse_o <= 1'b1; 62 | state <= STATE_IDLE; 63 | pulse_rdy <= 1'b1; 64 | end 65 | else 66 | begin 67 | pulse_o <= pulse_o; 68 | state <= state; 69 | pulse_rdy <= pulse_rdy; 70 | width_data <= width_data; 71 | cnt <= cnt; 72 | cnt_data <= cnt_data; 73 | width <= width + 1'b1; 74 | 75 | case(state) 76 | STATE_IDLE: 77 | begin 78 | if(en) 79 | begin 80 | state <= STATE_RUN; 81 | width_data <= width_in; 82 | width <= 8'd1; 83 | cnt_data <= cnt_in; 84 | cnt <= 8'd0; 85 | pulse_o <= 1'b0; 86 | pulse_rdy <= 1'b0; 87 | end 88 | end 89 | STATE_RUN: 90 | begin 91 | if(width == width_data) 92 | begin 93 | width <= 8'd0; 94 | cnt <= cnt + 1'b1; 95 | if(cnt == cnt_data) 96 | begin 97 | state <= STATE_WAIT_NO_ENABLE; 98 | pulse_o <= 1'b1; 99 | pulse_rdy <= 1'b1; 100 | end 101 | end 102 | end 103 | STATE_WAIT_NO_ENABLE: 104 | begin 105 | if(!en) 106 | begin 107 | state <= STATE_IDLE; 108 | end 109 | end 110 | default: 111 | $display ("cmd: Invalid state 0x%X", state); 112 | endcase 113 | end 114 | end 115 | 116 | endmodule 117 | -------------------------------------------------------------------------------- /src/ram_sdp.v: -------------------------------------------------------------------------------- 1 | /* 2 | * ram_sdp.v 3 | * 4 | * vim: ts=4 sw=4 5 | * 6 | * Copyright (C) 2019 Sylvain Munaut 7 | * All rights reserved. 8 | * 9 | * BSD 3-clause, see LICENSE.bsd 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions are met: 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of the nor the 19 | * names of its contributors may be used to endorse or promote products 20 | * derived from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 26 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | `default_nettype none 34 | 35 | module ram_sdp #( 36 | parameter integer AWIDTH = 9, 37 | parameter integer DWIDTH = 8 38 | )( 39 | input wire [AWIDTH-1:0] wr_addr, 40 | input wire [DWIDTH-1:0] wr_data, 41 | input wire wr_ena, 42 | 43 | input wire [AWIDTH-1:0] rd_addr, 44 | output reg [DWIDTH-1:0] rd_data, 45 | input wire rd_ena, 46 | 47 | input wire clk 48 | ); 49 | // Signals 50 | reg [DWIDTH-1:0] ram [(1< 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module top 35 | ( 36 | input wire ext_clk, 37 | input wire ftdi_rx, 38 | output wire ftdi_tx, 39 | input wire o_board_rx, 40 | output wire o_board_tx, 41 | output wire o_board_rst, 42 | output wire LEDR_N, 43 | output wire LEDG_N, 44 | output wire [6:0] seg0, 45 | output wire ca0, 46 | output wire [6:0] seg1, 47 | output wire ca1, 48 | output wire vout 49 | ); 50 | 51 | // Combinatorial logic 52 | // -- Pass through everything from the target to the host 53 | assign ftdi_tx = o_board_rx; 54 | 55 | // High nibble 56 | nibble_to_seven_seg segi0_1 ( 57 | .nibblein(pulse_width[7:4]), 58 | .segout(nib0_1) 59 | ); 60 | 61 | // Low nibble 62 | nibble_to_seven_seg segi0_0 ( 63 | .nibblein(pulse_width[3:0]), 64 | .segout(nib0_0) 65 | ); 66 | 67 | wire [6:0] nib0_0, nib0_1; 68 | 69 | seven_seg_mux dmuxi0 ( 70 | .clk(ext_clk), 71 | .disp0(nib0_0), 72 | .disp1(nib0_1), 73 | .segout(seg0), 74 | .disp_sel(ca0) 75 | ); 76 | 77 | // High nibble 78 | nibble_to_seven_seg segi1_1 ( 79 | .nibblein(delay[7:4]), 80 | .segout(nib1_1) 81 | ); 82 | 83 | // Low nibble 84 | nibble_to_seven_seg segi1_0 ( 85 | .nibblein(delay[3:0]), 86 | .segout(nib1_0) 87 | ); 88 | 89 | wire [6:0] nib1_0, nib1_1; 90 | 91 | seven_seg_mux dmuxi1 ( 92 | .clk(ext_clk), 93 | .disp0(nib1_0), 94 | .disp1(nib1_1), 95 | .segout(seg1), 96 | .disp_sel(ca1) 97 | ); 98 | 99 | assign LEDG_N = o_board_tx; 100 | assign LEDR_N = o_board_rx; 101 | 102 | wire rst; 103 | wire glitch_en; 104 | wire [7:0] pulse_width, pulse_cnt; 105 | wire [7:0] pwm; 106 | wire [63:0] delay; 107 | wire board_rst; 108 | wire passthrough; 109 | wire dout; 110 | 111 | assign o_board_tx = passthrough ? ftdi_rx : dout; 112 | 113 | // Receives commands from host uart and parses out commands intended for the 114 | // glitcher, passing through everything else 115 | cmd cmdi ( 116 | .clk(ext_clk), 117 | .din(ftdi_rx), 118 | .dout(dout), 119 | .board_rst(board_rst), 120 | .rst(rst), 121 | .pulse_width(pulse_width), 122 | .pulse_cnt(pulse_cnt), 123 | .delay(delay), 124 | .pwm(pwm), 125 | .glitch_en(glitch_en), 126 | .passthrough(passthrough) 127 | ); 128 | 129 | wire pwm_out; 130 | 131 | pattern pwmi ( 132 | .clk(ext_clk), 133 | .rst(rst), 134 | .en(1'b1), 135 | .pattern(pwm), 136 | .pattern_cnt(8'd0), 137 | .dout(pwm_out) 138 | ); 139 | 140 | wire delay_rdy; 141 | 142 | delay delayi ( 143 | .clk(ext_clk), 144 | .rst(rst), 145 | .en(glitch_en), 146 | .delay(delay), 147 | .rdy(delay_rdy) 148 | ); 149 | 150 | wire trigger_valid; 151 | 152 | trigger triggeri ( 153 | .clk(ext_clk), 154 | .rst(rst), 155 | .en(glitch_en), 156 | .trigger(delay_rdy), 157 | .valid(trigger_valid) 158 | ); 159 | 160 | wire pulse_o; 161 | wire pulse_rdy; 162 | 163 | pulse pulsei ( 164 | .clk(ext_clk), 165 | .rst(rst), 166 | .en(trigger_valid), 167 | .width_in(pulse_width), 168 | .cnt_in(pulse_cnt), 169 | .pulse_o(pulse_o), 170 | .pulse_rdy(pulse_rdy) 171 | ); 172 | 173 | resetter #( 174 | .cycles(60) 175 | ) rsti( 176 | .clk(ext_clk), 177 | .rst(board_rst || rst || glitch_en), 178 | .rst_out(o_board_rst) 179 | ); 180 | 181 | assign vout = pulse_rdy ? pwm_out : pulse_o; 182 | 183 | endmodule 184 | -------------------------------------------------------------------------------- /src/trigger.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * + Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * + Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * + Neither the name arty-glitcher nor the names of its contributors may be 14 | * used to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | * DAMAGE. 28 | * 29 | * Author: Dmitry Nedospasov 30 | * 31 | */ 32 | `default_nettype none 33 | 34 | module trigger ( 35 | input wire clk, 36 | input wire rst, 37 | input wire en, 38 | input wire trigger, 39 | output reg valid = 1'b0 40 | ); 41 | 42 | parameter STATE_IDLE = 1'b0; 43 | parameter STATE_RUN = 1'b1; 44 | 45 | reg state = STATE_IDLE; 46 | 47 | always @(posedge clk) 48 | begin 49 | if (rst) begin 50 | // reset 51 | state <= STATE_IDLE; 52 | end 53 | else 54 | begin 55 | state <= state; 56 | valid <= 1'b0; 57 | case(state) 58 | STATE_IDLE: 59 | begin 60 | if(en) 61 | begin 62 | state <= STATE_RUN; 63 | end 64 | end 65 | STATE_RUN: 66 | begin 67 | if(trigger) 68 | begin 69 | state <= STATE_IDLE; 70 | valid <= 1'b1; 71 | end 72 | end 73 | endcase 74 | end 75 | end 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /src/uart_defs.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | `define SYSTEM_CLOCK 12_000_000 4 | `define BAUD_RATE 115_200 5 | 6 | // 115200 8N1 7 | `define UART_FULL_ETU (`SYSTEM_CLOCK/`BAUD_RATE) 8 | `define UART_HALF_ETU ((`SYSTEM_CLOCK/`BAUD_RATE)/2) 9 | -------------------------------------------------------------------------------- /src/uart_rx.v: -------------------------------------------------------------------------------- 1 | `include "src/uart_defs.v" 2 | 3 | /* 4 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * + Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * + Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * + Neither the name arty-glitcher nor the names of its contributors may be 16 | * used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | * 31 | * Author: Dmitry Nedospasov 32 | * 33 | */ 34 | `default_nettype none 35 | 36 | module uart_rx ( 37 | input wire clk, 38 | input wire rst, 39 | input wire din, 40 | output reg [7:0] data_out, 41 | output reg valid 42 | ); 43 | 44 | parameter [1:0] UART_START = 2'd0; 45 | parameter [1:0] UART_DATA = 2'd1; 46 | parameter [1:0] UART_STOP = 2'd2; 47 | 48 | reg [1:0] state = UART_START; 49 | reg [2:0] bit_cnt = 3'b0; 50 | reg [9:0] etu_cnt = 10'd0; 51 | 52 | wire etu_full, etu_half; 53 | assign etu_full = (etu_cnt == `UART_FULL_ETU); 54 | assign etu_half = (etu_cnt == `UART_HALF_ETU); 55 | 56 | always @ (posedge clk) 57 | begin 58 | if (rst) 59 | begin 60 | state <= UART_START; 61 | end 62 | 63 | else 64 | begin 65 | // Default assignments 66 | valid <= 1'b0; 67 | etu_cnt <= (etu_cnt + 1'b1); 68 | state <= state; 69 | bit_cnt <= bit_cnt; 70 | data_out <= data_out; 71 | 72 | case(state) 73 | // Waiting for Start Bits 74 | UART_START: 75 | begin 76 | if(din == 1'b0) 77 | begin 78 | // wait .5 ETUs 79 | if(etu_half) 80 | begin 81 | state <= UART_DATA; 82 | etu_cnt <= 10'd0; 83 | bit_cnt <= 3'd0; 84 | data_out <= 8'd0; 85 | end 86 | end 87 | else 88 | etu_cnt <= 10'd0; 89 | end 90 | 91 | // Data Bits 92 | UART_DATA: 93 | if(etu_full) 94 | begin 95 | etu_cnt <= 10'd0; 96 | data_out <= {din, data_out[7:1]}; 97 | bit_cnt <= (bit_cnt + 1'b1); 98 | 99 | if(bit_cnt == 3'd7) 100 | state <= UART_STOP; 101 | end 102 | 103 | // Stop Bit(s) 104 | UART_STOP: 105 | if(etu_full) 106 | begin 107 | etu_cnt <= 10'd0; 108 | state <= UART_START; 109 | // Check Stop bit 110 | valid <= din; 111 | end 112 | 113 | default: 114 | $display ("UART RX: Invalid state 0x%X", state); 115 | 116 | endcase 117 | end 118 | end 119 | 120 | endmodule 121 | -------------------------------------------------------------------------------- /src/uart_tx.v: -------------------------------------------------------------------------------- 1 | `include "src/uart_defs.v" 2 | 3 | /* 4 | * Copyright (c) 2017, Toothless Consulting UG (haftungsbeschraenkt) 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * + Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * + Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * + Neither the name arty-glitcher nor the names of its contributors may be 16 | * used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE arty-glitcher PROJECT BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | * 31 | * Author: Dmitry Nedospasov 32 | * 33 | */ 34 | `default_nettype none 35 | 36 | module uart_tx ( 37 | input wire clk, 38 | input wire rst, 39 | output reg dout = 1'b1, 40 | input wire [7:0] data_in, 41 | input wire en, 42 | output reg rdy = 1'b1 43 | ); 44 | 45 | parameter [1:0] UART_START = 2'd0; 46 | parameter [1:0] UART_DATA = 2'd1; 47 | parameter [1:0] UART_STOP = 2'd2; 48 | parameter [1:0] UART_IDLE = 2'd3; 49 | 50 | reg [7:0] data = 8'd0; 51 | reg [1:0] state = UART_START; 52 | reg [2:0] bit_cnt = 3'd0; 53 | reg [9:0] etu_cnt = 10'd0; 54 | 55 | wire etu_full; 56 | assign etu_full = (etu_cnt == `UART_FULL_ETU); 57 | 58 | always @ (posedge clk) 59 | begin 60 | if (rst) 61 | begin 62 | state <= UART_START; 63 | dout <= 1'b1; 64 | rdy <= 1'b1; 65 | end 66 | 67 | else 68 | begin 69 | // Default assignments 70 | etu_cnt <= (etu_cnt + 1'b1); 71 | dout <= dout; 72 | rdy <= rdy; 73 | data <= data; 74 | state <= state; 75 | bit_cnt <= bit_cnt; 76 | 77 | case(state) 78 | 79 | // Idle, waiting for enable 80 | UART_START: 81 | begin 82 | if(en) 83 | begin 84 | // Start bit 85 | dout <= 1'b0; 86 | data <= data_in; 87 | state <= UART_DATA; 88 | etu_cnt <= 10'd0; 89 | bit_cnt <= 3'd0; 90 | rdy <= 1'b0; 91 | end 92 | end 93 | 94 | // Data Bits 95 | UART_DATA: 96 | if(etu_full) 97 | begin 98 | etu_cnt <= 10'd0; 99 | bit_cnt <= (bit_cnt + 1'b1); 100 | 101 | dout <= data[0]; 102 | data <= {data[0], data[7:1]}; 103 | 104 | if(bit_cnt == 3'd7) 105 | begin 106 | state <= UART_STOP; 107 | end 108 | end 109 | 110 | // Stop Bit(s) 111 | UART_STOP: 112 | if(etu_full) 113 | begin 114 | etu_cnt <= 10'd0; 115 | dout <= 1'b1; 116 | state <= UART_IDLE; 117 | end 118 | 119 | // Idle time before restarting 120 | UART_IDLE: 121 | if(etu_full) 122 | begin 123 | rdy <= 1'b1; 124 | state <= UART_START; 125 | end 126 | 127 | default: 128 | $display ("UART TX: Invalid state 0x%X", state); 129 | 130 | endcase 131 | end 132 | end 133 | 134 | endmodule 135 | -------------------------------------------------------------------------------- /syn/icebreaker.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock 2 | set_io -nowarn ext_clk 35 3 | set_io -nowarn rst 10 4 | 5 | # RS232 6 | set_io -nowarn RX 6 7 | set_io -nowarn TX 9 8 | 9 | # LEDs and Button 10 | set_io -nowarn BTN_N 10 11 | set_io -nowarn LEDR_N 11 12 | set_io -nowarn LEDG_N 37 13 | 14 | # RGB LED Driver 15 | set_io -nowarn LED_RED_N 39 16 | set_io -nowarn LED_GRN_N 40 17 | set_io -nowarn LED_BLU_N 41 18 | 19 | # SPI Flash 20 | set_io -nowarn FLASH_SCK 15 21 | set_io -nowarn FLASH_SSB 16 22 | set_io -nowarn FLASH_IO0 14 23 | set_io -nowarn FLASH_IO1 17 24 | set_io -nowarn FLASH_IO2 12 25 | set_io -nowarn FLASH_IO3 13 26 | 27 | # PMOD 1A 28 | set_io -nowarn P1A1 4 29 | set_io -nowarn P1A2 2 30 | set_io -nowarn P1A3 47 31 | set_io -nowarn P1A4 45 32 | set_io -nowarn P1A7 3 33 | set_io -nowarn P1A8 48 34 | set_io -nowarn P1A9 46 35 | set_io -nowarn P1A10 44 36 | 37 | # PMOD 1B 38 | set_io -nowarn P1B1 43 39 | set_io -nowarn P1B2 38 40 | set_io -nowarn P1B3 34 41 | set_io -nowarn P1B4 31 42 | set_io -nowarn P1B7 42 43 | set_io -nowarn P1B8 36 44 | set_io -nowarn P1B9 32 45 | set_io -nowarn P1B10 28 46 | 47 | # PMOD 2 48 | set_io -nowarn P2_1 27 49 | set_io -nowarn P2_2 25 50 | set_io -nowarn P2_3 21 51 | set_io -nowarn P2_4 19 52 | set_io -nowarn P2_7 26 53 | set_io -nowarn P2_8 23 54 | set_io -nowarn P2_9 20 55 | set_io -nowarn P2_10 18 56 | 57 | # LEDs and Buttons (PMOD 2) 58 | set_io -nowarn LED1 26 59 | set_io -nowarn LED2 27 60 | set_io -nowarn LED3 25 61 | set_io -nowarn LED4 23 62 | set_io -nowarn LED5 21 63 | set_io -nowarn BTN1 20 64 | set_io -nowarn BTN2 19 65 | set_io -nowarn BTN3 18 66 | 67 | set_io -nowarn led[0] 26 68 | set_io -nowarn led[1] 27 69 | set_io -nowarn led[2] 25 70 | set_io -nowarn led[3] 23 71 | set_io -nowarn led[4] 21 72 | 73 | # 7 Segment on PMOD 1A and 1B 74 | set_io -nowarn seg0[0] 4 75 | set_io -nowarn seg0[1] 2 76 | set_io -nowarn seg0[2] 47 77 | set_io -nowarn seg0[3] 45 78 | set_io -nowarn seg0[4] 3 79 | set_io -nowarn seg0[5] 48 80 | set_io -nowarn seg0[6] 46 81 | set_io -nowarn ca0 44 82 | 83 | set_io -nowarn seg1[0] 43 84 | set_io -nowarn seg1[1] 38 85 | set_io -nowarn seg1[2] 34 86 | set_io -nowarn seg1[3] 31 87 | set_io -nowarn seg1[4] 42 88 | set_io -nowarn seg1[5] 36 89 | set_io -nowarn seg1[6] 32 90 | set_io -nowarn ca1 28 91 | 92 | # FTDI 93 | set_io -nowarn ftdi_rx 6 94 | set_io -nowarn ftdi_tx 9 95 | 96 | # Debug header on PMOD 1B 97 | set_io -nowarn debug_header[0] 43 98 | set_io -nowarn debug_header[1] 38 99 | set_io -nowarn debug_header[2] 34 100 | set_io -nowarn debug_header[3] 31 101 | set_io -nowarn debug_header[4] 42 102 | set_io -nowarn debug_header[5] 36 103 | set_io -nowarn debug_header[6] 32 104 | set_io -nowarn debug_header[7] 28 105 | 106 | # Board control on PMOD 2 107 | set_io -nowarn o_board_rx 27 108 | set_io -nowarn o_board_tx 25 109 | set_io -nowarn o_board_rst 21 110 | set_io -nowarn vout 19 111 | set_io -nowarn P2_7 26 112 | set_io -nowarn P2_8 23 113 | set_io -nowarn P2_9 20 114 | set_io -nowarn P2_10 18 115 | 116 | --------------------------------------------------------------------------------