mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
203 lines
6.0 KiB
Verilog
203 lines
6.0 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-23-2008
|
|
|
|
module frame_sync_control (
|
|
input clk, arst,
|
|
input [64:0] din,
|
|
input din_valid,
|
|
input word_locked,
|
|
output reg sync_locked,
|
|
output good_sync,
|
|
output missing_sync,
|
|
|
|
output scrambler_load,
|
|
output scrambler_evolve,
|
|
input scrambler_match,
|
|
input scrambler_mismatch,
|
|
|
|
output check_crc32
|
|
);
|
|
|
|
`include "log2.inc"
|
|
|
|
parameter META_FRAME_LEN = 10; // words per metaframe
|
|
localparam META_CNTR_BITS = log2(META_FRAME_LEN-1);
|
|
|
|
/////////////////////////////////////////
|
|
//
|
|
reg sync_detected;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) sync_detected <= 0;
|
|
else if (din_valid) sync_detected <= (din == {1'b1,64'h78f678f678f678f6});
|
|
end
|
|
|
|
/////////////////////////////////////////
|
|
// Where are we within the metaframe?
|
|
|
|
reg [META_CNTR_BITS-1:0] meta_cntr;
|
|
reg meta_cntr_max;
|
|
reg expect_sync_word,expect_scram_state,expect_skip,expect_payload,expect_diag;
|
|
wire advance_meta = din_valid;
|
|
reg hold_meta;
|
|
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
meta_cntr <= 0;
|
|
meta_cntr_max <= 0;
|
|
expect_sync_word <= 0;
|
|
expect_scram_state <= 0;
|
|
expect_skip <= 0;
|
|
expect_diag <= 0;
|
|
end
|
|
else begin
|
|
if (hold_meta) begin
|
|
// freeze waiting for the sync word
|
|
meta_cntr <= 1;
|
|
meta_cntr_max <= 0;
|
|
expect_sync_word <= 1'b1;
|
|
expect_scram_state <= 0;
|
|
expect_skip <= 0;
|
|
expect_diag <= 0;
|
|
end
|
|
else 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;
|
|
|
|
expect_sync_word <= ~|meta_cntr;
|
|
expect_scram_state <= expect_sync_word;
|
|
expect_skip <= expect_scram_state;
|
|
expect_payload <= expect_payload | expect_skip;
|
|
expect_diag <= 1'b0;
|
|
if (meta_cntr == (META_FRAME_LEN-1)) begin
|
|
expect_payload <= 1'b0;
|
|
expect_diag <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
/////////////////////////////////
|
|
// tally up expected or missing
|
|
// sync words
|
|
/////////////////////////////////
|
|
reg last_din_valid;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) last_din_valid <= 1'b0;
|
|
else last_din_valid <= din_valid;
|
|
end
|
|
assign good_sync = last_din_valid & expect_sync_word & sync_detected;
|
|
assign missing_sync = last_din_valid & expect_sync_word & !sync_detected;
|
|
|
|
reg [2:0] sync_tally;
|
|
reg rst_sync_tally, inc_sync_tally;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) sync_tally <= 0;
|
|
else begin
|
|
if (rst_sync_tally) sync_tally <= 0;
|
|
else if (inc_sync_tally) sync_tally <= sync_tally + 1'b1;
|
|
end
|
|
end
|
|
|
|
/////////////////////////////////
|
|
// Watch the scrambler synch
|
|
// 3 consecutive problems = lost lock
|
|
/////////////////////////////////
|
|
reg [1:0] scramble_miss_cntr;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
scramble_miss_cntr <= 0;
|
|
end
|
|
else begin
|
|
if (scrambler_match | !sync_locked)
|
|
scramble_miss_cntr <= 0;
|
|
else if (scrambler_mismatch & (scramble_miss_cntr != 2'b11))
|
|
scramble_miss_cntr <= scramble_miss_cntr + 1'b1;
|
|
end
|
|
end
|
|
|
|
/////////////////////////////////
|
|
// tell the scrambler and CRC what to do
|
|
/////////////////////////////////
|
|
assign scrambler_load = last_din_valid & expect_scram_state;
|
|
assign scrambler_evolve = last_din_valid &
|
|
(!expect_sync_word & !expect_scram_state);
|
|
assign check_crc32 = last_din_valid & expect_diag;
|
|
|
|
/////////////////////////////////
|
|
// Little control machine
|
|
// implementing figure 5-10 from Interlaken 1.1 spec
|
|
/////////////////////////////////
|
|
localparam ST_RESET = 2'h0,
|
|
ST_SEARCH = 2'h1,
|
|
ST_VERIFY = 2'h2,
|
|
ST_LOCKED = 2'h3;
|
|
|
|
reg [1:0] state,next_state;
|
|
|
|
always @(*) begin
|
|
next_state = state;
|
|
sync_locked = 1'b0;
|
|
inc_sync_tally = 1'b0;
|
|
rst_sync_tally = 1'b0;
|
|
hold_meta = 1'b0;
|
|
|
|
case (state)
|
|
ST_RESET : begin
|
|
next_state = ST_SEARCH;
|
|
end
|
|
ST_SEARCH : begin
|
|
hold_meta = 1'b1;
|
|
rst_sync_tally = 1'b1;
|
|
if (good_sync) next_state = ST_VERIFY;
|
|
end
|
|
ST_VERIFY : begin
|
|
// I want to see 3 more consecutive good sync words to lock
|
|
if (good_sync) inc_sync_tally = 1'b1;
|
|
if (missing_sync) next_state = ST_SEARCH;
|
|
else if (sync_tally == 3'b011) begin
|
|
next_state = ST_LOCKED;
|
|
rst_sync_tally = 1'b1;
|
|
end
|
|
end
|
|
ST_LOCKED : begin
|
|
// Drop lock if there are
|
|
// 4 consecutive bad sync words
|
|
// 3 consecutive scrambler state problems
|
|
sync_locked = 1'b1;
|
|
if (missing_sync) inc_sync_tally = 1'b1;
|
|
if (good_sync) rst_sync_tally = 1'b1;
|
|
else if (sync_tally == 3'b100 || scramble_miss_cntr == 2'b11)
|
|
next_state = ST_SEARCH;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) state <= ST_RESET;
|
|
else state <= (!word_locked ? ST_RESET : next_state);
|
|
end
|
|
|
|
endmodule |