1+ module mojo_top (
2+ input clk, // 50MHz clock
3+ input rst_n, // reset button (active low)
4+ output led [8], // 8 user controllable LEDs
5+ input cclk, // configuration clock, AVR ready when high
6+ output spi_miso, // AVR SPI MISO
7+ input spi_ss, // AVR SPI Slave Select
8+ input spi_mosi, // AVR SPI MOSI
9+ input spi_sck, // AVR SPI Clock
10+ output spi_channel [4], // AVR general purpose pins (used by default to select ADC channel)
11+ input avr_tx, // AVR TX (FPGA RX)
12+ output avr_rx, // AVR RX (FPGA TX)
13+ input avr_rx_busy, // AVR RX buffer full
14+ input camera,
15+ output laser1,
16+ output laser2,
17+ output laser3,
18+ output laser4,
19+ output laser5,
20+ output laser6,
21+ output ttl1,
22+ output ttl2,
23+ output ttl3,
24+ output ttl4,
25+ output ttl5,
26+ output ttl6,
27+ output servo1,
28+ output servo2,
29+ output servo3,
30+ output servo4,
31+ output servo5,
32+ output servo6,
33+ output pwm1,
34+ output pwm2,
35+ output pwm3,
36+ output pwm4,
37+ output pwm5,
38+ output pwm6
39+ ) {
40+
41+ const ADDRESS_VERSION = 100;
42+ const ERROR_UNKNOW_COMMAND = 38730;
43+ const NUM_INPUT = 8; // fixed by the board
44+ const NUM_LASERS = 6;
45+ const NUM_PWM = 6;
46+ const NUM_TTL = 6;
47+ const NUM_SERVOS = 6;
48+
49+ sig rst; // reset signal
50+
51+ .clk(clk) {
52+ // The reset conditioner is used to synchronize the reset signal to the FPGA
53+ // clock. This ensures the entire FPGA comes out of reset at the same time.
54+ reset_conditioner reset_cond;
55+
56+ .rst(rst){
57+ // the avr_interface module is used to talk to the AVR for access to the USB port and analog pins
58+ avr_interface avr;
59+ reg_interface reg;
60+
61+ // adc
62+ analogreader adc;
63+
64+ // lasers
65+ lasertrigger l[NUM_LASERS];
66+ cam_synchro camsync;
67+
68+ dff sequence[NUM_LASERS][16];
69+ dff duration[NUM_LASERS][16];
70+ dff mode[NUM_LASERS][3];
71+
72+ // ttls
73+ dff ttl[NUM_TTL];
74+
75+ // servos
76+ servo_standard servo_controller[NUM_SERVOS];
77+ dff position[NUM_SERVOS][16];
78+ dff servo_sig_update[NUM_SERVOS];
79+ servo_stop servo_sig[NUM_SERVOS];// to shut down the servos 10 sec after every movement
80+
81+ // pwm
82+ pwm pulsewm[NUM_PWM](#TOP(254),#DIV(9),#WIDTH(8));
83+ dff dutycycle[NUM_PWM][8];
84+ dff pwmupdate[NUM_PWM];
85+ }
86+ }
87+
88+ always {
89+ led = 8b0;
90+
91+ reset_cond.in = ~rst_n; // input raw inverted reset signal
92+ rst = reset_cond.out; // conditioned reset
93+
94+ // connect inputs of avr
95+ avr.cclk = cclk;
96+ avr.spi_ss = spi_ss;
97+ avr.spi_mosi = spi_mosi;
98+ avr.spi_sck = spi_sck;
99+ avr.rx = avr_tx;
100+ avr.tx_block = avr_rx_busy; // block TX when AVR is busy
101+
102+ // connect outputs of avr
103+ spi_miso = avr.spi_miso;
104+ spi_channel = avr.spi_channel;
105+ avr_rx = avr.tx;
106+
107+ // connect adc to avr avr_interface
108+ avr.channel = adc.channel;
109+ adc.sample = avr.sample;
110+ adc.sample_channel = avr.sample_channel;
111+ adc.new_sample = avr.new_sample;
112+
113+ // connect reg interface to avr interface
114+ reg.rx_data = avr.rx_data;
115+ reg.new_rx_data = avr.new_rx_data;
116+ avr.tx_data = reg.tx_data;
117+ avr.new_tx_data = reg.new_tx_data;
118+ reg.tx_busy = avr.tx_busy;
119+
120+ reg.regIn.drdy = 0; // default to not ready
121+ reg.regIn.data = 32bx; // don't care
122+
123+ pwmupdate.d = NUM_PWMx{0};
124+ servo_sig_update.d = NUM_SERVOSx{0};
125+
126+ if (reg.regOut.new_cmd) { // new command
127+ if (reg.regOut.write) { // if write
128+ if (reg.regOut.address < NUM_LASERS) { // Laser modes
129+ mode.d[reg.regOut.address] = reg.regOut.data[2:0];
130+ } else if (reg.regOut.address < 10+NUM_LASERS) { // Laser duration
131+ duration.d[reg.regOut.address-10] = reg.regOut.data[15:0];
132+ } else if (reg.regOut.address < 20+NUM_LASERS) { // Laser sequence
133+ sequence.d[reg.regOut.address-20] = reg.regOut.data[15:0];
134+ } else if (reg.regOut.address < 30+NUM_TTL){ // TTL
135+ ttl.d[reg.regOut.address-30] = reg.regOut.data[0];
136+ } else if (reg.regOut.address < 40+NUM_SERVOS){ // Servo
137+ position.d[reg.regOut.address-40] = reg.regOut.data[15:0];
138+ servo_sig_update.d[reg.regOut.address-40] = 1;
139+ } else if (reg.regOut.address < 50+NUM_PWM){ // PWM
140+ dutycycle.d[reg.regOut.address-50] = reg.regOut.data[7:0];
141+ pwmupdate.d[reg.regOut.address-50] = 1;
142+ }
143+ } else { // read
144+ led = 10;
145+ if (reg.regOut.address < NUM_LASERS) { // Laser modes
146+ reg.regIn.data = mode.q[reg.regOut.address];
147+ reg.regIn.drdy = 1;
148+ } else if (reg.regOut.address < 10+NUM_LASERS) { // Laser duration
149+ reg.regIn.data = duration.q[reg.regOut.address-10];
150+ reg.regIn.drdy = 1;
151+ } else if (reg.regOut.address < 20+NUM_LASERS) { // Laser sequence
152+ reg.regIn.data = sequence.q[reg.regOut.address-20];
153+ reg.regIn.drdy = 1;
154+ } else if (reg.regOut.address < 30+NUM_TTL){ // TTL
155+ reg.regIn.data = ttl.q[reg.regOut.address-30];
156+ reg.regIn.drdy = 1;
157+ } else if (reg.regOut.address < 40+NUM_SERVOS){ // Servo
158+ reg.regIn.data = position.q[reg.regOut.address-40];
159+ reg.regIn.drdy = 1;
160+ } else if (reg.regOut.address < 50+NUM_PWM){ // PWM
161+ reg.regIn.data = dutycycle.q[reg.regOut.address-50];
162+ reg.regIn.drdy = 1;
163+ } else if (reg.regOut.address < 60+NUM_INPUT) { // Analog input
164+ reg.regIn.data = adc.value[reg.regOut.address-60];
165+ reg.regIn.drdy = 1;
166+ } else if (reg.regOut.address == ADDRESS_VERSION) { // Version
167+ reg.regIn.data = 1; // version number
168+ reg.regIn.drdy = 1;
169+ } else { // Error
170+ reg.regIn.data = ERROR_UNKNOW_COMMAND;
171+ reg.regIn.drdy = 1;
172+ }
173+ }
174+ }
175+
176+ ///////////////// Lasers
177+ camsync.camera = camera;
178+ l.trig = NUM_LASERSx{camera};
179+ l.seq = sequence.q;
180+ l.mod = mode.q;
181+ l.dura = duration.q;
182+ l.sync = NUM_LASERSx{{camsync.sync}};
183+
184+ laser1 = l.lasersignal[0];
185+ laser2 = l.lasersignal[1];
186+ laser3 = l.lasersignal[2];
187+ laser4 = l.lasersignal[3];
188+ laser5 = l.lasersignal[4];
189+ laser6 = l.lasersignal[5];
190+
191+ //////////////// TTLs
192+ ttl1 = ttl.q[0];
193+ ttl2 = ttl.q[1];
194+ ttl3 = ttl.q[2];
195+ ttl4 = ttl.q[3];
196+ ttl5 = ttl.q[4];
197+ ttl6 = ttl.q[5];
198+
199+ //////////////// Servos
200+ servo_controller.position = position.q;
201+ servo_sig.update = servo_sig_update.q;
202+ servo_sig.signal_in = servo_controller.servo;
203+ servo1 = servo_sig.signal_out[0];
204+ servo2 = servo_sig.signal_out[1];
205+ servo3 = servo_sig.signal_out[2];
206+ servo4 = servo_sig.signal_out[3];
207+ servo5 = servo_sig.signal_out[4];
208+ servo6 = servo_sig.signal_out[5];
209+
210+ //////////////// PWM
211+ pulsewm.update = pwmupdate.q;
212+ pulsewm.value = dutycycle.q;
213+ pwm1 = pulsewm.pulse[0];
214+ pwm2 = pulsewm.pulse[1];
215+ pwm3 = pulsewm.pulse[2];
216+ pwm4 = pulsewm.pulse[3];
217+ pwm5 = pulsewm.pulse[4];
218+ pwm6 = pulsewm.pulse[5];
219+ }
220+ }
0 commit comments