├── .project
├── LICENSE.txt
├── Mojo-Base.xise
├── README.md
├── ipcore_dir
└── .gitignore
├── iseconfig
├── Mojo-Base.projectmgr
└── mojo_top.xreport
├── src
├── avr_interface.v
├── bcd_counter.v
├── bcd_counter_tb.v
├── cclk_detector.v
├── fizzbuzz.v
├── fizzbuzz_tb.v
├── mojo.ucf
├── mojo_top.v
├── serial.v
├── serial_rx.v
├── serial_tb.v
├── serial_tx.v
└── spi_slave.v
└── syn
└── .gitignore
/.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 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Embedded Micro
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Mojo-Base.xise:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FizzBuzz implemented on an FPGA
2 |
3 | Just for fun, I implemented the FizzBuzz problem on an FPGA using Verilog.
4 |
5 | This is implemented for the Mojo board, using "mojo-base-project" as the framework.
6 |
7 | The code is in `src`, in the `fizzbuzz.v`, `bcd_counter.v` and `serial.v` files.
8 |
9 | The FizzBuzz problem is to output the numbers from 1 to 100, but for multiples of 3 output "Fizz" instead of the number.
10 | For multiples of 5 output "Buzz", and for multiples of both output "FizzBuzz".
11 |
--------------------------------------------------------------------------------
/ipcore_dir/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shirriff/fpga-fizzbuzz/0876b69ebbc8fe6a94bce294c44f6b7e85eac78a/ipcore_dir/.gitignore
--------------------------------------------------------------------------------
/iseconfig/Mojo-Base.projectmgr:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 2
10 | /avr_interface |home|justin|workspace|Mojo-Tutorials|Mojo-Base|src|avr_interface.v
11 |
12 |
13 | mojo_top (/home/parallels/fpga-fizzbuzz/mojo-base-project/src/mojo_top.v)
14 |
15 | 3
16 | 0
17 | 000000ff00000000000000010000000100000000000000000000000000000000020200000001000000010000006400000183000000020000000000000000000000000200000064ffffffff000000810000000300000002000001830000000100000003000000000000000100000003
18 | true
19 | mojo_top (/home/parallels/fpga-fizzbuzz/mojo-base-project/src/mojo_top.v)
20 |
21 |
22 |
23 | 1
24 | Configure Target Device
25 | Implement Design/Map
26 | Implement Design/Place & Route
27 | Implement Design/Translate
28 | User Constraints
29 |
30 |
31 | Generate Programming File
32 |
33 | 9
34 | 0
35 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000118000000010000000100000000000000000000000064ffffffff000000810000000000000001000001180000000100000000
36 | false
37 | Generate Programming File
38 |
39 |
40 |
41 | 1
42 |
43 |
44 | 0
45 | 0
46 | 000000ff0000000000000001000000000000000001000000000000000000000000000000000000025f000000040101000100000000000000000000000064ffffffff000000810000000000000004000000770000000100000000000000c50000000100000000000000790000000100000000000000aa0000000100000000
47 | false
48 | avr_interface.v
49 |
50 |
51 |
52 | 1
53 | work
54 |
55 |
56 | 0
57 | 0
58 | 000000ff00000000000000010000000000000000010000000000000000000000000000000000000128000000010001000100000000000000000000000064ffffffff000000810000000000000001000001280000000100000000
59 | false
60 | work
61 |
62 | 000000ff0000000000000002000001380000011b01000000040100000002
63 | Implementation
64 |
65 |
66 | 1
67 | Design Utilities
68 |
69 |
70 |
71 |
72 | 0
73 | 0
74 | 000000ff000000000000000100000001000000000000000000000000000000000000000000000000f6000000010000000100000000000000000000000064ffffffff000000810000000000000001000000f60000000100000000
75 | false
76 |
77 |
78 |
79 |
80 | 1
81 | User Constraints
82 |
83 |
84 |
85 |
86 | 0
87 | 0
88 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000124000000010000000100000000000000000000000064ffffffff000000810000000000000001000001240000000100000000
89 | false
90 |
91 |
92 |
93 |
94 | 2
95 | /avr_interface |home|parallels|fpga-fizzbuzz|mojo-base-project|src|avr_interface.v
96 | /bcd_counter_tb |home|parallels|fpga-fizzbuzz|mojo-base-project|bcd_counter_tb.v
97 | /fizzbuzz |home|parallels|fpga-fizzbuzz|mojo-base-project|fizzbuzz.v
98 | /mojo_top |home|parallels|fpga-fizzbuzz|mojo-base-project|src|mojo_top.v/fizzbuzz - fizzbuzz
99 | /serial_tb |home|parallels|fpga-fizzbuzz|mojo-base-project|serial_tb.v
100 |
101 |
102 | uut - fizzbuzz (/home/parallels/fpga-fizzbuzz/mojo-base-project/fizzbuzz.v)
103 |
104 | 2
105 | 0
106 | 000000ff0000000000000001000000010000000000000000000000000000000002020000000100000001000000640000017f000000020000000000000000000000000200000064ffffffff0000008100000003000000020000017f0000000100000003000000000000000100000003
107 | true
108 | uut - fizzbuzz (/home/parallels/fpga-fizzbuzz/mojo-base-project/fizzbuzz.v)
109 |
110 |
111 |
112 | 1
113 | Design Utilities
114 |
115 |
116 |
117 |
118 | 0
119 | 0
120 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000124000000010000000100000000000000000000000064ffffffff000000810000000000000001000001240000000100000000
121 | false
122 |
123 |
124 |
125 |
126 | 1
127 |
128 |
129 | Simulate Behavioral Model
130 |
131 | 0
132 | 0
133 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000127000000010000000100000000000000000000000064ffffffff000000810000000000000001000001270000000100000000
134 | false
135 | Simulate Behavioral Model
136 |
137 |
138 |
--------------------------------------------------------------------------------
/iseconfig/mojo_top.xreport:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2018-02-21T23:10:14
5 | mojo_top
6 | 2018-02-21T23:09:33
7 | /home/parallels/fpga-fizzbuzz/mojo-base-project/iseconfig/mojo_top.xreport
8 | /home/parallels/fpga-fizzbuzz/mojo-base-project/syn/
9 | 2012-11-08T12:38:20
10 | false
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/src/avr_interface.v:
--------------------------------------------------------------------------------
1 | module avr_interface #(
2 | parameter CLK_RATE = 50000000,
3 | parameter SERIAL_BAUD_RATE = 500000
4 | )(
5 | input clk,
6 | input rst,
7 |
8 | // cclk, or configuration clock is used when the FPGA is begin configured.
9 | // The AVR will hold cclk high when it has finished initializing.
10 | // It is important not to drive the lines connecting to the AVR
11 | // until cclk is high for a short period of time to avoid contention.
12 | input cclk,
13 |
14 | // AVR SPI Signals
15 | output spi_miso,
16 | input spi_mosi,
17 | input spi_sck,
18 | input spi_ss,
19 | output [3:0] spi_channel,
20 |
21 | // AVR Serial Signals
22 | output tx,
23 | input rx,
24 |
25 | // ADC Interface Signals
26 | input [3:0] channel,
27 | output new_sample,
28 | output [9:0] sample,
29 | output [3:0] sample_channel,
30 |
31 | // Serial TX User Interface
32 | input [7:0] tx_data,
33 | input new_tx_data,
34 | output tx_busy,
35 | input tx_block,
36 |
37 | // Serial Rx User Interface
38 | output [7:0] rx_data,
39 | output new_rx_data
40 | );
41 |
42 | wire ready;
43 | wire n_rdy = !ready;
44 | wire spi_done;
45 | wire [7:0] spi_dout;
46 |
47 | wire tx_m;
48 | wire spi_miso_m;
49 |
50 | reg byte_ct_d, byte_ct_q;
51 | reg [9:0] sample_d, sample_q;
52 | reg new_sample_d, new_sample_q;
53 | reg [3:0] sample_channel_d, sample_channel_q;
54 | reg [3:0] block_d, block_q;
55 | reg busy_d, busy_q;
56 |
57 | // cclk_detector is used to detect when cclk is high signaling when
58 | // the AVR is ready
59 | cclk_detector #(.CLK_RATE(CLK_RATE)) cclk_detector (
60 | .clk(clk),
61 | .rst(rst),
62 | .cclk(cclk),
63 | .ready(ready)
64 | );
65 |
66 | spi_slave spi_slave (
67 | .clk(clk),
68 | .rst(n_rdy),
69 | .ss(spi_ss),
70 | .mosi(spi_mosi),
71 | .miso(spi_miso_m),
72 | .sck(spi_sck),
73 | .done(spi_done),
74 | .din(8'hff),
75 | .dout(spi_dout)
76 | );
77 |
78 | // CLK_PER_BIT is the number of cycles each 'bit' lasts for
79 | // rtoi converts a 'real' number to an 'integer'
80 | parameter CLK_PER_BIT = $rtoi($ceil(CLK_RATE/SERIAL_BAUD_RATE));
81 |
82 | serial_rx #(.CLK_PER_BIT(CLK_PER_BIT)) serial_rx (
83 | .clk(clk),
84 | .rst(n_rdy),
85 | .rx(rx),
86 | .data(rx_data),
87 | .new_data(new_rx_data)
88 | );
89 |
90 | serial_tx #(.CLK_PER_BIT(CLK_PER_BIT)) serial_tx (
91 | .clk(clk),
92 | .rst(n_rdy),
93 | .tx(tx_m),
94 | .block(busy_q),
95 | .busy(tx_busy),
96 | .data(tx_data),
97 | .new_data(new_tx_data)
98 | );
99 |
100 | // Output declarations
101 | assign new_sample = new_sample_q;
102 | assign sample = sample_q;
103 | assign sample_channel = sample_channel_q;
104 |
105 | // these signals connect to the AVR and should be Z when the AVR isn't ready
106 | assign spi_channel = ready ? channel : 4'bZZZZ;
107 | assign spi_miso = ready && !spi_ss ? spi_miso_m : 1'bZ;
108 | assign tx = ready ? tx_m : 1'bZ;
109 |
110 | always @(*) begin
111 | byte_ct_d = byte_ct_q;
112 | sample_d = sample_q;
113 | new_sample_d = 1'b0;
114 | sample_channel_d = sample_channel_q;
115 |
116 | busy_d = busy_q;
117 | block_d = {block_q[2:0], tx_block};
118 |
119 | if (block_q[3] ^ block_q[2])
120 | busy_d = 1'b0;
121 |
122 | if (!tx_busy && new_tx_data)
123 | busy_d = 1'b1;
124 |
125 | if (spi_ss) begin // device is not selected
126 | byte_ct_d = 1'b0;
127 | end
128 |
129 | if (spi_done) begin // sent/received data from SPI
130 | if (byte_ct_q == 1'b0) begin
131 | sample_d[7:0] = spi_dout; // first byte is the 8 LSB of the sample
132 | byte_ct_d = 1'b1;
133 | end else begin
134 | sample_d[9:8] = spi_dout[1:0]; // second byte is the channel 2 MSB of the sample
135 | sample_channel_d = spi_dout[7:4]; // and the channel that was sampled
136 | byte_ct_d = 1'b1; // slave-select must be brought high before the next transfer
137 | new_sample_d = 1'b1;
138 | end
139 | end
140 | end
141 |
142 | always @(posedge clk) begin
143 | if (n_rdy) begin
144 | byte_ct_q <= 1'b0;
145 | sample_q <= 10'b0;
146 | new_sample_q <= 1'b0;
147 | end else begin
148 | byte_ct_q <= byte_ct_d;
149 | sample_q <= sample_d;
150 | new_sample_q <= new_sample_d;
151 | end
152 |
153 | block_q <= block_d;
154 | busy_q <= busy_d;
155 | sample_channel_q <= sample_channel_d;
156 | end
157 |
158 | endmodule
--------------------------------------------------------------------------------
/src/bcd_counter.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | // 3-digit BCD counter
3 | // A signal on "increment" will increment the counter.
4 | // Ken Shirriff http://righto.com
5 |
6 | module bcd_counter(
7 | input clk,
8 | input rst,
9 | input increment,
10 | output reg [3:0] digit2, // High-order digit
11 | output reg [3:0] digit1,
12 | output reg [3:0] digit0
13 | );
14 |
15 | always @(posedge clk) begin
16 | if (rst) begin
17 | // Reset to 000
18 | digit2 <= 4'b0;
19 | digit1 <= 4'b0;
20 | digit0 <= 4'b0;
21 | end else if (increment) begin
22 | // Increment value, rolling over digits at 9
23 | if (digit0 != 4'd9) begin
24 | // Regular increment digit 0
25 | digit0 <= digit0 + 1'b1;
26 | end else begin
27 | // Carry from digit 0
28 | digit0 <= 4'd0;
29 | if (digit1 != 4'd9) begin
30 | // Regular increment digit 1
31 | digit1 <= digit1 + 1'b1;
32 | end else begin
33 | // Carry from digit 1
34 | digit1 <= 4'd0;
35 | digit2 <= digit2 + 1'b1;
36 | end
37 | end
38 | end
39 | end
40 |
41 |
42 | endmodule
43 |
--------------------------------------------------------------------------------
/src/bcd_counter_tb.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | // Testbench for bcd_counter.
4 | // Ken Shirriff http://righto.com
5 |
6 | module bcd_counter_tb;
7 |
8 | // Inputs
9 | reg clk;
10 | reg rst;
11 | reg increment;
12 |
13 | // Outputs
14 | wire [3:0] digit2, digit1, digit0;
15 |
16 | // Instantiate the Unit Under Test (UUT)
17 | bcd_counter uut (
18 | .clk(clk),
19 | .rst(rst),
20 | .increment(increment),
21 | .digit2(digit2),
22 | .digit1(digit1),
23 | .digit0(digit0)
24 | );
25 |
26 | initial begin
27 | clk = 1'b0;
28 | rst = 1'b1;
29 | repeat(4) #10 clk = ~clk;
30 | rst = 1'b0;
31 | forever #10 clk = ~clk;
32 | end
33 |
34 | initial begin
35 | # 20; // Wait for reset
36 | // Increment 120 times
37 | repeat(120) begin
38 | #20 increment = 1'b1;
39 | #20 increment = 1'b0;
40 | end
41 | $finish;
42 | end
43 |
44 | endmodule
45 |
46 |
--------------------------------------------------------------------------------
/src/cclk_detector.v:
--------------------------------------------------------------------------------
1 | module cclk_detector #(
2 | parameter CLK_RATE = 50000000
3 | )(
4 | input clk,
5 | input rst,
6 | input cclk,
7 | output ready
8 | );
9 |
10 | parameter CTR_SIZE = $clog2(CLK_RATE/50000);
11 |
12 | reg [CTR_SIZE-1:0] ctr_d, ctr_q;
13 | reg ready_d, ready_q;
14 |
15 | assign ready = ready_q;
16 |
17 | // ready should only go high once cclk has been high for a while
18 | // if cclk ever falls, ready should go low again
19 | always @(ctr_q or cclk) begin
20 | ready_d = 1'b0;
21 | if (cclk == 1'b0) begin // when cclk is 0 reset the counter
22 | ctr_d = 1'b0;
23 | end else if (ctr_q != {CTR_SIZE{1'b1}}) begin
24 | ctr_d = ctr_q + 1'b1; // counter isn't max value yet
25 | end else begin
26 | ctr_d = ctr_q;
27 | ready_d = 1'b1; // counter reached the max, we are ready
28 | end
29 |
30 | end
31 |
32 | always @(posedge clk) begin
33 | if (rst) begin
34 | ctr_q <= 1'b0;
35 | ready_q <= 1'b0;
36 | end else begin
37 | ctr_q <= ctr_d;
38 | ready_q <= ready_d;
39 | end
40 | end
41 | endmodule
42 |
--------------------------------------------------------------------------------
/src/fizzbuzz.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | // Main fizzbuzz loop
4 | // Ken Shirriff http://righto.com
5 |
6 | // The fizzbuzz problem is to output the numbers 1 to 100 except
7 | // Output "Fizz" if the number is divisible by 3.
8 | // Output "Buzz" if the number is divisible by 5.
9 | // Output "Fizzbuzz" if the number is divisible by both.
10 |
11 | // The algorithm is to have a BCD counter incremented from 1 to 100.
12 | // Store count mod 3 in "mod3", and count mod 5 in "mod5".
13 | // That way the modulo values can be simply incremented rather than an
14 | // expensive modulo operation.
15 |
16 | // Writes ASCII fizzbuzz output as 9600 baud serial.
17 |
18 | module fizzbuzz(
19 | input clk,
20 | input rst,
21 | output [7:0] led, // Diagnostic LED
22 | output out // Output pin
23 | );
24 |
25 | reg [1:0] mod3; // Current value mod 3
26 | reg [2:0] mod5; // Current value mod 5
27 | reg [7:0] char; // Current character to send
28 | reg serial_send; // Flag to send character
29 |
30 | // The serial sending module
31 | serial serial(
32 | .clk(clk),
33 | .rst(rst),
34 | .char(char),
35 | .send(serial_send),
36 | .out(out),
37 | .busy(serial_busy)
38 | );
39 |
40 | reg [3:0] state;
41 |
42 | // States for fizzbuzz.
43 | // NEXT indicates ready to move to next digit (line has been printed).
44 | // States 1 to n indicate that the character should be printed.
45 | // DONE indicates the algorithm is done. The reset button will restart it.
46 | localparam NEXT = 4'b0, DONE = 4'b1111;
47 |
48 | // Show state and middle digit on LEDs for debugging.
49 | assign led[3:0] = state;
50 | assign led[7:4] = digit1;
51 |
52 | // Send an increment signal to the BCD counter in state NEXT
53 | wire increment = (state == NEXT) ? 1'b1 : 1'b0;
54 |
55 | // The 3-digit BCD counter.
56 | wire [3:0] digit2, digit1, digit0;
57 | bcd_counter bcd_counter(
58 | .clk(clk),
59 | .rst(rst),
60 | .increment(increment),
61 | .digit2(digit2),
62 | .digit1(digit1),
63 | .digit0(digit0)
64 | );
65 |
66 | // Main loop
67 | always @(posedge clk) begin
68 | serial_send <= 1'b0;
69 | if (rst) begin
70 | // Start with BCD value 000 and modulo values 0
71 | mod3 <= 2'd0;
72 | mod5 <= 3'd0;
73 | state <= NEXT; // Will increment to 1 before first output.
74 | end else if (state == NEXT) begin
75 | // Line done. Move to next counter value or enter DONE state.
76 | if (digit2 == 1 && digit1 == 0 && digit0 == 0) begin
77 | state <= DONE;
78 | end else begin
79 | // Move to next counter value
80 | mod3 <= (mod3 == 2) ? 2'b0 : mod3 + 1'b1;
81 | mod5 <= (mod5 == 4) ? 3'b0 : mod5 + 1'b1;
82 | state <= 1; // Start output with state 1
83 | end
84 | end else if (!serial_busy && !serial_send && state != DONE) begin
85 | // The output path. Output next character, controlled by state.
86 | state <= state + 1'b1;
87 | serial_send <= 1'b1; // Tell serial module to output a character.
88 | // serial_busy will be high until the serial module is done.
89 | if (mod3 == 2'b0 && mod5 == 3'b0) begin
90 | // Fizzbuzz: output each character of the string.
91 | case (state)
92 | 1: char <= "F";
93 | 2: char <= "i";
94 | 3: char <= "z";
95 | 4: char <= "z";
96 | 5: char <= "b";
97 | 6: char <= "u";
98 | 7: char <= "z";
99 | 8: char <= "z";
100 | 9: char <= "\r";
101 | 10: begin
102 | char <= "\n";
103 | state <= NEXT; // Done with output line
104 | end
105 | endcase
106 | end else if (mod3 == 2'b0) begin
107 | // Fizz
108 | case (state)
109 | 1: char <= "F";
110 | 2: char <= "i";
111 | 3: char <= "z";
112 | 4: char <= "z";
113 | 5: char <= "\r";
114 | 6: begin
115 | char <= "\n";
116 | state <= NEXT; // Done with output line
117 | end
118 | endcase
119 | end else if (mod5 == 3'b0) begin
120 | // Buzz
121 | case (state)
122 | 1: char <= "B";
123 | 2: char <= "u";
124 | 3: char <= "z";
125 | 4: char <= "z";
126 | 5: char <= "\r";
127 | 6: begin
128 | char <= "\n";
129 | state <= NEXT; // Done with output line
130 | end
131 | endcase
132 | end else begin
133 | // No divisors; output the digits of the number.
134 | case (state)
135 | 1: begin
136 | if (digit2 == 0) begin
137 | serial_send <= 0; // Suppress leading zero
138 | end else begin
139 | char <= {2'b11, digit2[3:0]}; // Append 11 bits to get 7-bit ASCII digit
140 | end
141 | end
142 | 2: begin
143 | if (digit2 == 0 && digit1 == 0) begin
144 | serial_send <= 0; // Suppress leading zero
145 | end else begin
146 | char <= {2'b11, digit1[3:0]};
147 | end
148 | end
149 | 3: char <= {2'b11, digit0[3:0]};
150 | 4: char <= "\r";
151 | 5: begin
152 | char <= "\n";
153 | state <= NEXT;
154 | end
155 | endcase
156 | end
157 | end
158 | end
159 |
160 | endmodule
161 |
--------------------------------------------------------------------------------
/src/fizzbuzz_tb.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | // Testbench for fizzbuzz
3 | // Ken Shirriff http://righto.com
4 | module fizzbuzz_tb;
5 |
6 | // Inputs
7 | reg clk;
8 | reg rst;
9 |
10 | // Outputs
11 | wire out;
12 |
13 | // Instantiate the Unit Under Test (UUT)
14 | fizzbuzz uut (
15 | .clk(clk),
16 | .rst(rst),
17 | .out(out)
18 | );
19 |
20 | initial begin
21 | clk = 1'b0;
22 | rst = 1'b1;
23 | repeat(4) #10 clk = ~clk;
24 | rst = 1'b0;
25 | forever #10 clk = ~clk;
26 | end
27 |
28 | initial begin
29 | # 10000000;
30 | $finish;
31 | end
32 |
33 | endmodule
34 |
35 |
--------------------------------------------------------------------------------
/src/mojo.ucf:
--------------------------------------------------------------------------------
1 | #Created by Constraints Editor (xc6slx9-tqg144-3) - 2012/11/05
2 | NET "clk" TNM_NET = clk;
3 | TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
4 |
5 | # PlanAhead Generated physical constraints
6 | NET "clk" LOC = P56 | IOSTANDARD = LVTTL;
7 | NET "rst_n" LOC = P38 | IOSTANDARD = LVTTL;
8 |
9 | NET "cclk" LOC = P70 | IOSTANDARD = LVTTL;
10 |
11 | NET "led<0>" LOC = P134 | IOSTANDARD = LVTTL;
12 | NET "led<1>" LOC = P133 | IOSTANDARD = LVTTL;
13 | NET "led<2>" LOC = P132 | IOSTANDARD = LVTTL;
14 | NET "led<3>" LOC = P131 | IOSTANDARD = LVTTL;
15 | NET "led<4>" LOC = P127 | IOSTANDARD = LVTTL;
16 | NET "led<5>" LOC = P126 | IOSTANDARD = LVTTL;
17 | NET "led<6>" LOC = P124 | IOSTANDARD = LVTTL;
18 | NET "led<7>" LOC = P123 | IOSTANDARD = LVTTL;
19 |
20 | NET "spi_mosi" LOC = P44 | IOSTANDARD = LVTTL;
21 | NET "spi_miso" LOC = P45 | IOSTANDARD = LVTTL;
22 | NET "spi_ss" LOC = P48 | IOSTANDARD = LVTTL;
23 | NET "spi_sck" LOC = P43 | IOSTANDARD = LVTTL;
24 | NET "spi_channel<0>" LOC = P46 | IOSTANDARD = LVTTL;
25 | NET "spi_channel<1>" LOC = P61 | IOSTANDARD = LVTTL;
26 | NET "spi_channel<2>" LOC = P62 | IOSTANDARD = LVTTL;
27 | NET "spi_channel<3>" LOC = P65 | IOSTANDARD = LVTTL;
28 |
29 | NET "avr_tx" LOC = P55 | IOSTANDARD = LVTTL;
30 | NET "avr_rx" LOC = P59 | IOSTANDARD = LVTTL;
31 | NET "avr_rx_busy" LOC = P39 | IOSTANDARD = LVTTL;
32 | NET "pin50" LOC = P50 | IOSTANDARD = LVTTL;
--------------------------------------------------------------------------------
/src/mojo_top.v:
--------------------------------------------------------------------------------
1 | //
2 | // Top-level routine for FizzBuzz problem.
3 | // This simply instantiates the fizzbuzz module, which does all the work.
4 | // Ken Shirriff http://righto.com
5 |
6 | // FizzBuzz: loop from 1 to 100. Print Fizz for multiples of 3,
7 | // Buzz for multiples of 5, FizzBuzz for multiples of both.
8 |
9 | module mojo_top(
10 | // 50MHz clock input
11 | input clk,
12 | // Input from reset button (active low)
13 | input rst_n,
14 | // cclk input from AVR, high when AVR is ready
15 | input cclk,
16 | // Outputs to the 8 onboard LEDs
17 | output[7:0]led,
18 | // AVR SPI connections
19 | output spi_miso,
20 | input spi_ss,
21 | input spi_mosi,
22 | input spi_sck,
23 | // AVR ADC channel select
24 | output [3:0] spi_channel,
25 | // Serial connections
26 | input avr_tx, // AVR Tx => FPGA Rx
27 | output avr_rx, // AVR Rx => FPGA Tx
28 | input avr_rx_busy, // AVR Rx buffer full
29 | output pin50
30 | );
31 |
32 | wire rst = ~rst_n; // make reset active high
33 |
34 | // these signals should be high-z when not used
35 | assign spi_miso = 1'bz;
36 | assign avr_rx = 1'bz;
37 | assign spi_channel = 4'bzzzz;
38 |
39 | // Main loop for FizzBuzz
40 | fizzbuzz fizzbuzz(
41 | .clk(clk),
42 | .rst(rst),
43 | .led(led),
44 | .out(pin50)
45 | );
46 |
47 | endmodule
48 |
--------------------------------------------------------------------------------
/src/serial.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | // Serial output module.
3 | // Output a character using RS232 protocol (8N1) and 9600 baud
4 | // Ken Shirriff http://righto.com
5 |
6 | module serial(
7 | input clk,
8 | input rst,
9 | input [7:0] char, // Character to output
10 | input send, // High = request a send
11 | output reg out, // Output pin
12 | output busy // High while character is being output
13 | );
14 |
15 | // Busy while not in IDLE state
16 | assign busy = (state == IDLE) ? 1'b0 : 1'b1;
17 |
18 | // Divide 50 MHz by 5208 to get approximately 9600 baud
19 | localparam DIVISOR = 13'd5208;
20 | reg [12:0] counter;
21 |
22 | localparam SPACE = 1'b0, MARK = 1'b1;
23 |
24 | reg [3:0] state; // Bit counter
25 | localparam IDLE = 4'd0, START = 4'd1, BIT0 = 4'd2, BIT1 = 4'd3,
26 | BIT2 = 4'd4, BIT3 = 4'd5, BIT4 = 4'd6, BIT5 = 4'd7, BIT6 = 4'd8,
27 | BIT7 = 4'd9, STOP = 4'd10;
28 |
29 | reg [7:0] char1;
30 |
31 | always @(posedge clk) begin
32 | if (rst) begin
33 | state <= IDLE;
34 | counter <= 0;
35 | end else if (state == IDLE) begin
36 | // Wait for a send request
37 | if (send == 1) begin
38 | state <= START;
39 | counter <= 0;
40 | char1 <= char;
41 | end
42 | end else begin
43 | if (counter < DIVISOR - 1) begin
44 | // Keep counting to the end of the bit time
45 | counter <= counter + 1'b1;
46 | end else begin
47 | // End of bit time. Reset counter and move to next state.
48 | counter <= 0;
49 | if (state != STOP) begin
50 | state <= state + 1'b1;
51 | end else begin
52 | state <= IDLE;
53 | end
54 | end
55 | end
56 | end
57 |
58 | // Output the appropriate level depending on state
59 | always @(*) begin
60 | case (state)
61 | IDLE: out = MARK; // Stop bit is also IDLE
62 | START: out = SPACE;
63 | BIT0: out = char1[0];
64 | BIT1: out = char1[1];
65 | BIT2: out = char1[2];
66 | BIT3: out = char1[3];
67 | BIT4: out = char1[4];
68 | BIT5: out = char1[5];
69 | BIT6: out = char1[6];
70 | BIT7: out = char1[7];
71 | default: out = MARK;
72 | endcase
73 | end
74 |
75 | endmodule
76 |
--------------------------------------------------------------------------------
/src/serial_rx.v:
--------------------------------------------------------------------------------
1 | module serial_rx #(
2 | parameter CLK_PER_BIT = 50
3 | )(
4 | input clk,
5 | input rst,
6 | input rx,
7 | output [7:0] data,
8 | output new_data
9 | );
10 |
11 | // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value
12 | parameter CTR_SIZE = $clog2(CLK_PER_BIT);
13 |
14 | localparam STATE_SIZE = 2;
15 | localparam IDLE = 2'd0,
16 | WAIT_HALF = 2'd1,
17 | WAIT_FULL = 2'd2,
18 | WAIT_HIGH = 2'd3;
19 |
20 | reg [CTR_SIZE-1:0] ctr_d, ctr_q;
21 | reg [2:0] bit_ctr_d, bit_ctr_q;
22 | reg [7:0] data_d, data_q;
23 | reg new_data_d, new_data_q;
24 | reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
25 | reg rx_d, rx_q;
26 |
27 | assign new_data = new_data_q;
28 | assign data = data_q;
29 |
30 | always @(*) begin
31 | rx_d = rx;
32 | state_d = state_q;
33 | ctr_d = ctr_q;
34 | bit_ctr_d = bit_ctr_q;
35 | data_d = data_q;
36 | new_data_d = 1'b0;
37 |
38 | case (state_q)
39 | IDLE: begin
40 | bit_ctr_d = 3'b0;
41 | ctr_d = 1'b0;
42 | if (rx_q == 1'b0) begin
43 | state_d = WAIT_HALF;
44 | end
45 | end
46 | WAIT_HALF: begin
47 | ctr_d = ctr_q + 1'b1;
48 | if (ctr_q == (CLK_PER_BIT >> 1)) begin
49 | ctr_d = 1'b0;
50 | state_d = WAIT_FULL;
51 | end
52 | end
53 | WAIT_FULL: begin
54 | ctr_d = ctr_q + 1'b1;
55 | if (ctr_q == CLK_PER_BIT - 1) begin
56 | data_d = {rx_q, data_q[7:1]};
57 | bit_ctr_d = bit_ctr_q + 1'b1;
58 | ctr_d = 1'b0;
59 | if (bit_ctr_q == 3'd7) begin
60 | state_d = WAIT_HIGH;
61 | new_data_d = 1'b1;
62 | end
63 | end
64 | end
65 | WAIT_HIGH: begin
66 | if (rx_q == 1'b1) begin
67 | state_d = IDLE;
68 | end
69 | end
70 | default: begin
71 | state_d = IDLE;
72 | end
73 | endcase
74 |
75 | end
76 |
77 | always @(posedge clk) begin
78 | if (rst) begin
79 | ctr_q <= 1'b0;
80 | bit_ctr_q <= 3'b0;
81 | new_data_q <= 1'b0;
82 | state_q <= IDLE;
83 | end else begin
84 | ctr_q <= ctr_d;
85 | bit_ctr_q <= bit_ctr_d;
86 | new_data_q <= new_data_d;
87 | state_q <= state_d;
88 | end
89 |
90 | rx_q <= rx_d;
91 | data_q <= data_d;
92 | end
93 |
94 | endmodule
--------------------------------------------------------------------------------
/src/serial_tb.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | // Testbench for the serial output module
4 | // Ken Shirriff http://righto.com
5 | module serial_tb;
6 |
7 | reg clk, rst, send;
8 | reg [7:0] char;
9 | wire out, busy;
10 |
11 | // Instantiate the Unit Under Test (UUT)
12 | serial uut (
13 | .clk(clk),
14 | .rst(rst),
15 | .char(char),
16 | .send(send),
17 | .out(out),
18 | .busy(busy)
19 | );
20 |
21 | initial begin
22 | clk = 1'b0;
23 | rst = 1'b1;
24 | repeat(4) #10 clk = ~clk;
25 | rst = 1'b0;
26 | forever #10 clk = ~clk;
27 | end
28 |
29 | initial begin
30 | send = 0;
31 | # 10000; // Wait for reset
32 | char = 8'b01000010; // ASCII 'B'
33 | send = 1;
34 | #20;
35 | send = 0;
36 | #20
37 | while (busy) #10;
38 | char = 8'b10101010;
39 | send = 1;
40 | #20
41 | send = 0;
42 | while (busy) #10;
43 | # 100
44 | $finish;
45 | end
46 |
47 | endmodule
48 |
49 |
--------------------------------------------------------------------------------
/src/serial_tx.v:
--------------------------------------------------------------------------------
1 | module serial_tx #(
2 | parameter CLK_PER_BIT = 50
3 | )(
4 | input clk,
5 | input rst,
6 | output tx,
7 | input block,
8 | output busy,
9 | input [7:0] data,
10 | input new_data
11 | );
12 |
13 | // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value
14 | parameter CTR_SIZE = $clog2(CLK_PER_BIT);
15 |
16 | localparam STATE_SIZE = 2;
17 | localparam IDLE = 2'd0,
18 | START_BIT = 2'd1,
19 | DATA = 2'd2,
20 | STOP_BIT = 2'd3;
21 |
22 | reg [CTR_SIZE-1:0] ctr_d, ctr_q;
23 | reg [2:0] bit_ctr_d, bit_ctr_q;
24 | reg [7:0] data_d, data_q;
25 | reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
26 | reg tx_d, tx_q;
27 | reg busy_d, busy_q;
28 | reg block_d, block_q;
29 |
30 | assign tx = tx_q;
31 | assign busy = busy_q;
32 |
33 | always @(*) begin
34 | block_d = block;
35 | ctr_d = ctr_q;
36 | bit_ctr_d = bit_ctr_q;
37 | data_d = data_q;
38 | state_d = state_q;
39 | busy_d = busy_q;
40 |
41 | case (state_q)
42 | IDLE: begin
43 | if (block_q) begin
44 | busy_d = 1'b1;
45 | tx_d = 1'b1;
46 | end else begin
47 | busy_d = 1'b0;
48 | tx_d = 1'b1;
49 | bit_ctr_d = 3'b0;
50 | ctr_d = 1'b0;
51 | if (new_data) begin
52 | data_d = data;
53 | state_d = START_BIT;
54 | busy_d = 1'b1;
55 | end
56 | end
57 | end
58 | START_BIT: begin
59 | busy_d = 1'b1;
60 | ctr_d = ctr_q + 1'b1;
61 | tx_d = 1'b0;
62 | if (ctr_q == CLK_PER_BIT - 1) begin
63 | ctr_d = 1'b0;
64 | state_d = DATA;
65 | end
66 | end
67 | DATA: begin
68 | busy_d = 1'b1;
69 | tx_d = data_q[bit_ctr_q];
70 | ctr_d = ctr_q + 1'b1;
71 | if (ctr_q == CLK_PER_BIT - 1) begin
72 | ctr_d = 1'b0;
73 | bit_ctr_d = bit_ctr_q + 1'b1;
74 | if (bit_ctr_q == 7) begin
75 | state_d = STOP_BIT;
76 | end
77 | end
78 | end
79 | STOP_BIT: begin
80 | busy_d = 1'b1;
81 | tx_d = 1'b1;
82 | ctr_d = ctr_q + 1'b1;
83 | if (ctr_q == CLK_PER_BIT - 1) begin
84 | state_d = IDLE;
85 | end
86 | end
87 | default: begin
88 | state_d = IDLE;
89 | end
90 | endcase
91 | end
92 |
93 | always @(posedge clk) begin
94 | if (rst) begin
95 | state_q <= IDLE;
96 | tx_q <= 1'b1;
97 | end else begin
98 | state_q <= state_d;
99 | tx_q <= tx_d;
100 | end
101 |
102 | block_q <= block_d;
103 | data_q <= data_d;
104 | bit_ctr_q <= bit_ctr_d;
105 | ctr_q <= ctr_d;
106 | busy_q <= busy_d;
107 | end
108 |
109 | endmodule
--------------------------------------------------------------------------------
/src/spi_slave.v:
--------------------------------------------------------------------------------
1 | module spi_slave(
2 | input clk,
3 | input rst,
4 | input ss,
5 | input mosi,
6 | output miso,
7 | input sck,
8 | output done,
9 | input [7:0] din,
10 | output [7:0] dout
11 | );
12 |
13 | reg mosi_d, mosi_q;
14 | reg ss_d, ss_q;
15 | reg sck_d, sck_q;
16 | reg sck_old_d, sck_old_q;
17 | reg [7:0] data_d, data_q;
18 | reg done_d, done_q;
19 | reg [2:0] bit_ct_d, bit_ct_q;
20 | reg [7:0] dout_d, dout_q;
21 | reg miso_d, miso_q;
22 |
23 | assign miso = miso_q;
24 | assign done = done_q;
25 | assign dout = dout_q;
26 |
27 | always @(*) begin
28 | ss_d = ss;
29 | mosi_d = mosi;
30 | miso_d = miso_q;
31 | sck_d = sck;
32 | sck_old_d = sck_q;
33 | data_d = data_q;
34 | done_d = 1'b0;
35 | bit_ct_d = bit_ct_q;
36 | dout_d = dout_q;
37 |
38 | if (ss_q) begin
39 | bit_ct_d = 3'b0;
40 | data_d = din;
41 | miso_d = data_q[7];
42 | end else begin
43 | if (!sck_old_q && sck_q) begin // rising edge
44 | data_d = {data_q[6:0], mosi_q};
45 | bit_ct_d = bit_ct_q + 1'b1;
46 | if (bit_ct_q == 3'b111) begin
47 | dout_d = {data_q[6:0], mosi_q};
48 | done_d = 1'b1;
49 | data_d = din;
50 | end
51 | end else if (sck_old_q && !sck_q) begin // falling edge
52 | miso_d = data_q[7];
53 | end
54 | end
55 | end
56 |
57 | always @(posedge clk) begin
58 | if (rst) begin
59 | done_q <= 1'b0;
60 | bit_ct_q <= 3'b0;
61 | dout_q <= 8'b0;
62 | miso_q <= 1'b1;
63 | end else begin
64 | done_q <= done_d;
65 | bit_ct_q <= bit_ct_d;
66 | dout_q <= dout_d;
67 | miso_q <= miso_d;
68 | end
69 |
70 | sck_q <= sck_d;
71 | mosi_q <= mosi_d;
72 | ss_q <= ss_d;
73 | data_q <= data_d;
74 | sck_old_q <= sck_old_d;
75 |
76 | end
77 |
78 |
79 | endmodule
80 |
--------------------------------------------------------------------------------
/syn/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------