mor1kx-bemicrocv/ip/altera/ddr3/altera_avalon_st_packets_to...

254 lines
9.9 KiB
Verilog

// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
// --------------------------------------------------------------------------------
//| Avalon ST Packets to Bytes Component
// --------------------------------------------------------------------------------
`timescale 1ns / 100ps
module altera_avalon_st_packets_to_bytes
//if ENCODING ==0, CHANNEL_WIDTH must be 8
//else CHANNEL_WIDTH can be from 0 to 127
#( parameter CHANNEL_WIDTH = 8,
parameter ENCODING = 0)
(
// Interface: clk
input clk,
input reset_n,
// Interface: ST in with packets
output reg in_ready,
input in_valid,
input [7: 0] in_data,
input [CHANNEL_WIDTH-1: 0] in_channel,
input in_startofpacket,
input in_endofpacket,
// Interface: ST out
input out_ready,
output reg out_valid,
output reg [7: 0] out_data
);
// ---------------------------------------------------------------------
//| Signal Declarations
// ---------------------------------------------------------------------
localparam CHN_COUNT = (CHANNEL_WIDTH-1)/7;
localparam CHN_EFFECTIVE = CHANNEL_WIDTH-1;
reg sent_esc, sent_sop, sent_eop;
reg sent_channel_char, channel_escaped, sent_channel;
reg [CHANNEL_WIDTH:0] stored_channel;
reg [4:0] channel_count;
reg [((CHN_EFFECTIVE/7+1)*7)-1:0] stored_varchannel;
reg channel_needs_esc;
wire need_sop, need_eop, need_esc, need_channel;
// ---------------------------------------------------------------------
//| Thingofamagick
// ---------------------------------------------------------------------
assign need_esc = (in_data === 8'h7a |
in_data === 8'h7b |
in_data === 8'h7c |
in_data === 8'h7d );
assign need_eop = (in_endofpacket);
assign need_sop = (in_startofpacket);
generate
if( CHANNEL_WIDTH > 0) begin
wire channel_changed;
assign channel_changed = (in_channel != stored_channel);
assign need_channel = (need_sop | channel_changed);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
sent_esc <= 0;
sent_sop <= 0;
sent_eop <= 0;
sent_channel <= 0;
channel_escaped <= 0;
sent_channel_char <= 0;
out_data <= 0;
out_valid <= 0;
channel_count <= 0;
channel_needs_esc <= 0;
end else begin
if (out_ready )
out_valid <= 0;
if ((out_ready | ~out_valid) && in_valid )
out_valid <= 1;
if ((out_ready | ~out_valid) && in_valid) begin
if (need_channel & ~sent_channel) begin
if (~sent_channel_char) begin
sent_channel_char <= 1;
out_data <= 8'h7c;
channel_count <= CHN_COUNT[4:0];
stored_varchannel <= in_channel;
if ((ENCODING == 0) | (CHANNEL_WIDTH == 7)) begin
channel_needs_esc <= (in_channel == 8'h7a |
in_channel == 8'h7b |
in_channel == 8'h7c |
in_channel == 8'h7d );
end
end else if (channel_needs_esc & ~channel_escaped) begin
out_data <= 8'h7d;
channel_escaped <= 1;
end else if (~sent_channel) begin
if (ENCODING) begin
// Sending out MSB=1, while not last 7 bits of Channel
if (channel_count > 0) begin
if (channel_needs_esc) out_data <= {1'b1, stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-1:((CHN_EFFECTIVE/7+1)*7)-7]} ^ 8'h20;
else out_data <= {1'b1, stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-1:((CHN_EFFECTIVE/7+1)*7)-7]};
stored_varchannel <= stored_varchannel<<7;
channel_count <= channel_count - 1'b1;
// check whether the last 7 bits need escape or not
if (channel_count ==1 & CHANNEL_WIDTH > 7) begin
channel_needs_esc <=
((stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-8:((CHN_EFFECTIVE/7+1)*7)-14] == 7'h7a)|
(stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-8:((CHN_EFFECTIVE/7+1)*7)-14] == 7'h7b) |
(stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-8:((CHN_EFFECTIVE/7+1)*7)-14] == 7'h7c) |
(stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-8:((CHN_EFFECTIVE/7+1)*7)-14] == 7'h7d) );
end
end else begin
// Sending out MSB=0, last 7 bits of Channel
if (channel_needs_esc) begin
channel_needs_esc <= 0;
out_data <= {1'b0, stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-1:((CHN_EFFECTIVE/7+1)*7)-7]} ^ 8'h20;
end else out_data <= {1'b0, stored_varchannel[((CHN_EFFECTIVE/7+1)*7)-1:((CHN_EFFECTIVE/7+1)*7)-7]};
sent_channel <= 1;
end
end else begin
if (channel_needs_esc) begin
channel_needs_esc <= 0;
out_data <= in_channel ^ 8'h20;
end else out_data <= in_channel;
sent_channel <= 1;
end
end
end else if (need_sop & ~sent_sop) begin
sent_sop <= 1;
out_data <= 8'h7a;
end else if (need_eop & ~sent_eop) begin
sent_eop <= 1;
out_data <= 8'h7b;
end else if (need_esc & ~sent_esc) begin
sent_esc <= 1;
out_data <= 8'h7d;
end else begin
if (sent_esc) out_data <= in_data ^ 8'h20;
else out_data <= in_data;
sent_esc <= 0;
sent_sop <= 0;
sent_eop <= 0;
sent_channel <= 0;
channel_escaped <= 0;
sent_channel_char <= 0;
end
end
end
end
//channel related signals
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
//extra bit in stored_channel to force reset
stored_channel <= {CHANNEL_WIDTH{1'b1}};
end else begin
//update stored_channel only when it is sent out
if (sent_channel) stored_channel <= in_channel;
end
end
always @* begin
// in_ready. Low when:
// back pressured, or when
// we are outputting a control character, which means that one of
// {escape_char, start of packet, end of packet, channel}
// needs to be, but has not yet, been handled.
in_ready = (out_ready | !out_valid) & in_valid & (~need_esc | sent_esc)
& (~need_sop | sent_sop)
& (~need_eop | sent_eop)
& (~need_channel | sent_channel);
end
end else begin
assign need_channel = (need_sop);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
sent_esc <= 0;
sent_sop <= 0;
sent_eop <= 0;
out_data <= 0;
out_valid <= 0;
sent_channel <= 0;
sent_channel_char <= 0;
end else begin
if (out_ready )
out_valid <= 0;
if ((out_ready | ~out_valid) && in_valid )
out_valid <= 1;
if ((out_ready | ~out_valid) && in_valid) begin
if (need_channel & ~sent_channel) begin
if (~sent_channel_char) begin //Added sent channel 0 before the 1st SOP
sent_channel_char <= 1;
out_data <= 8'h7c;
end else if (~sent_channel) begin
out_data <= 'h0;
sent_channel <= 1;
end
end else if (need_sop & ~sent_sop) begin
sent_sop <= 1;
out_data <= 8'h7a;
end else if (need_eop & ~sent_eop) begin
sent_eop <= 1;
out_data <= 8'h7b;
end else if (need_esc & ~sent_esc) begin
sent_esc <= 1;
out_data <= 8'h7d;
end else begin
if (sent_esc) out_data <= in_data ^ 8'h20;
else out_data <= in_data;
sent_esc <= 0;
sent_sop <= 0;
sent_eop <= 0;
end
end
end
end
always @* begin
in_ready = (out_ready | !out_valid) & in_valid & (~need_esc | sent_esc)
& (~need_sop | sent_sop)
& (~need_eop | sent_eop)
& (~need_channel | sent_channel);
end
end
endgenerate
endmodule