// Max ASCII = 255 (extended) module piano #( parameter CLOCK_FREQ = 125_000_000 ) ( input clk, input rst, input [2:0] buttons, input [1:0] switches, output [5:0] leds, output reg [7:0] ua_tx_din, output reg ua_tx_wr_en, input ua_tx_full, input [7:0] ua_rx_dout, input ua_rx_empty, output reg ua_rx_rd_en, output [23:0] tone ); reg [7:0] address; wire [7:0] last_addr; wire [23:0] rom_out; assign tone = (curr_state == PLAY) ? rom_out : 24'd0; assign leds[0] = (ua_rx_rd_en & !ua_rx_empty); assign leds[1] = ua_rx_empty; assign leds[2] = (ua_rx_dout != 8'd0); assign leds[3] = (curr_state == PLAY); assign leds[4] = (ua_rx_rd_en); assign leds[5] = temp; piano_scale_rom rom ( .address(address), .data(rom_out), .last_address(last_addr) ); // Delay /* verilator lint_off WIDTH */ localparam [22:0] BASE_DELAY = 5_000_000; localparam [18:0] DELTA_TEMPO = 500_000; localparam [24:0] MAX_DELAY = ~0 - DELTA_TEMPO; reg [24:0] delay; always @(posedge clk) begin casez ({switches[0], buttons[0], rst}) 3'b??1 : delay <= BASE_DELAY; 3'b110 : begin if (delay > DELTA_TEMPO) delay <= delay - DELTA_TEMPO; end 3'b010 : begin if (delay < MAX_DELAY) delay <= delay + DELTA_TEMPO; end default : delay <= delay; endcase end /* lint_on */ // Tone generator reg [24:0] clk_counter; always @(posedge clk) begin if (rst) clk_counter <= 0; else if (clk_counter == delay - 1) clk_counter <= 0; else clk_counter <= clk_counter + 1; end // FSM reg [1:0] next_state, curr_state; localparam [1:0] READ = 2'b00, PAD = 2'b01, WRITE = 2'b10, PLAY = 2'b11; reg temp = 0; always @(posedge clk) begin if (rst) begin address <= 0; ua_rx_rd_en <= 0; ua_tx_wr_en <= 0; ua_tx_din <= 0; end else begin next_state = curr_state; case (curr_state) READ : begin if (!ua_rx_empty) begin ua_rx_rd_en <= 1; temp <= 1; ua_tx_wr_en <= 0; next_state = PAD; end end PAD : begin ua_rx_rd_en <= 0; ua_tx_wr_en <= 0; next_state = WRITE; end WRITE : begin if (!ua_tx_full) begin ua_rx_rd_en <= 0; ua_tx_wr_en <= 1; ua_tx_din <= ua_rx_dout; address <= ua_rx_dout; // for clarity next_state = PLAY; end end PLAY : begin if (clk_counter != delay - 1) begin ua_rx_rd_en <= 0; ua_tx_wr_en <= 0; end else next_state = READ; end default : begin next_state = READ; end endcase end end always @ (posedge clk) begin if (rst) begin curr_state <= READ; end else curr_state <= next_state; end endmodule