`timescale 1ns/1ns module z1top #( parameter CLOCK_FREQ = 125_000_000, parameter BAUD_RATE = 115_200, /* verilator lint_off REALCVT */ // Sample the button signal every 500us parameter integer B_SAMPLE_COUNT_MAX = 0.0005 * CLOCK_FREQ, // The button is considered 'pressed' after 100ms of continuous pressing parameter integer B_PULSE_COUNT_MAX = 0.100 / 0.0005 /* lint_on */ ) ( input CLK_125MHZ_FPGA, input [3:0] BUTTONS, input [1:0] SWITCHES, output [5:0] LEDS, output aud_pwm, output aud_sd, input FPGA_SERIAL_RX, output FPGA_SERIAL_TX ); localparam ASCII_LEN = 8; // 8-bit characters localparam FIFO_DEPTH = 16; // max depth necessary per lab instructions wire [2:0] buttons_pressed; wire reset; assign aud_sd = SWITCHES[1]; // Enable the audio output button_parser #( .width(4), .sample_count_max(B_SAMPLE_COUNT_MAX), .pulse_count_max(B_PULSE_COUNT_MAX) ) bp ( .clk(CLK_125MHZ_FPGA), .in(BUTTONS), .out({buttons_pressed, reset}) ); wire [7:0] data_in, data_out; wire data_in_ready, data_out_valid, data_out_ready; reg data_in_valid; // This UART is on the FPGA and communicates with your desktop // using the FPGA_SERIAL_TX, and FPGA_SERIAL_RX signals. The ready/valid // interface for this UART is used on the FPGA design. uart # ( .CLOCK_FREQ(CLOCK_FREQ), .BAUD_RATE(BAUD_RATE) ) on_chip_uart ( .clk(CLK_125MHZ_FPGA), .reset(reset), .data_in(data_in), // output data from transmitter FIFO .data_in_valid(data_in_valid), // transmitter FIFO is not empty .data_in_ready(data_in_ready), // UART transmitter is not running .data_out(data_out), // Forwarded to receiver FIFO's din .data_out_valid(data_out_valid), // Won't overwrite anything if receiver FIFO is full .data_out_ready(data_out_ready), // FIFO is not ready to receive if full .serial_in(FPGA_SERIAL_RX), .serial_out(FPGA_SERIAL_TX) ); // FIFO wires wire ua_rx_empty, ua_rx_full, ua_rx_rd_en; wire ua_tx_wr_en, ua_tx_empty, ua_tx_full; wire [7:0] ua_rx_dout, ua_tx_din; reg ua_tx_rd_en; // FIFO receiver logic assign data_out_ready = !ua_rx_full; always @(posedge CLK_125MHZ_FPGA) begin if (reset) begin ua_tx_rd_en <= 0; data_in_valid <= 0; end else begin ua_tx_rd_en <= (!ua_tx_empty & data_in_ready); data_in_valid <= ua_tx_rd_en; // data takes a cycle to be valid after read end end // Instantiate receiver's FIFO fifo # ( .data_width(ASCII_LEN), .fifo_depth(FIFO_DEPTH) ) receiver_fifo ( .clk(CLK_125MHZ_FPGA), .rst(reset), .wr_en(data_out_valid), // Write to FIFO if UART receiver data_out is valid .din(data_out), // Forward UART receiver data to receiver FIFO .full(ua_rx_full), // Flag if receiver FIFO is full to UART receiver .rd_en(ua_rx_rd_en), // Piano tries reading from FIFO .dout(ua_rx_dout), // Output of read from FIFO sent to piano .empty(ua_rx_empty) // Flag is receiver FIFO is empty to piano ); // Instantiate transmitter's FIFO fifo # ( .data_width(ASCII_LEN), .fifo_depth(FIFO_DEPTH) ) transmitter_fifo ( .clk(CLK_125MHZ_FPGA), .rst(reset), .wr_en(ua_tx_wr_en), // Piano tries writing ASCII char to FIFO .din(ua_tx_din), // ASCII char to write .full(ua_tx_full), // Is transmitter FIFO full? Output to piano .rd_en(ua_tx_rd_en), // Pull high when UART is ready .dout(data_in), // Data-in to UART transmitter is output of transmitter FIFO .empty(ua_tx_empty) // data_in_valid = !ua_tx_empty (assigned above) ); // Tone generator wires wire [23:0] tone; wire volume; // Force volume to be low. Originally controlled by SWITCHES[0] which now controls // tempo. Could keep it on SWITCHES[0], but it's less annoying this way. assign volume = 1'd0; // Instantiate tone generator tone_generator tg ( .clk(CLK_125MHZ_FPGA), .rst(reset), .output_enable(aud_sd), .tone_switch_period(tone), .volume(volume), .square_wave_out(aud_pwm) ); // Instantiate piano piano # ( .CLOCK_FREQ(CLOCK_FREQ) ) piano ( .clk(CLK_125MHZ_FPGA), .rst(reset), .buttons(buttons_pressed), .switches(SWITCHES), .leds(LEDS), .ua_tx_din(ua_tx_din), // ASCII echo to UART transmitter .ua_tx_wr_en(ua_tx_wr_en), // Try to write to transmitter FIFO .ua_tx_full(ua_tx_full), // Transmitter FIFO full? (input) .ua_rx_dout(ua_rx_dout), // Read from receiver FIFO dout .ua_rx_empty(ua_rx_empty), // Is receiver FIFO empty? .ua_rx_rd_en(ua_rx_rd_en), // Try to read from receiver FIFO .tone(tone) ); endmodule