`timescale 1 ns / 1 ps module adg1414_if# ( parameter CLK_PERIOD = 10 , parameter CLK_DIV = 4 , // max: 255 parameter DATA_WIDTH = 64 , parameter T_SYNC_MIN = 100 // Unit: ns ) ( input clk , input rst_n , output reg s_tready , input s_tvalid , input [DATA_WIDTH-1:0] s_tdata , output sync , output reg sclk , output sdin ); //***************************************************************************** // Parameter definition //***************************************************************************** localparam CNT_POS = CLK_DIV/2 ; localparam CNT_NEG = 0 ; localparam IDLE = 8'd0 ; localparam TRANS_ST = 8'd1 ; localparam END_ST = 8'd2 ; localparam T_DELAY = T_SYNC_MIN/CLK_PERIOD ; //***************************************************************************** // Internal register and wire declarations //***************************************************************************** reg [ 4-1:0] cstate ; reg [ 4-1:0] nstate ; reg [DATA_WIDTH-1:0] tx_data ; reg clk_en ; reg [ 8-1:0] cnt ; reg sck_pos ; reg sck_neg ; reg [ 8-1:0] trans_cnt ; reg [ 8-1:0] t_cnt ; //***************************************************************************** // Instantiation //***************************************************************************** //***************************************************************************** always@( posedge clk or negedge rst_n ) begin if( !rst_n ) cstate <= IDLE; else cstate <= nstate; end always@( * ) begin case ( cstate ) IDLE: if ( s_tvalid ) nstate <= TRANS_ST; else nstate <= IDLE; TRANS_ST: if( (trans_cnt == 0) && sck_pos ) nstate <= END_ST; else nstate <= TRANS_ST; END_ST: if (t_cnt == T_DELAY-1) nstate <= IDLE; else nstate <= END_ST; default: nstate <= IDLE; endcase end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) s_tready <= 1'b0; else if ( nstate == IDLE ) s_tready <= 1'b1; else if ( cstate == IDLE && nstate == IDLE ) s_tready <= 1'b1; else s_tready <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin tx_data <= 0; end else if ( s_tready && s_tvalid ) begin tx_data <= s_tdata; end end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) clk_en <= 0; else if ( ((cstate == IDLE) && (nstate == TRANS_ST)) || ((cstate == TRANS_ST) && (nstate != END_ST)) ) clk_en <= 1'b1; else if ( nstate == END_ST ) clk_en <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) cnt <= 0; else if ( !clk_en ) cnt <= 0; else if ( cnt == CLK_DIV-1 ) cnt <= 0; else cnt <= cnt + 1; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) sck_pos <= 0; else if ( clk_en && (cnt == CNT_POS) ) sck_pos <= 1; else sck_pos <= 0; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) sck_neg <= 0; else if ( clk_en && (cnt == CNT_NEG) ) sck_neg <= 1; else sck_neg <= 0; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) sclk <= 1'b1; else if ( sck_pos && nstate == TRANS_ST || cstate == END_ST ) sclk <= 1'b1; else if ( sck_neg ) sclk <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) trans_cnt <= DATA_WIDTH - 1; else if ( cstate == IDLE ) trans_cnt <= DATA_WIDTH - 1; else if ( sck_pos && (trans_cnt != 0) ) trans_cnt <= trans_cnt - 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if( !rst_n ) t_cnt <= 0; else if ( cstate != END_ST ) t_cnt <= 0; else t_cnt <= t_cnt + 1'b1; end //***************************************************************************** // Wire assignment //***************************************************************************** assign sync = (cstate == IDLE || cstate == END_ST)? 1'b1 : 1'b0; assign sdin = tx_data[trans_cnt]; endmodule