1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

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