Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
7 views

code

The document describes a Verilog module for a WM8731 audio codec controller and a wave generator. It includes the configuration of the codec via I2C, audio clock generation, and audio data serialization. Additionally, it features a testbench for simulating the wave generator and codec interaction, allowing for different waveforms and parameters to be tested.

Uploaded by

Võ Thành Trung
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

code

The document describes a Verilog module for a WM8731 audio codec controller and a wave generator. It includes the configuration of the codec via I2C, audio clock generation, and audio data serialization. Additionally, it features a testbench for simulating the wave generator and codec interaction, allowing for different waveforms and parameters to be tested.

Uploaded by

Võ Thành Trung
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

module wm8731_controller (

input logic clk,

input logic reset_n,

input logic signed [23:0] sample_data,

output logic init_done,

// I2C interface

inout wire i2c_sclk,

inout wire i2c_sdat,

// CODEC interface

output logic aud_xck,

output logic aud_bclk,

output logic aud_dacdat,

output logic aud_daclrck

);

// Constants

localparam CODEC_I2C_ADDR = 7'h1A; // WM8731 I2C address (0011010)

localparam NUM_CONFIG_REGS = 10;

// I2C Controller Signals

logic i2c_start;

logic i2c_busy;

logic [23:0] i2c_data;

// Audio transmission signals

logic [23:0] audio_sample;

logic sample_valid;

logic sample_ready;

// Configuration state machine


logic [3:0] config_state;

logic [3:0] config_index;

// Audio clock generation

logic [1:0] mclk_count; // Chia 4 (2 bit)

logic [1:0] bclk_count; // Chia 4 (2 bit)

logic [5:0] lrclk_count; // Chia 64 (6 bit)

// Configuration registers for WM8731

logic [15:0] codec_configs [0:NUM_CONFIG_REGS-1];

// Initialize configuration data for WM8731 based on register map

initial begin

// R0 (0x00) - Left Line In: Vol=0x17 (~0dB), không mute

codec_configs[0] = 16'h0017;

// R1 (0x02) - Right Line In: Vol=0x17 (~0dB), không mute

codec_configs[1] = 16'h0217;

// R2 (0x04) - Left Headphone Out: Vol=0x79 (0dB)

codec_configs[2] = 16'h0479;

// R3 (0x06) - Right Headphone Out: Vol=0x79 (0dB)

codec_configs[3] = 16'h0679;

// R4 (0x08) - Analog Audio Path: DAC enabled, Bypass disabled, Line Input enabled

codec_configs[4] = 16'h0810;

// R5 (0x0A) - Digital Audio Path: Không de-emphasis, không mute

codec_configs[5] = 16'h0A00;

// R6 (0x0C) - Power Down Control: Không power down (tất cả đều on)
codec_configs[6] = 16'h0C00;

// R7 (0x0E) - Digital Audio Interface: I2S format, 24-bit, Master mode

codec_configs[7] = 16'h0E02; // Bit 2-1 = 01 (24-bit), Bit 0 = 0 (master)

// R8 (0x10) - Sampling Control: Normal mode, 256fs, 48kHz

codec_configs[8] = 16'h1000; // 48kHz, 256fs oversampling

// R9 (0x12) - Active Control: Active

codec_configs[9] = 16'h1201;

end

// I2C configuration state machine

always_ff @(posedge clk or negedge reset_n) begin

if (!reset_n) begin

config_state <= 4'd0;

config_index <= 4'd0;

i2c_start <= 1'b0;

init_done <= 1'b0;

i2c_data <= 24'd0;

end else begin

case (config_state)

4'd0: begin // Idle state

if (config_index < NUM_CONFIG_REGS) begin

config_state <= 4'd1;

end else begin

init_done <= 1'b1;

end

end

4'd1: begin // Start I2C write

// [23:17]=địa chỉ thiết bị (7 bit), [16]=R/W bit (0=write)


// [15:9]=địa chỉ thanh ghi (7 bit), [8:1]=dữ liệu (8 bit)

