EECS151 / fpga_labs_fa20 / lab6 / src / z1top.v
z1top.v
Raw
`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