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

211 lines
7.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 Bytes to Packet
// --------------------------------------------------------------------------------
`timescale 1ns / 100ps
module altera_avalon_st_bytes_to_packets
//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 out with packets
input out_ready,
output reg out_valid,
output reg [7: 0] out_data,
output reg [CHANNEL_WIDTH-1: 0] out_channel,
output reg out_startofpacket,
output reg out_endofpacket,
// Interface: ST in
output reg in_ready,
input in_valid,
input [7: 0] in_data
);
// ---------------------------------------------------------------------
//| Signal Declarations
// ---------------------------------------------------------------------
reg received_esc, received_channel, received_varchannel;
wire escape_char, sop_char, eop_char, channel_char, varchannelesc_char;
// data out mux.
// we need it twice (data & channel out), so use a wire here
wire [7:0] data_out;
// ---------------------------------------------------------------------
//| Thingofamagick
// ---------------------------------------------------------------------
assign sop_char = (in_data == 8'h7a);
assign eop_char = (in_data == 8'h7b);
assign channel_char = (in_data == 8'h7c);
assign escape_char = (in_data == 8'h7d);
assign data_out = received_esc ? (in_data ^ 8'h20) : in_data;
generate
if (CHANNEL_WIDTH == 0) begin
// Synchorous block -- reset and registers
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
received_esc <= 0;
out_startofpacket <= 0;
out_endofpacket <= 0;
end else begin
// we take data when in_valid and in_ready
if (in_valid & in_ready) begin
if (received_esc) begin
//if we got esc char, after next byte is consumed, quit esc mode
if (out_ready) received_esc <= 0;
end else begin
if (escape_char) received_esc <= 1;
if (sop_char) out_startofpacket <= 1;
if (eop_char) out_endofpacket <= 1;
end
if (out_ready & out_valid) begin
out_startofpacket <= 0;
out_endofpacket <= 0;
end
end
end
end
// Combinational block for in_ready and out_valid
always @* begin
//we choose not to pipeline here. We can process special characters when
//in_ready, but in a chain of microcores, backpressure path is usually
//time critical, so we keep it simple here.
in_ready = out_ready;
//out_valid when in_valid, except when we are processing the special
//characters. However, if we are in escape received mode, then we are
//valid
out_valid = 0;
if ((out_ready | ~out_valid) && in_valid) begin
out_valid = 1;
if (sop_char | eop_char | escape_char | channel_char) out_valid = 0;
end
out_data = data_out;
end
end else begin
assign varchannelesc_char = in_data[7];
// Synchorous block -- reset and registers
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
received_esc <= 0;
received_channel <= 0;
received_varchannel <= 0;
out_startofpacket <= 0;
out_endofpacket <= 0;
end else begin
// we take data when in_valid and in_ready
if (in_valid & in_ready) begin
if (received_esc) begin
//if we got esc char, after next byte is consumed, quit esc mode
if (out_ready | received_channel | received_varchannel) received_esc <= 0;
end else begin
if (escape_char) received_esc <= 1;
if (sop_char) out_startofpacket <= 1;
if (eop_char) out_endofpacket <= 1;
if (channel_char & ENCODING ) received_varchannel <= 1;
if (channel_char & ~ENCODING) received_channel <= 1;
end
if (received_channel & (received_esc | (~sop_char & ~eop_char & ~escape_char & ~channel_char ))) begin
received_channel <= 0;
end
if (received_varchannel & ~varchannelesc_char & (received_esc | (~sop_char & ~eop_char & ~escape_char & ~channel_char))) begin
received_varchannel <= 0;
end
if (out_ready & out_valid) begin
out_startofpacket <= 0;
out_endofpacket <= 0;
end
end
end
end
// Combinational block for in_ready and out_valid
always @* begin
in_ready = out_ready;
out_valid = 0;
if ((out_ready | ~out_valid) && in_valid) begin
out_valid = 1;
if (received_esc) begin
if (received_channel | received_varchannel) out_valid = 0;
end else begin
if (sop_char | eop_char | escape_char | channel_char | received_channel | received_varchannel) out_valid = 0;
end
end
out_data = data_out;
end
end
endgenerate
// Channel block
generate
if (CHANNEL_WIDTH == 0) begin
always @(posedge clk) begin
out_channel <= 'h0;
end
end else if (CHANNEL_WIDTH < 8) begin
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
out_channel <= 'h0;
end else begin
if (in_ready & in_valid) begin
if ((channel_char & ENCODING) & (~received_esc & ~sop_char & ~eop_char & ~escape_char )) begin
out_channel <= 'h0;
end else if (received_varchannel & (received_esc | (~sop_char & ~eop_char & ~escape_char & ~channel_char & ~received_channel))) begin
// Shifting out only the required bits
out_channel[CHANNEL_WIDTH-1:0] <= data_out[CHANNEL_WIDTH-1:0];
end
end
end
end
end else begin
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
out_channel <= 'h0;
end else begin
if (in_ready & in_valid) begin
if (received_channel & (received_esc | (~sop_char & ~eop_char & ~escape_char & ~channel_char))) begin
out_channel <= data_out;
end else if ((channel_char & ENCODING) & (~received_esc & ~sop_char & ~eop_char & ~escape_char )) begin
// Variable Channel Encoding always setting to 0 before begin to shift the channel in
out_channel <= 'h0;
end else if (received_varchannel & (received_esc | (~sop_char & ~eop_char & ~escape_char & ~channel_char & ~received_channel))) begin
// Shifting out the lower 7 bits
out_channel <= out_channel <<7;
out_channel[6:0] <= data_out[6:0];
end
end
end
end
end
endgenerate
endmodule