module synth_config( input clock, input start, output busy, output sck, output sda ); // Divide main clock down to get the configuration clock (twice the I2C clock) reg i2c_clock = 0; reg [5:0] clock_div = 0; always @(posedge clock) begin clock_div <= clock_div + 1; if (clock_div == 0) begin i2c_clock <= ~i2c_clock; end end // Configuration data // // Each I2C transfer has this format: // // // A length of 0 indicates the end of the data. // reg [7:0] config_rom[31:0]; initial begin config_rom[5'h00] = 8'h03; config_rom[5'h01] = 8'hd2; config_rom[5'h02] = 8'h09; config_rom[5'h03] = 8'h20; // 09 config_rom[5'h04] = 8'h03; config_rom[5'h05] = 8'hd2; config_rom[5'h06] = 8'h0c; config_rom[5'h07] = 8'h08; // 0c config_rom[5'h08] = 8'h04; config_rom[5'h09] = 8'hd2; config_rom[5'h0a] = 8'h12; config_rom[5'h0b] = 8'h18; // 12 config_rom[5'h0c] = 8'h00; // 13 config_rom[5'h0d] = 8'h05; config_rom[5'h0e] = 8'hd2; config_rom[5'h0f] = 8'h40; config_rom[5'h10] = 8'hc8; // 40 config_rom[5'h11] = 8'hfc; // 41 config_rom[5'h12] = 8'h7b; // 42 config_rom[5'h13] = 8'h06; config_rom[5'h14] = 8'hd2; config_rom[5'h15] = 8'h44; config_rom[5'h16] = 8'h00; // 44 config_rom[5'h17] = 8'h01; // 45 config_rom[5'h18] = 8'hbf; // 46 config_rom[5'h19] = 8'h08; // 47 config_rom[5'h1a] = 8'h00; config_rom[5'h1b] = 8'h00; config_rom[5'h1c] = 8'h00; config_rom[5'h1d] = 8'h00; config_rom[5'h1e] = 8'h00; config_rom[5'h1f] = 8'h00; end reg i2c_start = 0; reg [7:0] i2c_data = 0; reg [4:0] length = 0, addr = 0, read_addr = 0; reg [7:0] read_data = 0; reg state_setup = 0, state_len = 0, state_data = 0, state_send = 0, state_stop = 0; wire i2c_done, i2c_busy; assign busy = state_setup | state_len | state_data | state_send | state_stop; i2c_write w(i2c_clock, i2c_start, i2c_busy, i2c_done, i2c_data, sck, sda); always @(posedge i2c_clock) begin read_data <= config_rom[read_addr]; case ({state_setup, state_len, state_data, state_send, state_stop}) 5'b0000: begin // Idle addr <= 0; read_addr <= 0; if (start == 1) begin state_setup <= 1; end end 5'b10000: begin // Setup // This state waits for the first byte to be read from config_rom state_setup <= 0; state_len <= 1; end 5'b01000: begin // Read length length <= read_data; addr <= addr + 1; read_addr <= addr + 1; state_len <= 0; state_data <= 1; end 5'b00100: begin // Read data if (length == 0) begin // End of data - go back to idle state_data <= 0; end else begin i2c_data <= read_data; i2c_start <= 1; // Wait for the last byte to finish (i2c_done goes low again). // i2c_start is sampled just before the falling edge of i2c_done. if (!i2c_done && i2c_busy) begin addr <= addr + 1; read_addr <= addr + 1; length <= length - 1; state_data <= 0; state_send <= 1; end end end 5'b00010: begin // Send data if (i2c_done) begin state_send <= 0; if (length != 0) begin state_data <= 1; end else begin state_stop <= 1; i2c_start <= 0; end end end 5'b00001: begin // Stop if (!i2c_done) begin state_stop <= 0; state_len <= 1; end end endcase end endmodule