mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
188 lines
7.3 KiB
Verilog
188 lines
7.3 KiB
Verilog
// Copyright 2008 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.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// baeckler - 09-19-2008
|
|
// Convert a 67 bit stream to a 20 bit stream
|
|
// Note : requires a specific din_valid schedule to avoid overflow.
|
|
//
|
|
module gearbox_67_20 (
|
|
input clk,arst,
|
|
input [66:0] din,
|
|
input din_valid,
|
|
output [19:0] dout
|
|
);
|
|
|
|
// worst case : 19 bits surplus, and 67 arriving = 86 bits
|
|
|
|
reg [85:0] storage;
|
|
reg [4:0] wr_ptr /* synthesis preserve */;
|
|
reg [4:0] next_wr_ptr;
|
|
reg [85:0] aligned_din;
|
|
|
|
//////////////////////////////////////////////////////
|
|
// This is a debug only sanity check
|
|
//////////////////////////////////////////////////////
|
|
// synthesis translate off
|
|
reg [85:0] aligned_din_mask;
|
|
reg [85:0] storage_mask;
|
|
|
|
always @(*) begin
|
|
case (wr_ptr)
|
|
5'd19 : aligned_din_mask = {67'h7ffffffffffffffff,19'b0};
|
|
5'd18 : aligned_din_mask = {1'b0,67'h7ffffffffffffffff,18'b0};
|
|
5'd17 : aligned_din_mask = {2'b0,67'h7ffffffffffffffff,17'b0};
|
|
5'd16 : aligned_din_mask = {3'b0,67'h7ffffffffffffffff,16'b0};
|
|
5'd15 : aligned_din_mask = {4'b0,67'h7ffffffffffffffff,15'b0};
|
|
5'd14 : aligned_din_mask = {5'b0,67'h7ffffffffffffffff,14'b0};
|
|
5'd13 : aligned_din_mask = {6'b0,67'h7ffffffffffffffff,13'b0};
|
|
5'd12 : aligned_din_mask = {7'b0,67'h7ffffffffffffffff,12'b0};
|
|
5'd11 : aligned_din_mask = {8'b0,67'h7ffffffffffffffff,11'b0};
|
|
5'd10 : aligned_din_mask = {9'b0,67'h7ffffffffffffffff,10'b0};
|
|
5'd9 : aligned_din_mask = {10'b0,67'h7ffffffffffffffff,9'b0};
|
|
5'd8 : aligned_din_mask = {11'b0,67'h7ffffffffffffffff,8'b0};
|
|
5'd7 : aligned_din_mask = {12'b0,67'h7ffffffffffffffff,7'b0};
|
|
5'd6 : aligned_din_mask = {13'b0,67'h7ffffffffffffffff,6'b0};
|
|
5'd5 : aligned_din_mask = {14'b0,67'h7ffffffffffffffff,5'b0};
|
|
5'd4 : aligned_din_mask = {15'b0,67'h7ffffffffffffffff,4'b0};
|
|
5'd3 : aligned_din_mask = {16'b0,67'h7ffffffffffffffff,3'b0};
|
|
5'd2 : aligned_din_mask = {17'b0,67'h7ffffffffffffffff,2'b0};
|
|
5'd1 : aligned_din_mask = {18'b0,67'h7ffffffffffffffff,1'b0};
|
|
5'd0 : aligned_din_mask = {19'b0,67'h7ffffffffffffffff};
|
|
default : aligned_din_mask = 0; // could be X for QOR
|
|
endcase
|
|
end
|
|
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
storage_mask <= 0;
|
|
end
|
|
else begin
|
|
if (din_valid) begin
|
|
storage_mask <= (storage_mask << 7'd20) | aligned_din_mask;
|
|
if (|((storage_mask << 7'd20) & aligned_din_mask))
|
|
$display ("Warning - TX gearbox lost one or more bits");
|
|
end
|
|
else
|
|
storage_mask <= (storage_mask << 7'd20);
|
|
end
|
|
end
|
|
|
|
wire [19:0] dout_mask;
|
|
assign dout_mask = storage_mask [85:85-19];
|
|
|
|
reg [4:0] flushing;
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) flushing <= 5'b11111;
|
|
else if (|flushing) flushing <= flushing - 1'b1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
#1 if (din_valid & ~(din[65] ^ din[64]) & (~|flushing)) begin
|
|
// the data in to the gearbox should have 10 or 01 framing bits
|
|
// possibly ignoring some pipe flush at reset time
|
|
$display ("Warning - TX gearbox din is not properly framed");
|
|
end
|
|
if (~&dout_mask & (~|flushing)) begin
|
|
// sim only check for gearbox sending out "missing" bits
|
|
// possibly ignoring some pipe flush
|
|
$display ("Warning - some TX gearbox dout bits are invalid");
|
|
end
|
|
end
|
|
|
|
// synthesis translate on
|
|
//////////////////////////////////////////////////////
|
|
// End of sanity check
|
|
//////////////////////////////////////////////////////
|
|
|
|
assign dout = storage [85:85-19];
|
|
|
|
// semi barrel shifter to align incomming data words
|
|
always @(*) begin
|
|
case (wr_ptr)
|
|
5'd19 : aligned_din = {din,19'b0};
|
|
5'd18 : aligned_din = {1'b0,din,18'b0};
|
|
5'd17 : aligned_din = {2'b0,din,17'b0};
|
|
5'd16 : aligned_din = {3'b0,din,16'b0};
|
|
5'd15 : aligned_din = {4'b0,din,15'b0};
|
|
5'd14 : aligned_din = {5'b0,din,14'b0};
|
|
5'd13 : aligned_din = {6'b0,din,13'b0};
|
|
5'd12 : aligned_din = {7'b0,din,12'b0};
|
|
5'd11 : aligned_din = {8'b0,din,11'b0};
|
|
5'd10 : aligned_din = {9'b0,din,10'b0};
|
|
5'd9 : aligned_din = {10'b0,din,9'b0};
|
|
5'd8 : aligned_din = {11'b0,din,8'b0};
|
|
5'd7 : aligned_din = {12'b0,din,7'b0};
|
|
5'd6 : aligned_din = {13'b0,din,6'b0};
|
|
5'd5 : aligned_din = {14'b0,din,5'b0};
|
|
5'd4 : aligned_din = {15'b0,din,4'b0};
|
|
5'd3 : aligned_din = {16'b0,din,3'b0};
|
|
5'd2 : aligned_din = {17'b0,din,2'b0};
|
|
5'd1 : aligned_din = {18'b0,din,1'b0};
|
|
5'd0 : aligned_din = {19'b0,din};
|
|
default : aligned_din = 0; // could be X for QOR
|
|
endcase
|
|
end
|
|
|
|
// figure out where the next word will need to be loaded
|
|
always @(*) begin
|
|
case (wr_ptr)
|
|
5'd19 : next_wr_ptr = 5'd12; // residue 0 + 67 new = 7 leftover
|
|
5'd18 : next_wr_ptr = 5'd11; // residue 1 + 67 new = 8 leftover
|
|
5'd17 : next_wr_ptr = 5'd10; // residue 2 + 67 new = 9 leftover
|
|
5'd16 : next_wr_ptr = 5'd9; // residue 3 + 67 new = 10 leftover
|
|
5'd15 : next_wr_ptr = 5'd8; // residue 4 + 67 new = 11 leftover
|
|
5'd14 : next_wr_ptr = 5'd7; // residue 5 + 67 new = 12 leftover
|
|
5'd13 : next_wr_ptr = 5'd6; // residue 6 + 67 new = 13 leftover
|
|
5'd12 : next_wr_ptr = 5'd5; // residue 7 + 67 new = 14 leftover
|
|
5'd11 : next_wr_ptr = 5'd4; // residue 8 + 67 new = 15 leftover
|
|
5'd10 : next_wr_ptr = 5'd3; // residue 9 + 67 new = 16 leftover
|
|
5'd9 : next_wr_ptr = 5'd2; // residue 10 + 67 new = 17 leftover
|
|
5'd8 : next_wr_ptr = 5'd1; // residue 11 + 67 new = 18 leftover
|
|
5'd7 : next_wr_ptr = 5'd0; // residue 12 + 67 new = 19 leftover
|
|
5'd6 : next_wr_ptr = 5'd19; // residue 13 + 67 new = 0 leftover
|
|
5'd5 : next_wr_ptr = 5'd18; // residue 14 + 67 new = 1 leftover
|
|
5'd4 : next_wr_ptr = 5'd17; // residue 15 + 67 new = 2 leftover
|
|
5'd3 : next_wr_ptr = 5'd16; // residue 16 + 67 new = 3 leftover
|
|
5'd2 : next_wr_ptr = 5'd15; // residue 17 + 67 new = 4 leftover
|
|
5'd1 : next_wr_ptr = 5'd14; // residue 18 + 67 new = 5 leftover
|
|
5'd0 : next_wr_ptr = 5'd13; // residue 19 + 67 new = 6 leftover
|
|
default : next_wr_ptr = 5'd0;
|
|
endcase
|
|
end
|
|
|
|
always @(posedge clk or posedge arst) begin
|
|
if (arst) begin
|
|
wr_ptr <= 7'd19;
|
|
storage <= 0;
|
|
end
|
|
else begin
|
|
if (din_valid) begin
|
|
storage <= (storage << 7'd20) | aligned_din;
|
|
wr_ptr <= next_wr_ptr;
|
|
end
|
|
else begin
|
|
storage <= (storage << 7'd20);
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule |