mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
179 lines
5.1 KiB
Verilog
179 lines
5.1 KiB
Verilog
// Copyright 2011 Altera Corporation. All rights reserved.
|
|
// Altera products are protected under numerous U.S. and foreign patents,
|
|
// maskwork rights, copyrights and other intellectual property laws.
|
|
//
|
|
// This reference design file, and your use thereof, is subject to and governed
|
|
// by the terms and conditions of the applicable Altera Reference Design
|
|
// License Agreement (either as signed by you or found at www.altera.com). By
|
|
// using this reference design file, you indicate your acceptance of such terms
|
|
// and conditions between you and Altera Corporation. In the event that you do
|
|
// not agree with such terms and conditions, you may not use the reference
|
|
// design file and please promptly destroy any copies you have made.
|
|
//
|
|
// This reference design file is being provided on an "as-is" basis and as an
|
|
// accommodation and therefore all warranties, representations or guarantees of
|
|
// any kind (whether express, implied or statutory) including, without
|
|
// limitation, warranties of merchantability, non-infringement, or fitness for
|
|
// a particular purpose, are specifically disclaimed. By making this reference
|
|
// design file available, Altera expressly does not recommend, suggest or
|
|
// require that this reference design file be used in combination with any
|
|
// other product not provided by Altera.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// baeckler - 09-22-2008
|
|
|
|
module lane_tx (
|
|
input clk,arst,
|
|
input [64:0] din, // bit [64] = 1 indicates control word
|
|
output din_ack,
|
|
output [19:0] dout
|
|
);
|
|
|
|
`include "log2.inc"
|
|
|
|
// call all data non-inverted, for debug
|
|
parameter DISABLE_DISPARITY = 1'b0;
|
|
|
|
// the RESET_VAL must be non-zero and
|
|
// for noise should be unique per TX lane
|
|
parameter SCRAMBLER_RESET = 58'h1234567_89abcdef;
|
|
|
|
parameter META_FRAME_LEN = 10; // words per metaframe
|
|
localparam META_CNTR_BITS = log2(META_FRAME_LEN-1);
|
|
|
|
parameter PN_REVERSE = 1'b0;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// this is the schedule for sending 20 words to the gearbox
|
|
// every 67 cycles in order to maintain continuous output.
|
|
reg [66:0] schedule /* synthesis preserve */;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) schedule <= 67'b1001001000100100100010010010001001001000100100100010010010001001000;
|
|
else schedule <= {schedule[65:0],schedule[66]};
|
|
end
|
|
|
|
/////////////////////////////////////////
|
|
// Where are we within the metaframe?
|
|
|
|
reg [META_CNTR_BITS-1:0] meta_cntr;
|
|
reg meta_cntr_max;
|
|
reg send_sync_word,send_scram_state,send_skip,send_payload,send_diag;
|
|
|
|
wire advance_meta = schedule[61];
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
meta_cntr <= 0;
|
|
meta_cntr_max <= 0;
|
|
send_sync_word <= 0;
|
|
send_scram_state <= 0;
|
|
send_skip <= 0;
|
|
send_payload <= 0;
|
|
send_diag <= 0;
|
|
end
|
|
else begin
|
|
if (advance_meta) begin
|
|
meta_cntr_max <= (meta_cntr == META_FRAME_LEN-2);
|
|
if (meta_cntr_max) meta_cntr <= 0;
|
|
else meta_cntr <= meta_cntr + 1'b1;
|
|
|
|
send_sync_word <= ~|meta_cntr;
|
|
send_scram_state <= send_sync_word;
|
|
send_skip <= send_scram_state;
|
|
send_payload <= send_payload | send_skip;
|
|
send_diag <= 1'b0;
|
|
if (meta_cntr == (META_FRAME_LEN-1)) begin
|
|
send_payload <= 1'b0;
|
|
send_diag <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
assign din_ack = schedule[61] & send_payload;
|
|
|
|
/////////////////////////
|
|
// 32 bit meta frame CRC
|
|
wire [1:0] status_bits = 2'b11;
|
|
wire [31:0] crc;
|
|
lane_tx_crc ltc (
|
|
.clk(clk),
|
|
.arst(arst),
|
|
.din(din[63:0]),
|
|
.previous_din_ack(din_ack),
|
|
.final_din_of_burst(send_diag),
|
|
.status_bits(status_bits), // to be embedded in the diagnostic word
|
|
.crc(crc)
|
|
);
|
|
|
|
/////////////////////////
|
|
// Scrambler
|
|
wire [63:0] scrambler_q;
|
|
wire scrambler_evolve = advance_meta & !send_sync_word & !send_scram_state;
|
|
|
|
scrambler_lfsr scr (
|
|
.clk(clk),
|
|
.arst(arst),
|
|
.verify(1'b0),
|
|
.load(1'b0),
|
|
.load_d(58'h0),
|
|
.evolve(scrambler_evolve),
|
|
.q(scrambler_q),
|
|
.verify_pass(),
|
|
.verify_fail()
|
|
);
|
|
defparam scr .RESET_VAL = SCRAMBLER_RESET;
|
|
|
|
/////////////////////////
|
|
// transmit data select
|
|
reg [64:0] tx_din;
|
|
reg stick_in_crc;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
tx_din <= 0;
|
|
stick_in_crc <= 0;
|
|
end
|
|
else begin
|
|
stick_in_crc <= 1'b0;
|
|
if (send_sync_word)
|
|
tx_din <= {1'b1,64'h78f678f678f678f6};
|
|
else if (send_skip)
|
|
tx_din <= {1'b1,({6'b000111,58'h21e1e1e1e1e1e1e} ^ scrambler_q)};
|
|
else if (send_scram_state)
|
|
tx_din <= {1'b1,6'b001010,scrambler_q[63:6]};
|
|
else if (send_diag) begin
|
|
tx_din <= {1'b1,({6'b011001,24'h000000,status_bits,32'h00000000} ^ scrambler_q)};
|
|
stick_in_crc <= 1'b1;
|
|
end
|
|
else
|
|
tx_din <= {din[64],(din[63:0] ^ scrambler_q)};
|
|
|
|
end
|
|
end
|
|
|
|
/////////////////////////
|
|
// 64-67 disparity encoder
|
|
wire [66:0] gb_data;
|
|
enc_64_67 enc (
|
|
.clk(clk),
|
|
.arst(arst),
|
|
.din((stick_in_crc ? (crc ^ 32'hffffffff) : 32'h0) ^ tx_din), // bit 64=1 indicates control word
|
|
.din_fresh(schedule[62]),
|
|
.pn_reverse(PN_REVERSE),
|
|
.dout(gb_data)
|
|
);
|
|
defparam enc .DISABLE_DISPARITY = DISABLE_DISPARITY;
|
|
|
|
/////////////////////////
|
|
// 67 to 20 bit gearbox
|
|
gearbox_67_20 gb (
|
|
.clk(clk),
|
|
.arst(arst),
|
|
.din(gb_data),
|
|
.din_valid(schedule[66]),
|
|
.dout(dout)
|
|
);
|
|
|
|
endmodule
|