Skip to content

MIPI Primitives updates #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions models_internal/verilog/MIPI_RX.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
`timescale 1ns/1ps
`celldefine
//
// MIPI_RX simulation model
// MIPI Receiver
//
// Copyright (c) 2023 Rapid Silicon, Inc. All rights reserved.
//

module MIPI_RX #(
parameter WIDTH = 4, // Width of input data to serializer (3-10)
parameter EN_IDLY = "FALSE", // True or False
parameter DELAY = 0 // Fixed TAP delay value (0-63)
) (
input RST, // Active-low, asynchronous reset
input RX_CLK, // MIPI RX_IO clock input, PLL_CLK
input PLL_LOCK, // PLL lock input
input CLK_IN, // Fabric core clock input
input RX_DP, // MIPI RX Data Positive input From I_BUF
input RX_DN, // MIPI RX Data Negative input from I_BUF
input HS_EN, // EN HS Data input (From Fabric). Active high signal. This is a common signal between MIPI RX/TX interface.
input LP_EN, // EN LP Data input (From Fabric). This is a common signal between MIPI RX/TX interface.
input RX_TERM_EN, // EN Differential Termination
input BITSLIP_ADJ, // BITSLIP_ADJ input from Fabric
input DLY_LOAD, // Delay load input, from Fabric
input DLY_ADJ, // Delay adjust input, from Fabric
input DLY_INCDEC, // Delay increment / decrement input, from Fabric
output [5:0] DLY_TAP_VALUE, // Delay tap value output to fabric
output [WIDTH-1:0] HS_RX_DATA, // HS RX Data output to Fabric
output HS_RXD_VALID, // HS RX Parallel DATA is VALID
output RX_OE, // IBUF OE signal for MIPI I_BUF
output LP_RX_DP, // LP RX Data positive output to the Fabric
output LP_RX_DN // LP RX Data negative output to the Fabric
);


wire i_delay_out;
wire rx_dp_delay;
wire rx_dn_delay;
wire rx_dp;
wire rx_dn;

I_DELAY # (
.DELAY(DELAY)
)
I_DELAY_inst (
.I(RX_DP),
.DLY_LOAD(DLY_LOAD),
.DLY_ADJ(DLY_ADJ),
.DLY_INCDEC(DLY_INCDEC),
.DLY_TAP_VALUE(DLY_TAP_VALUE),
.CLK_IN(CLK_IN),
.O(i_delay_out)
);

I_SERDES # (
.DATA_RATE("DDR"),
.WIDTH(WIDTH),
.DPA_MODE("NONE")
)
I_SERDES_inst (
.D(rx_dp),
.RST(RST),
.BITSLIP_ADJ(BITSLIP_ADJ),
.EN(HS_EN),
.CLK_IN(CLK_IN),
.CLK_OUT(CLK_OUT),
.Q(HS_RX_DATA),
.DATA_VALID(HS_RXD_VALID),
.DPA_LOCK(),
.DPA_ERROR(),
.PLL_LOCK(PLL_LOCK),
.PLL_CLK(RX_CLK)
);

assign RX_OE= HS_EN | LP_EN;
assign rx_dp_delay = (EN_IDLY=="FALSE")? RX_DP:i_delay_out;
assign rx_dn_delay = (EN_IDLY=="FALSE")? RX_DN:~i_delay_out;

assign rx_dp = RX_TERM_EN?1'bz:RX_OE?rx_dp_delay:'b0;
assign rx_dn = RX_TERM_EN?1'bz:RX_OE?rx_dn_delay:'b0;

assign LP_RX_DP = rx_dp;
assign LP_RX_DN = rx_dn;


always@(*)
begin
if(LP_EN && HS_EN)
$fatal(1,"\nERROR: MIPI RX instance %m LP_EN and HS_EN can't be hight at same time");
end

initial begin

if ((WIDTH < 3) || (WIDTH > 10)) begin
$fatal(1,"MIPI_RX instance %m WIDTH set to incorrect value, %d. Values must be between 3 and 10.", WIDTH);
end
case(EN_IDLY)
"TRUE" ,
"FALSE": begin end
default: begin
$fatal(1,"\nError: MIPI_RX instance %m has parameter EN_IDLY set to %s. Valid values are TRUE, FALSE\n", EN_IDLY);
end
endcase

