Commit 7194dbb0 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

replaced elastic buffer, simulated, tested

parent 0c64eabc
Loading
Loading
Loading
Loading
+17 −17
Original line number Diff line number Diff line
@@ -52,87 +52,87 @@
		<link>
			<name>vivado_logs/VivadoBitstream.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoOpt.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoOptPhys.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoOptPower.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoPlace.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoRoute.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoSynthesis.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160203212221686.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160204124820270.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160203212221686.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160204124820270.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoTimingReportImplemented.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160203212454764.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160204125242916.log</location>
		</link>
		<link>
			<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160203212221686.log</location>
			<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160204124820270.log</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-opt-phys.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160203212454764.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160204125242916.dcp</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-opt-power.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160203212454764.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160204125242916.dcp</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-opt.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160203212454764.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160204125242916.dcp</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-place.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160203212454764.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160204125242916.dcp</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-route.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160203212454764.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160204125242916.dcp</location>
		</link>
		<link>
			<name>vivado_state/x393_sata-synth.dcp</name>
			<type>1</type>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160203212221686.dcp</location>
			<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160204124820270.dcp</location>
		</link>
	</linkedResources>
</projectDescription>

host/elastic1632.v

0 → 100644
+170 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: elastic1632
 * Date:2016-02-03  
 * Author: andrey     
 * Description: Elastic buffer with 16-bit data input and 32-bit output
 *
 * Copyright (c) 2016 Elphel, Inc .
 * elastic1632.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  elastic1632.v is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  elastic1632#(
    parameter DEPTH_LOG2 =  4,   // => 16 total rows x16 is for free in Xilinx, but keep it asymmetrical to reduce
                                 // latency
    parameter OFFSET =  5        // distance between read and write pointers, = wr_ptr - rd_ptr 
)(
    input             wclk,
    input             rclk,

    input             isaligned_in,
    input       [1:0] charisk_in,
    input       [1:0] notintable_in,
    input       [1:0] disperror_in,
    input      [15:0] data_in,
 
    output            isaligned_out,
    output reg  [3:0] charisk_out,
    output reg  [3:0] notintable_out,
    output reg  [3:0] disperror_out,
    output reg [31:0] data_out,

//  status outputs, just in case
    output            full,
    output            empty

);
localparam ALIGN_PRIM = 32'h7B4A4ABC;
localparam FIFO_DEPTH = 1 << DEPTH_LOG2;
localparam CORR_OFFSET = OFFSET - 0;
reg            [15:0] data_in_r;
reg             [1:0] charisk_in_r;
reg             [1:0] notintable_in_r;
reg             [1:0] disperror_in_r;
reg                   aligned32_in_r;  // input data is word-aligned and got ALIGNp
reg                   msb_in_r;      // input contains MSB
reg                   inc_waddr;
reg    [DEPTH_LOG2:0] waddr;
wire [DEPTH_LOG2-1:0] waddr_minus = waddr[DEPTH_LOG2-1:0] - 1;
reg    [DEPTH_LOG2:0] raddr;
reg            [44:0] fifo_ram    [0: FIFO_DEPTH -1];
reg             [0:0] prealign_ram[0: FIFO_DEPTH -1];
reg  [FIFO_DEPTH-1:0] fill;
wire [FIFO_DEPTH-1:0] fill_out;
wire [FIFO_DEPTH-1:0] fill_1;
reg             [2:0] aligned_rclk;
reg             [1:0] dav_rclk;
wire                  skip_rclk;
wire                  add_rclk;
wire           [44:0] rdata = fifo_ram[raddr[DEPTH_LOG2-1:0]];
wire                  align_out = rdata[44];
wire                  pre_align_out = prealign_ram[raddr[DEPTH_LOG2-1:0]];
reg                   align_out_r;
reg             [2:0] correct_r;
wire                  correct = align_out && (!align_out_r || (pre_align_out && !correct_r[2]));


