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

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