if ((DELAY < 0) || (DELAY > 63)) begin
$fatal(1,"MIPI_RX instance %m DELAY set to incorrect value, %d. Values must be between 0 and 63.", DELAY);
end

end

endmodule
`endcelldefine
8 changes: 5 additions & 3 deletions models_internal/verilog/MIPI_TX.v
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ O_DELAY_inst (
end
end

assign TX_DP = (EN_ODLY=="FALSE")? tx_dp:o_delay_dout;
assign TX_DN = (EN_ODLY=="FALSE")? tx_dn:~o_delay_dout;
assign TX_DP = TX_ODT_EN?1'bz:(EN_ODLY=="FALSE")? tx_dp:o_delay_dout;
assign TX_DN = TX_ODT_EN?1'bz:(EN_ODLY=="FALSE")? tx_dn:~o_delay_dout;

// assign TX_DP = tx_dp;
// assign TX_DN = tx_dn;
Expand All @@ -96,7 +96,9 @@ O_DELAY_inst (
begin
if(LP_EN && HS_EN)
$fatal(1,"\nERROR: MIPI TX instance %m LP_EN and HS_EN can't be hight at same time");
end initial begin
end

initial begin

if ((WIDTH < 3) || (WIDTH > 10)) begin
$fatal(1,"MIPI_TX instance %m WIDTH set to incorrect value, %d. Values must be between 3 and 10.", WIDTH);
Expand Down
58 changes: 58 additions & 0 deletions models_internal/verilog/inc/MIPI_RX.inc.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@


wire i_delay_out;
wire rx_dp_delay;
wire rx_dn_delay;
wire rx_dp;
wire rx_dn;

I_DELAY # (
.DELAY(DELAY)
)
I_DELAY_inst (
.I(RX_DP),
.DLY_LOAD(DLY_LOAD),
.DLY_ADJ(DLY_ADJ),
.DLY_INCDEC(DLY_INCDEC),
.DLY_TAP_VALUE(DLY_TAP_VALUE),
.CLK_IN(CLK_IN),
.O(i_delay_out)
);

I_SERDES # (
.DATA_RATE("DDR"),
.WIDTH(WIDTH),
.DPA_MODE("NONE")
)
I_SERDES_inst (
.D(rx_dp),
.RST(RST),
.BITSLIP_ADJ(BITSLIP_ADJ),
.EN(HS_EN),
.CLK_IN(CLK_IN),
.CLK_OUT(CLK_OUT),
.Q(HS_RX_DATA),
.DATA_VALID(HS_RXD_VALID),
.DPA_LOCK(),
.DPA_ERROR(),
.PLL_LOCK(PLL_LOCK),
.PLL_CLK(RX_CLK)
);

assign RX_OE= HS_EN | LP_EN;
assign rx_dp_delay = (EN_IDLY=="FALSE")? RX_DP:i_delay_out;
assign rx_dn_delay = (EN_IDLY=="FALSE")? RX_DN:~i_delay_out;

assign rx_dp = RX_TERM_EN?1'bz:RX_OE?rx_dp_delay:'b0;
assign rx_dn = RX_TERM_EN?1'bz:RX_OE?rx_dn_delay:'b0;

assign LP_RX_DP = rx_dp;
assign LP_RX_DN = rx_dn;


always@(*)
begin
if(LP_EN && HS_EN)
$fatal(1,"\nERROR: MIPI RX instance %m LP_EN and HS_EN can't be hight at same time");
end

Empty file.
8 changes: 5 additions & 3 deletions models_internal/verilog/inc/MIPI_TX.inc.v
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ O_DELAY_inst (
end
end

assign TX_DP = (EN_ODLY=="FALSE")? tx_dp:o_delay_dout;
assign TX_DN = (EN_ODLY=="FALSE")? tx_dn:~o_delay_dout;
assign TX_DP = TX_ODT_EN?1'bz:(EN_ODLY=="FALSE")? tx_dp:o_delay_dout;
assign TX_DN = TX_ODT_EN?1'bz:(EN_ODLY=="FALSE")? tx_dn:~o_delay_dout;

// assign TX_DP = tx_dp;
// assign TX_DN = tx_dn;
Expand All @@ -61,4 +61,6 @@ O_DELAY_inst (
begin
if(LP_EN && HS_EN)
$fatal(1,"\nERROR: MIPI TX instance %m LP_EN and HS_EN can't be hight at same time");
end
end


167 changes: 167 additions & 0 deletions models_internal/verilog/tb/MIPI_RX_tb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
`timescale 1ns/1ps
module MIPI_RX_tb;