reg             [1:0] full_0; // full at waddr = waddr
reg             [1:0] full_1; // full at waddr = raddr+1



wire is_alignp_w = ({data_in,       data_in_r} ==       ALIGN_PRIM) &&
                   ({charisk_in,    charisk_in_r} ==    4'h1) &&
                   ({notintable_in, notintable_in_r} == 0) &&
                   ({disperror_in,  disperror_in_r} ==  0);

wire  [DEPTH_LOG2:0] dbg_diff = waddr-raddr;
wire                 dbg_dav1 = dav_rclk[1];
wire                 dbg_full0 = full_0[1];
wire                 dbg_full1 = full_1[1];

genvar ii;
generate
    for (ii = 0; ii < FIFO_DEPTH; ii = ii + 1)
    begin: gen_fill_out
        assign fill_out[ii] =            fill[(ii + CORR_OFFSET) & (FIFO_DEPTH-1)] ^ ((ii + CORR_OFFSET)>=FIFO_DEPTH);
        assign fill_1[ii] =              fill[(ii + 1) & (FIFO_DEPTH-1)] ^ ((ii + 1)>=FIFO_DEPTH);
    end
endgenerate
                   
// FIFO write clock domain - read data synchronous, 150MHz for SATA2
always @(posedge wclk) begin
    data_in_r <= data_in;
    charisk_in_r <= charisk_in;
    notintable_in_r <= notintable_in;
    disperror_in_r <= disperror_in;
    
    if    (!isaligned_in) aligned32_in_r <= 0;
    else if (is_alignp_w) aligned32_in_r <= 1;
    
    if (!aligned32_in_r && !is_alignp_w) msb_in_r <= 1;
    else                                 msb_in_r <= !msb_in_r;
    
    inc_waddr <= !msb_in_r || (is_alignp_w && !aligned32_in_r);
    
    if (!aligned32_in_r)  waddr <= 0;
    else if (inc_waddr)   waddr <= waddr + 1;
    
    // write will be active before aligned32_in_r too
    if (msb_in_r) fifo_ram[waddr[DEPTH_LOG2-1:0]] <= {is_alignp_w,
                                                      disperror_in,  disperror_in_r,
                                                      notintable_in, notintable_in_r,
                                                      charisk_in,    charisk_in_r,
                                                      data_in,       data_in_r};
    if (msb_in_r) prealign_ram[waddr_minus] <= is_alignp_w;
                                                      
    if (!aligned32_in_r)  fill <= 0;
    else if (msb_in_r)    fill <={fill[FIFO_DEPTH-2:0],~waddr[DEPTH_LOG2]};
    
    
end

// FIFO read clock domain - system synchronous, 75MHz for SATA2
always @(posedge rclk) begin
    if (!aligned32_in_r) aligned_rclk <= 0;
    else                 aligned_rclk <= {aligned_rclk[1:0],fill[OFFSET-2] | aligned_rclk[0]};

    if (!aligned32_in_r) dav_rclk <= 0;
    else                 dav_rclk <= {dav_rclk[0],fill_out[raddr[DEPTH_LOG2-1:0]] ^ raddr[DEPTH_LOG2]};
    
    if (!aligned32_in_r) full_0 <= 1;
    else                 full_0 <= {full_0[0], fill[raddr[DEPTH_LOG2-1:0]] ^ raddr[DEPTH_LOG2]};

    if (!aligned32_in_r) full_1 <= 1;
    else                 full_1 <= {full_1[0], fill_1[raddr[DEPTH_LOG2-1:0]] ^ raddr[DEPTH_LOG2]};
    

    if (!aligned_rclk[1]) raddr <=0;
    else if (!add_rclk)   raddr <= raddr + (skip_rclk ? 2 : 1);

    disperror_out <=  rdata[43:40];
    notintable_out <= rdata[39:36];
    charisk_out <=    rdata[35:32];
    data_out <=       rdata[31: 0];
    
    align_out_r <= align_out;

    if (correct || !aligned_rclk) correct_r <= ~0;
    else correct_r <= correct_r << 1;
    
end

assign skip_rclk = correct &&  dav_rclk[1];
assign add_rclk =  correct && !dav_rclk[1];
assign isaligned_out = aligned_rclk[2];
assign full =   full_1[1] && !full_0[1];
assign empty = !full_1[1] &&  full_0[1];
endmodule
+215 −207
Original line number Diff line number Diff line
@@ -94,16 +94,19 @@ module gtx_wrap #(

wire    rxresetdone_gtx; 
wire    txresetdone_gtx;
reg     rxresetdone_gtx_r; 
reg     txresetdone_gtx_r;
reg     wrap_rxreset_;
reg     wrap_txreset_;
`ifdef OLD_ELASTIC
    reg     rxresetdone_gtx_r; 
    reg     txresetdone_gtx_r;
    // resets while PCS resets, active low
always @ (posedge rxusrclk2)
    wrap_rxreset_ <= rxuserrdy & rxresetdone_gtx_r;
always @ (posedge txusrclk2)
    wrap_txreset_ <= txuserrdy & txresetdone_gtx_r;

    always @ (posedge rxusrclk2) wrap_rxreset_ <= rxuserrdy & rxresetdone_gtx_r;
    always @ (posedge txusrclk2) wrap_txreset_ <= txuserrdy & txresetdone_gtx_r;
`else // OLD_ELASTIC
    // resets while PCS resets, active low
    always @ (posedge rxusrclk2) wrap_rxreset_ <= rxuserrdy & rxresetdone_gtx;
    always @ (posedge txusrclk2) wrap_txreset_ <= txuserrdy & txresetdone_gtx;
`endif // OLD_ELASTIC
wire    [63:0]  rxdata_gtx;
wire    [7:0]   rxcharisk_gtx;
wire    [7:0]   rxdisperr_gtx;
@@ -213,62 +216,6 @@ if (DATA_BYTE_WIDTH == 4) begin
    assign  txcomwake_gtx       = txcomwake_gtx_f[0];
    assign  txelecidle_gtx      = txelecidle_gtx_f[0];
    
    
    /*wire    txdata_resync_nempty;
    reg     txdata_resync_nempty_r;
    reg     txdata_resync_nempty_rr;
    reg     txdata_resync_strobe;
    wire    [38:0] txdata_resync_out;
    reg     [35:0] txdata_resync;

    assign  txdata_enc_in       = {16{~txdata_resync_strobe}} & txdata_resync[15:0] | {16{txdata_resync_strobe}} & txdata_resync[31:16];
    assign  txcharisk_enc_in   = {2{~txdata_resync_strobe}} & txdata_resync[33:32] | {2{txdata_resync_strobe}} & txdata_resync[35:34];
    // Andrey: wrap_txreset_ has different clock domain
    always @ (posedge txusrclk)
    begin
        txdata_resync        <= ~wrap_txreset_ ? 36'h0 : ((txdata_resync_nempty & txdata_resync_strobe) ? txdata_resync_out[35:0] : txdata_resync);
        txdata_resync_strobe <= ~wrap_txreset_ ? 1'b0  : ((~txdata_resync_nempty) ? txdata_resync_strobe : ~txdata_resync_strobe); // -> 1 once every resynced dword = signal to latch it
    end

    // nempty_rr & nempty => shall be at least 2 elements in fifo
    always @ (posedge txusrclk2) 
    begin
        txdata_resync_nempty_r  <= txdata_resync_nempty;
        txdata_resync_nempty_rr <= txdata_resync_nempty_r;
    end

    fifo_cross_clocks #(
      .DATA_WIDTH (39),
      .DATA_DEPTH (4)
    )
    txdata_resynchro(
        .rst        (txreset),
        .rrst       (txreset),
        .wrst       (txreset),
        .rclk       (txusrclk),
        .wclk       (txusrclk2),
        .we         (1'b1),
        .re         (txdata_resync_nempty & txdata_resync_nempty_rr & txdata_resync_strobe),
        .data_in    ({txelecidle, txcominit, txcomwake, txcharisk, txdata}),
        .data_out   (txdata_resync_out),
        .nempty     (txdata_resync_nempty),
        .half_empty ()
    );


    reg txcomwake_gtx_f;
    reg txcominit_gtx_f;
    reg txelecidle_gtx_f;
    always @ (posedge txusrclk)
    begin
        txcomwake_gtx_f  <= txdata_resync_out[36];
        txcominit_gtx_f  <= txdata_resync_out[37];
        txelecidle_gtx_f <= txdata_resync_out[38];
    end
    assign  txcomwake_gtx  = txcomwake_gtx_f;
    assign  txcominit_gtx  = txcominit_gtx_f;
    assign  txelecidle_gtx = txelecidle_gtx_f;
    */
 end

else
@@ -397,6 +344,11 @@ gtx_10x8dec gtx_10x8dec(
    .notintable (rxnotintable_dec_out),
    .disperror  (rxdisperr_dec_out)
);
// iface resync
wire    rxcomwakedet_gtx;
wire    rxcominitdet_gtx;

`ifdef OLD_ELASTIC
    
    // elastic buffer: transition from xclk to rxusrclk
    wire    [15:0]  rxdata_els_out;
@@ -438,18 +390,6 @@ gtx_elastic(
    );
    
    // iface resync

/*
    output  wire    cplllock,       - async
    output  wire    rxbyteisaligned,- rxusrclk2
    output  wire    rxcomwakedet,   - rxusrclk2
    output  wire    rxcominitdet,   - rxusrclk2
    output  wire    rxelecidle,     - async
    output  wire    rxresetdone,    - rxusrclk2
    output  wire    txresetdone,    - txusrclk2
*/
wire    rxcomwakedet_gtx;
wire    rxcominitdet_gtx;
    reg     rxcomwakedet_gtx_r;
    reg     rxcominitdet_gtx_r;
    
@@ -482,9 +422,18 @@ if (DATA_BYTE_WIDTH == 4) begin
                                    rxcharisk_els_out,                     // 2
                                    rxdata_els_out,                        // 16
                                    rxdata_resync_buf[21:0]};              // 22 / 51 total
    always @ (posedge rxusrclk)
        rxdata_resync_buf    <= ~wrap_rxreset_ ? 26'h0 : ~rxdata_resync_strobe ? {rxcomwakedet_gtx_r, rxcominitdet_gtx_r, elastic_full, elastic_empty, rxdisperr_els_out, rxnotintable_els_out, rxcharisk_els_out, rxdata_els_out} : rxdata_resync_buf;

        always @ (posedge rxusrclk) begin
    ///        rxdata_resync_buf    <= ~wrap_rxreset_ ? 26'h0 : ~rxdata_resync_strobe ? {rxcomwakedet_gtx_r, rxcominitdet_gtx_r, elastic_full, elastic_empty, rxdisperr_els_out, rxnotintable_els_out, rxcharisk_els_out, rxdata_els_out} : rxdata_resync_buf;
            if      (!wrap_rxreset_)        rxdata_resync_buf <= 26'b0;
            else if (!rxdata_resync_strobe) rxdata_resync_buf <= {rxcomwakedet_gtx_r,
                                                                  rxcominitdet_gtx_r,
                                                                  elastic_full,
                                                                  elastic_empty,
                                                                  rxdisperr_els_out,
                                                                  rxnotintable_els_out,
                                                                  rxcharisk_els_out,
                                                                  rxdata_els_out};
        end 
        always @ (posedge rxusrclk2)
            rxdata_resync_nempty_r <= rxdata_resync_nempty;
    