i2c_data <= {CODEC_I2C_ADDR, 1'b0, codec_configs[config_index]};

i2c_start <= 1'b1;

config_state <= 4'd2;

end

4'd2: begin // Wait for I2C completion

i2c_start <= 1'b0;

if (!i2c_busy) begin

config_index <= config_index + 4'd1;

config_state <= 4'd0;

end

end

default: config_state <= 4'd0;

endcase

end

end

// Generate master clock (12.5MHz from 50MHz)

always_ff @(posedge clk or negedge reset_n) begin

if (!reset_n) begin

mclk_count <= 2'd0;

aud_xck <= 1'b0;

end else begin

if (mclk_count == 2'd1) begin // Chia 2 cho mỗi nửa chu kỳ = chia 4 cho cả chu kỳ

mclk_count <= 2'd0;

aud_xck <= ~aud_xck;

end else begin

mclk_count <= mclk_count + 2'd1;

end

end
end

// Generate bit clock (BCLK = 3.125MHz từ 12.5MHz MCLK) - Chia 4

always_ff @(posedge aud_xck or negedge reset_n) begin

if (!reset_n) begin

bclk_count <= 2'd0;

aud_bclk <= 1'b0;

end else begin

if (bclk_count == 2'd1) begin

bclk_count <= 2'd0;

aud_bclk <= ~aud_bclk;

end else begin

bclk_count <= bclk_count + 2'd1;

end

end

end

// Generate LR clock (LRCLK = ~48.8kHz từ 3.125MHz BCLK) - Chia 64

always_ff @(posedge aud_bclk or negedge reset_n) begin

if (!reset_n) begin

lrclk_count <= 6'd0;

aud_daclrck <= 1'b0;

end else begin

if (lrclk_count == 6'd31) begin // Chia 32 cho mỗi nửa chu kỳ = chia 64 cho cả chu kỳ

lrclk_count <= 6'd0;

aud_daclrck <= ~aud_daclrck;

// Sample new audio data at LRCK transition

if (aud_daclrck == 1'b0) begin

audio_sample <= sample_data;

end

end else begin


lrclk_count <= lrclk_count + 6'd1;

end

end

end

// Audio data serialization

logic [4:0] bit_counter;

logic [23:0] shift_reg;

always_ff @(negedge aud_bclk or negedge reset_n) begin

if (!reset_n) begin

bit_counter <= 5'd0;

shift_reg <= 24'd0;

aud_dacdat <= 1'b0;

end else begin

// Reset or load shift register on LRCK edge

if (lrclk_count == 6'd0 || lrclk_count == 6'd32) begin

bit_counter <= 5'd0;

shift_reg <= audio_sample;

end

// Shift out MSB first, 24 bits per sample

if (bit_counter < 5'd24) begin

aud_dacdat <= shift_reg[23];

shift_reg <= {shift_reg[22:0], 1'b0};

bit_counter <= bit_counter + 5'd1;

end

end

end

// I2C Master module

i2c_master i2c_control (
.clk (clk),

.reset_n (reset_n),

.i2c_data (i2c_data),

.start (i2c_start),

.busy (i2c_busy),

.sclk (i2c_sclk),

.sdat (i2c_sdat)

);

Endmodule

module wave_gen_top (

// System inputs

input logic CLOCK_50,

input logic [3:0] KEY,

input logic [9:0] SW,

// CODEC Interface

output logic AUD_XCK,

output logic AUD_BCLK,

output logic AUD_DACDAT,

output logic AUD_DACLRCK,

inout wire I2C_SDAT,

inout wire I2C_SCLK

);

// Internal signals

logic reset_n;

logic signed [23:0] wave_data;

logic codec_init_done;

// Assign reset signal

assign reset_n = KEY[0]; // Active low reset


// Control signals from switches

logic noise_en;

logic [1:0] wave_sel;

logic [2:0] amp_sel;

logic [2:0] freq_sel;

// Assign switches to controls

assign noise_en = SW[0];

assign wave_sel = SW[2:1];

assign amp_sel = SW[5:3];

assign freq_sel = SW[8:6];

// Wave generator module

wave_gen generator (

.i_clk (CLOCK_50),

.i_rst_n (reset_n),

.i_noise_en (noise_en),

.i_wave_sel (wave_sel),

.i_amp_sel (amp_sel),

.i_freq_sel (freq_sel),

.o_wave (wave_data)

);

// WM8731 Audio CODEC controller

wm8731_controller codec (

.clk (CLOCK_50),

.reset_n (reset_n),

.sample_data (wave_data),

.init_done (codec_init_done),

// I2C interface

.i2c_sclk (I2C_SCLK),
.i2c_sdat (I2C_SDAT),

// CODEC interface

.aud_xck (AUD_XCK),

.aud_bclk (AUD_BCLK),

.aud_dacdat (AUD_DACDAT),

.aud_daclrck (AUD_DACLRCK)

);

Endmodule

`timescale 1ns/1ps

module wave_gen_tb;

// Testbench signals

logic clk ;

logic rst_n ;

logic noise_en;

logic [1:0] wave_sel;

logic [2:0] amp_sel ;

logic [2:0] freq_sel;

logic signed [23:0] wave_out;

// Audio CODEC signals

logic aud_dacdat;

logic aud_daclrck;

logic aud_bclk;

logic aud_xck;

wire i2c_sclk;

wire i2c_sdat;

// Khởi tạo đồng hồ

initial clk = 0;
// Tạo xung đồng hồ (50MHz -> 20ns period)

always #10 clk = ~clk;

// Instantiate wave_generator top module

wave_gen_top DUT (

.CLOCK_50 (clk),

.KEY ({3'b0, rst_n}),

.SW ({1'b0, freq_sel, amp_sel, wave_sel, noise_en}),

.AUD_XCK (aud_xck),

.AUD_BCLK (aud_bclk),

.AUD_DACDAT (aud_dacdat),

.AUD_DACLRCK(aud_daclrck),

.I2C_SCLK (i2c_sclk),

.I2C_SDAT (i2c_sdat)

);

// Probe the wave data from the generator for monitoring

assign wave_out = DUT.generator.o_wave;

initial begin

// Initialize signals

rst_n = 0;

noise_en = 0;

wave_sel = 0;

amp_sel = 0;

freq_sel = 0;

// Apply reset for 100ns

#100;

rst_n = 1;

// Test different wave types


// Sine wave, 100Hz, amp=1

noise_en = 1'b0;

wave_sel = 2'b00;

freq_sel = 3'b000;

amp_sel = 3'b011;

#300000;

// Sine wave with noise

noise_en = 1'b1;

wave_sel = 2'b00;

freq_sel = 3'b000;

amp_sel = 3'b011;

#300000;

// Square wave, 200Hz, amp=2

noise_en = 1'b0;

wave_sel = 2'b01;

freq_sel = 3'b001;

amp_sel = 3'b100;

#300000;

// Triangle wave, 500Hz, amp=0.5

noise_en = 1'b0;

wave_sel = 2'b10;

freq_sel = 3'b010;

amp_sel = 3'b010;

#300000;

// Sawtooth wave, 1kHz, amp=4

noise_en = 1'b0;

wave_sel = 2'b11;

freq_sel = 3'b011;
amp_sel = 3'b101;

#300000;

// Sine wave, high frequency

noise_en = 1'b0;

wave_sel = 2'b00;

freq_sel = 3'b101; // 10kHz

amp_sel = 3'b011;

#100000;

$finish;

end

// Add monitors

initial begin

$monitor("Time=%0t, Wave=%0d, Type=%0d, Freq=%0d, Amp=%0d, Noise=%0d",

$time, wave_out, wave_sel, freq_sel, amp_sel, noise_en);

end

endmodule

module wave_gen (

// Inputs

input logic i_clk ,

input logic i_rst_n ,

input logic i_noise_en,

input logic [ 1:0] i_wave_sel,

input logic [ 2:0] i_amp_sel ,

input logic [ 2:0] i_freq_sel,

// Outputs

output logic signed [23:0] o_wave

);
logic [23:0] phase_inc;

logic [23:0] phase ;

logic signed [23:0] lut_data;

logic signed [23:0] wave ;

logic signed [17:0] noise ;

// Frequency controller

freq_ctrl Frequency (

.i_freq_sel (i_freq_sel),

.o_phase_inc (phase_inc)

);

// DDS (Direct Digital Synthesis)

dds DDS (

.i_clk (i_clk) ,

.i_rst_n (i_rst_n) ,

.i_phase_inc (phase_inc),

.o_phase (phase)

);

// Lookup table for waveforms

lut LUT (

.i_wave_sel (i_wave_sel),

.i_phase (phase) ,

.o_data (lut_data)

);

// Amplitude controller

amp_ctrl Amplitude (

.i_data (lut_data) ,

.i_amp_sel (i_amp_sel),
.o_data (wave)

);

// Noise generator

noise_gen Noise (

.i_clk (i_clk) ,

.i_rst_n (i_rst_n),

.o_noise (noise)

);

// Mix wave with noise if enabled

always_comb begin

o_wave = i_noise_en ? (wave + noise) : wave;

end

endmodule

module noise_gen (

// Inputs

input logic i_clk ,

input logic i_rst_n,

// Output

output logic signed [17:0] o_noise

);

logic [17:0] lfsr_reg;

always_ff @(posedge i_clk or negedge i_rst_n) begin

if (!i_rst_n)

lfsr_reg <= 18'h2A3F5; // Arbitrary initial value

else

lfsr_reg <= {lfsr_reg[16:0], lfsr_reg[17] ^ lfsr_reg[16] ^ lfsr_reg[4] ^ lfsr_reg[0]};

end
assign o_noise = $signed(lfsr_reg);

endmodule

module lut (

input logic [ 1:0] i_wave_sel,

input logic [23:0] i_phase ,

output logic signed [23:0] o_data

);

logic [11:0] index;

logic signed [23:0] sine_wave [0:4095];

logic signed [23:0] square_wave [0:4095];

logic signed [23:0] triangle_wave [0:4095];

logic signed [23:0] sawtooth_wave [0:4095];

// Sử dụng đường dẫn tương đối (file trong cùng thư mục)

initial begin

$readmemh("sine_wave.hex", sine_wave);

$readmemh("square_wave.hex", square_wave);

$readmemh("triangle_wave.hex", triangle_wave);

$readmemh("sawtooth_wave.hex", sawtooth_wave);

end

assign index = i_phase[23:12];

always_comb begin

case (i_wave_sel)

2'b00: o_data = sine_wave[index];

2'b01: o_data = square_wave[index];

2'b10: o_data = triangle_wave[index];

2'b11: o_data = sawtooth_wave[index];

default: o_data = 24'd0;

endcase

end
endmodule

module freq_ctrl (

input logic [ 2:0] i_freq_sel ,

output logic [23:0] o_phase_inc

);

always_comb begin

case (i_freq_sel)

3'b000: o_phase_inc = 24'h000D1B; // 100 Hz

3'b001: o_phase_inc = 24'h001A35; // 200 Hz

3'b010: o_phase_inc = 24'h004189; // 500 Hz

3'b011: o_phase_inc = 24'h008311; // 1 kHz

3'b100: o_phase_inc = 24'h028F5B; // 5 kHz

3'b101: o_phase_inc = 24'h051EB7; // 10 kHz

3'b110: o_phase_inc = 24'h0A3D70; // 20 kHz

3'b111: o_phase_inc = 24'h0F5C29; // 30 kHz

default: o_phase_inc = 24'h000D1B; // default = 100 Hz

endcase

end

endmodule

module dds (

input logic i_clk ,

input logic i_rst_n ,

input logic [23:0] i_phase_inc,

output logic [23:0] o_phase

);

always_ff @(posedge i_clk or negedge i_rst_n) begin

if (!i_rst_n) begin

o_phase <= 24'd0;

end else begin

o_phase <= o_phase + i_phase_inc;

end

end
endmodule

module amp_ctrl (

input logic signed [23:0] i_data ,

input logic [ 2:0] i_amp_sel,

output logic signed [23:0] o_data

);

always_comb begin

case (i_amp_sel)

3'b000: o_data = i_data >>> 3; // amp/8

3'b001: o_data = i_data >>> 2; // amp/4

3'b010: o_data = i_data >>> 1; // amp/2

3'b011: o_data = i_data ; // amp

3'b100: o_data = i_data << 1 ; // amp*2

3'b101: o_data = i_data << 2 ; // amp*4

3'b110: o_data = i_data << 3 ; // amp*8

default: o_data = i_data ;

endcase

end

endmodule

module i2c_master (

input logic clk,

input logic reset_n,

input logic [23:0] i2c_data, // [23:16]=địa chỉ, [15:8]=địa chỉ thanh ghi, [7:0]=dữ liệu

input logic start,

output logic busy,

inout wire sclk,

inout wire sdat

);

// I2C States

localparam IDLE = 4'd0;

localparam START = 4'd1;


localparam ADDR_MSB = 4'd2; // Gửi 7 bit địa chỉ + 1 bit R/W (luôn là Write)

localparam ACK1 = 4'd3;

localparam REG_ADDR = 4'd4; // Gửi 7 bit địa chỉ thanh ghi + 1 bit trong thanh ghi

localparam ACK2 = 4'd5;

localparam DATA = 4'd6; // Gửi 8 bit dữ liệu

localparam ACK3 = 4'd7;

localparam STOP = 4'd8;

// I2C control signals

logic [3:0] state;

logic [3:0] bit_count;

logic [23:0] shift_reg;

logic sda_out;

logic scl_out;

logic sda_oe;

logic scl_oe;

// I2C clock generation (100kHz từ 50MHz)

// Theo datasheet, tần số SCLK tối đa là 400kHz, nên 100kHz là an toàn

logic [8:0] clk_count;

logic i2c_clk;

logic i2c_clk_en;

// Generate I2C clock enable

always_ff @(posedge clk or negedge reset_n) begin

if (!reset_n) begin

clk_count <= 9'd0;

i2c_clk_en <= 1'b0;

end else begin

if (clk_count == 9'd249) begin // 50MHz/500 = 100kHz

clk_count <= 9'd0;

i2c_clk_en <= 1'b1;


end else begin

clk_count <= clk_count + 9'd1;

i2c_clk_en <= 1'b0;

end

end

end

// I2C state machine

always_ff @(posedge clk or negedge reset_n) begin

if (!reset_n) begin

state <= IDLE;

bit_count <= 4'd0;

shift_reg <= 24'd0;

sda_out <= 1'b1;

scl_out <= 1'b1;

sda_oe <= 1'b1;

scl_oe <= 1'b1;

busy <= 1'b0;

i2c_clk <= 1'b0;

end else if (i2c_clk_en) begin

// Toggle I2C clock for SCL generation

i2c_clk <= ~i2c_clk;

case (state)

IDLE: begin

// Default states

scl_out <= 1'b1;

sda_out <= 1'b1;

sda_oe <= 1'b1;

scl_oe <= 1'b1;

busy <= 1'b0;


if (start) begin

state <= START;

shift_reg <= i2c_data;

busy <= 1'b1;

end

end

START: begin

if (i2c_clk) begin

// Tạo điều kiện START: SDA chuyển từ HIGH sang LOW khi SCL đang HIGH

sda_out <= 1'b0;

state <= ADDR_MSB;

bit_count <= 4'd0;

end

end

ADDR_MSB: begin

if (i2c_clk) begin

// Gửi 7 bit địa chỉ (0011010x) + 1 bit R/W(0 = write)

scl_out <= 1'b0;

end else begin

if (bit_count < 4'd8) begin

sda_out <= (bit_count == 4'd7) ? 1'b0 : shift_reg[23-bit_count]; // Bit thứ 8 là bit R/W = 0 (Write)

bit_count <= bit_count + 4'd1;

scl_out <= 1'b1;

end else begin

state <= ACK1;

scl_out <= 1'b0;

end

end

end
ACK1: begin

if (i2c_clk) begin

sda_oe <= 1'b0; // Giải phóng SDA để CODEC có thể ACK

scl_out <= 1'b1;

end else begin

scl_out <= 1'b0;

sda_oe <= 1'b1; // Lấy lại quyền điều khiển SDA

state <= REG_ADDR;

bit_count <= 4'd0;

end

end

REG_ADDR: begin

if (i2c_clk) begin

// Gửi 8 bit địa chỉ thanh ghi (7 bits address + 1 bit đầu của data)

scl_out <= 1'b0;

end else begin

if (bit_count < 4'd8) begin

sda_out <= shift_reg[15-bit_count];

bit_count <= bit_count + 4'd1;

scl_out <= 1'b1;

end else begin

state <= ACK2;

scl_out <= 1'b0;

end

end

end

ACK2: begin

if (i2c_clk) begin

sda_oe <= 1'b0; // Giải phóng SDA để CODEC có thể ACK

scl_out <= 1'b1;


end else begin

scl_out <= 1'b0;

sda_oe <= 1'b1; // Lấy lại quyền điều khiển SDA

state <= DATA;

bit_count <= 4'd0;

end

end

DATA: begin

if (i2c_clk) begin

// Gửi 8 bits dữ liệu cho thanh ghi

scl_out <= 1'b0;

end else begin

if (bit_count < 4'd8) begin

// Từ bit 8 (MSB) đến bit 1 (LSB)

sda_out <= shift_reg[7-bit_count];

bit_count <= bit_count + 4'd1;

scl_out <= 1'b1;

end else begin

state <= ACK3;

scl_out <= 1'b0;

end

end

end

ACK3: begin

if (i2c_clk) begin

sda_oe <= 1'b0; // Giải phóng SDA để CODEC có thể ACK

scl_out <= 1'b1;

end else begin

scl_out <= 1'b0;

sda_oe <= 1'b1; // Lấy lại quyền điều khiển SDA


sda_out <= 1'b0; // Chuẩn bị cho trạng thái STOP

state <= STOP;

end

end

STOP: begin

if (i2c_clk) begin

// Tạo điều kiện STOP: SDA chuyển từ LOW sang HIGH khi SCL đang HIGH

scl_out <= 1'b1;

end else begin

if (scl_out) begin

sda_out <= 1'b1;

state <= IDLE;

end

end

end

default: state <= IDLE;

endcase

end

end

// I2C tri-state control

assign sdat = sda_oe ? sda_out : 1'bz;

assign sclk = scl_oe ? scl_out : 1'bz;

endmodule

# wave_gen.sdc - SDC file cải tiến

# Clock definitions

create_clock -name CLOCK_50 -period 20.000 [get_ports CLOCK_50]


# Derived clocks

create_generated_clock -name MCLK -source [get_ports CLOCK_50] -divide_by 4 \

[get_registers {wm8731_controller:codec|aud_xck}]

create_generated_clock -name BCLK -source [get_registers {wm8731_controller:codec|aud_xck}] -divide_by 4 \

[get_registers {wm8731_controller:codec|aud_bclk}]

create_generated_clock -name LRCLK -source [get_registers {wm8731_controller:codec|aud_bclk}] -divide_by 64


\

[get_registers {wm8731_controller:codec|aud_daclrck}]

# Set false path between clock domains

set_false_path -from [get_clocks CLOCK_50] -to [get_clocks MCLK]

set_false_path -from [get_clocks MCLK] -to [get_clocks BCLK]

set_false_path -from [get_clocks BCLK] -to [get_clocks LRCLK]

set_false_path -from [get_clocks LRCLK] -to [get_clocks BCLK]

set_false_path -from [get_clocks BCLK] -to [get_clocks MCLK]

set_false_path -from [get_clocks MCLK] -to [get_clocks CLOCK_50]

# Input delay constraints

set_input_delay -clock CLOCK_50 -max 5.0 [get_ports {KEY[*]}]

set_input_delay -clock CLOCK_50 -min 1.0 [get_ports {KEY[*]}]

set_input_delay -clock CLOCK_50 -max 5.0 [get_ports {SW[*]}]

set_input_delay -clock CLOCK_50 -min 1.0 [get_ports {SW[*]}]

# Output delay constraints

set_output_delay -clock MCLK -max 3.0 [get_ports AUD_XCK]

set_output_delay -clock MCLK -min 1.0 [get_ports AUD_XCK]

set_output_delay -clock BCLK -max 3.0 [get_ports AUD_BCLK]

set_output_delay -clock BCLK -min 1.0 [get_ports AUD_BCLK]

set_output_delay -clock LRCLK -max 3.0 [get_ports {AUD_DACDAT AUD_DACLRCK}]

set_output_delay -clock LRCLK -min 1.0 [get_ports {AUD_DACDAT AUD_DACLRCK}]

# I2C signals can be slow, so add appropriate constraints


set_output_delay -clock CLOCK_50 -max 10.0 [get_ports {I2C_SCLK I2C_SDAT}]

set_output_delay -clock CLOCK_50 -min 1.0 [get_ports {I2C_SCLK I2C_SDAT}]

set_input_delay -clock CLOCK_50 -max 10.0 [get_ports {I2C_SCLK I2C_SDAT}]

set_input_delay -clock CLOCK_50 -min 1.0 [get_ports {I2C_SCLK I2C_SDAT}]

# I2C signals are bi-directional and have special considerations

set_false_path -to [get_ports {I2C_SCLK I2C_SDAT}]

set_false_path -from [get_ports {I2C_SCLK I2C_SDAT}]

# Set multicycle paths for slower clock domains

set_multicycle_path -from [get_clocks CLOCK_50] -to [get_clocks MCLK] -setup 2

set_multicycle_path -from [get_clocks CLOCK_50] -to [get_clocks MCLK] -hold 1

set_multicycle_path -from [get_clocks MCLK] -to [get_clocks BCLK] -setup 2

set_multicycle_path -from [get_clocks MCLK] -to [get_clocks BCLK] -hold 1

set_multicycle_path -from [get_clocks BCLK] -to [get_clocks LRCLK] -setup 4

set_multicycle_path -from [get_clocks BCLK] -to [get_clocks LRCLK] -hold 3

# Asynchronous interfaces - manual controls from switches and buttons

set_false_path -from [get_ports {KEY[*] SW[*]}] -to *

# Derive clock uncertainty

derive_clock_uncertainty

You might also like