// Parameters
localparam WIDTH = 4 ;
localparam EN_IDLY = "FALSE";
localparam DELAY = 0;
localparam phase = 0;

//Ports
reg RST;
reg RX_CLK;
reg PLL_LOCK;
reg CLK_IN;
reg RX_DP;
reg RX_DN;
reg HS_EN;
reg LP_EN;
reg RX_TERM_EN;
reg BITSLIP_ADJ;
reg DLY_LOAD;
reg DLY_ADJ;
reg DLY_INCDEC;
wire [5:0] DLY_TAP_VALUE;
wire [WIDTH-1:0] HS_RX_DATA;
wire HS_RXD_VALID;
wire RX_OE;
wire LP_RX_DP;
wire LP_RX_DN;

real delay;

MIPI_RX # (
.WIDTH(WIDTH),
.EN_IDLY(EN_IDLY),
.DELAY(DELAY)
)
MIPI_RX_inst (
.RST(RST),
.RX_CLK(RX_CLK),
.PLL_LOCK(PLL_LOCK),
.CLK_IN(CLK_IN),
.RX_DP(RX_DP),
.RX_DN(RX_DN),
.HS_EN(HS_EN),
.LP_EN(LP_EN),
.RX_TERM_EN(RX_TERM_EN),
.BITSLIP_ADJ(BITSLIP_ADJ),
.DLY_LOAD(DLY_LOAD),
.DLY_ADJ(DLY_ADJ),
.DLY_INCDEC(DLY_INCDEC),
.DLY_TAP_VALUE(DLY_TAP_VALUE),
.HS_RX_DATA(HS_RX_DATA),
.HS_RXD_VALID(HS_RXD_VALID),
.RX_OE(RX_OE),
.LP_RX_DP(LP_RX_DP),
.LP_RX_DN(LP_RX_DN)
);

always #0.2 RX_CLK = ! RX_CLK ; // 2.5 GHz
always #0.8 CLK_IN = ! CLK_IN ;

initial
begin
CLK_IN=0;
RX_CLK=0;
PLL_LOCK=1;
RST=0;
DLY_LOAD=0;
DLY_ADJ=0;
DLY_INCDEC=0;
RX_DP=0;
HS_EN=0;
LP_EN=0;
BITSLIP_ADJ=0;
RX_TERM_EN=0;
delay=(phase==90)?0.1:(phase==180)?0.2:(phase==270)?0.3:0;
repeat(2)@(posedge RX_CLK);
RST=1;
RX_DP=0;
HS_EN=0;
repeat(63)
begin
@(posedge RX_CLK);
#(delay);
HS_EN=1;
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;
@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;

end

fork
begin
repeat(20)
begin
@(posedge RX_CLK);
#(delay);
HS_EN=1;
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;
@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;
end
@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;
@(posedge RX_CLK);
#(delay);
RX_DP=0;

@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=1;
@(posedge RX_CLK);
#(delay);
RX_DP=0;
@(posedge RX_CLK);
#(delay);
RX_DP=1;
end

begin
// bitslip
repeat(3)
begin
@(negedge CLK_IN);
BITSLIP_ADJ=1;
repeat(2)@(negedge CLK_IN);
BITSLIP_ADJ=0;
end
end
join_any
#1000;
$finish;

end

assign RX_DN = ~RX_DP;
initial
begin
$dumpfile("waves.vcd");
$dumpvars;
end
endmodule
Loading