├── .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 | 32 | 33 | 37 | 38 | 43 | 44 | 45 | 56 | 57 | 83 | 148 | 149 | 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 --------------------------------------------------------------------------------