@@ -517,9 +466,7 @@ if (DATA_BYTE_WIDTH == 4) begin
        assign  rxnotintable[3:0]   = {rxdata_resync_out[41:40], rxdata_resync_out[19:18]};
        assign  rxcharisk[3:0]      = {rxdata_resync_out[39:38], rxdata_resync_out[17:16]};
        assign  rxdata[31:0]        = {rxdata_resync_out[37:22], rxdata_resync_out[15:0] };
end
else
if (DATA_BYTE_WIDTH == 2) begin
    end else if (DATA_BYTE_WIDTH == 2) begin
        // no resync is needed => straightforward assignments
        assign  rxbyteisaligned = isaligned;
        assign  rxcomwakedet    = rxcomwakedet_gtx_r;
@@ -551,6 +498,67 @@ begin
        txresetdone_gtx_r   <= txresetdone_gtx;
    end
    
`else // OLD_ELASTIC
    elastic1632 #(
        .DEPTH_LOG2(4),
        .OFFSET(5)
    ) elastic1632_i (
        .wclk           (xclk),                               // input 150MHz, recovered
        .rclk           (rxusrclk2),                          // input 75 MHz, system
        .isaligned_in   (state_aligned && rxdlysresetdone_r), // input
        .charisk_in     (rxcharisk_dec_out),                  // input[1:0] 
        .notintable_in  (rxnotintable_dec_out),               // input[1:0] 
        .disperror_in   (rxdisperr_dec_out),                  // input[1:0] 
        .data_in        (rxdata_dec_out),                     // input[15:0] 
        .isaligned_out  (rxbyteisaligned),                    // output
        .charisk_out    (rxcharisk),                          // output[3:0] reg 
        .notintable_out (rxnotintable),                       // output[3:0] reg 
        .disperror_out  (rxdisperr),                          // output[3:0] reg 
        .data_out       (rxdata),                             // output[31:0] reg 
        .full           (rxelsfull),                          // output
        .empty          (rxelsempty)                          // output
    );
/*
    // What is left:
    assign  rxcomwakedet    = rxdata_resync_out[49];
    assign  rxcominitdet    = rxdata_resync_out[48];
    assign  rxresetdone     = rxdata_resync_out[47];
    assign  txresetdone     = rxdata_resync_out[46];

*/
    reg rxresetdone_r;
    reg txresetdone_r;
    always @ (posedge rxusrclk2) rxresetdone_r <= rxresetdone_gtx;
    always @ (posedge txusrclk2) txresetdone_r <= txresetdone_gtx;
    assign  rxresetdone     = rxresetdone_r;
    assign  txresetdone     = txresetdone_r;
    
    pulse_cross_clock #(
        .EXTRA_DLY(0)
    ) pulse_cross_clock_rxcominitdet_i (
        .rst       (~wrap_rxreset_),   // input
        .src_clk   (xclk),             // input
        .dst_clk   (rxusrclk2),        // input
        .in_pulse  (rxcominitdet_gtx), // input
        .out_pulse (rxcominitdet),     // output
        .busy      ()                  // output
    );
    
    pulse_cross_clock #(
        .EXTRA_DLY(0)
    ) pulse_cross_clock_rxcomwakedet_i (
        .rst       (~wrap_rxreset_),   // input
        .src_clk   (xclk),             // input
        .dst_clk   (rxusrclk2),        // input
        .in_pulse  (rxcomwakedet_gtx), // input
        .out_pulse (rxcomwakedet),     // output
        .busy      ()                  // output
    );
    

//rxusrclk2  

`endif //OLD_ELASTIC
wire    txoutclk_gtx;
wire    xclk_gtx;
//wire    xclk_mr;
+2 −0
Original line number Diff line number Diff line
eclipse.preferences.version=1
encoding/create_ahci_registers.py=utf-8
Loading