Files
2024-10-28 13:14:49 +08:00

174 lines
4.1 KiB
Verilog

`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