mirror of
https://github.com/alexforencich/verilog-ethernet.git
synced 2025-01-14 06:43:18 +08:00
merged changes in axis
This commit is contained in:
commit
4e8ef42031
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -101,25 +101,26 @@ localparam [2:0]
|
||||
|
||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg [7:0] cycle_count_reg = 0, cycle_count_next;
|
||||
reg [7:0] cycle_count_reg = 8'd0, cycle_count_next;
|
||||
|
||||
reg last_cycle;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_tdata_reg = 0, temp_tdata_next;
|
||||
reg [KEEP_WIDTH-1:0] temp_tkeep_reg = 0, temp_tkeep_next;
|
||||
reg temp_tlast_reg = 0, temp_tlast_next;
|
||||
reg temp_tuser_reg = 0, temp_tuser_next;
|
||||
reg [DATA_WIDTH-1:0] temp_tdata_reg = {DATA_WIDTH{1'b0}}, temp_tdata_next;
|
||||
reg [KEEP_WIDTH-1:0] temp_tkeep_reg = {KEEP_WIDTH{1'b0}}, temp_tkeep_next;
|
||||
reg temp_tlast_reg = 1'b0, temp_tlast_next;
|
||||
reg temp_tuser_reg = 1'b0, temp_tuser_next;
|
||||
|
||||
// internal datapath
|
||||
reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
always @* begin
|
||||
@ -132,13 +133,13 @@ always @* begin
|
||||
temp_tlast_next = temp_tlast_reg;
|
||||
temp_tuser_next = temp_tuser_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {OUTPUT_DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {OUTPUT_KEEP_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
@ -161,7 +162,7 @@ always @* begin
|
||||
// output bus is wider
|
||||
|
||||
// accept new data
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
|
||||
if (input_axis_tready & input_axis_tvalid) begin
|
||||
// word transfer in - store it in data register
|
||||
@ -173,15 +174,15 @@ always @* begin
|
||||
temp_tuser_next = input_axis_tuser;
|
||||
|
||||
// first input cycle complete
|
||||
cycle_count_next = 1;
|
||||
cycle_count_next = 8'd1;
|
||||
|
||||
if (input_axis_tlast) begin
|
||||
// got last signal on first cycle, so output it
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
state_next = STATE_TRANSFER_OUT;
|
||||
end else begin
|
||||
// otherwise, transfer in the rest of the words
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
state_next = STATE_TRANSFER_IN;
|
||||
end
|
||||
end else begin
|
||||
@ -191,24 +192,24 @@ always @* begin
|
||||
// output bus is narrower
|
||||
|
||||
// accept new data
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
|
||||
if (input_axis_tready & input_axis_tvalid) begin
|
||||
// word transfer in - store it in data register
|
||||
cycle_count_next = 0;
|
||||
cycle_count_next = 8'd0;
|
||||
|
||||
// is this the last cycle?
|
||||
if (CYCLE_COUNT == 1) begin
|
||||
// last cycle by counter value
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else if (input_axis_tkeep[CYCLE_KEEP_WIDTH-1:0] != {CYCLE_KEEP_WIDTH{1'b1}}) begin
|
||||
// last cycle by tkeep fall in current cycle
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else if (input_axis_tkeep[(CYCLE_KEEP_WIDTH*2)-1:CYCLE_KEEP_WIDTH] == {CYCLE_KEEP_WIDTH{1'b0}}) begin
|
||||
// last cycle by tkeep fall at end of current cycle
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else begin
|
||||
last_cycle = 0;
|
||||
last_cycle = 1'b0;
|
||||
end
|
||||
|
||||
// pass complete input word, zero-extended to temp register
|
||||
@ -220,18 +221,18 @@ always @* begin
|
||||
// short-circuit and get first word out the door
|
||||
output_axis_tdata_int = input_axis_tdata[CYCLE_DATA_WIDTH-1:0];
|
||||
output_axis_tkeep_int = input_axis_tkeep[CYCLE_KEEP_WIDTH-1:0];
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = input_axis_tlast & last_cycle;
|
||||
output_axis_tuser_int = input_axis_tuser & last_cycle;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// if output register is ready for first word, then move on to the next one
|
||||
cycle_count_next = 1;
|
||||
cycle_count_next = 8'd1;
|
||||
end
|
||||
|
||||
if (!last_cycle || !output_axis_tready_int) begin
|
||||
if (!last_cycle || !output_axis_tready_int_reg) begin
|
||||
// continue outputting words
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
state_next = STATE_TRANSFER_OUT;
|
||||
end else begin
|
||||
state_next = STATE_IDLE;
|
||||
@ -246,7 +247,7 @@ always @* begin
|
||||
// only used when output is wider
|
||||
|
||||
// accept new data
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
|
||||
if (input_axis_tready & input_axis_tvalid) begin
|
||||
// word transfer in - store in data register
|
||||
@ -265,7 +266,7 @@ always @* begin
|
||||
state_next = STATE_TRANSFER_OUT;
|
||||
end else begin
|
||||
// more words to read
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
state_next = STATE_TRANSFER_IN;
|
||||
end
|
||||
end else begin
|
||||
@ -279,16 +280,16 @@ always @* begin
|
||||
// output bus is wider
|
||||
|
||||
// do not accept new data
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
// single-cycle output of entire stored word (output wider)
|
||||
output_axis_tdata_int = temp_tdata_reg;
|
||||
output_axis_tkeep_int = temp_tkeep_reg;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = temp_tlast_reg;
|
||||
output_axis_tuser_int = temp_tuser_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// word transfer out
|
||||
|
||||
if (input_axis_tready & input_axis_tvalid) begin
|
||||
@ -301,19 +302,19 @@ always @* begin
|
||||
temp_tuser_next = input_axis_tuser;
|
||||
|
||||
// first input cycle complete
|
||||
cycle_count_next = 1;
|
||||
cycle_count_next = 8'd1;
|
||||
|
||||
if (input_axis_tlast) begin
|
||||
// got last signal on first cycle, so output it
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
state_next = STATE_TRANSFER_OUT;
|
||||
end else begin
|
||||
// otherwise, transfer in the rest of the words
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
state_next = STATE_TRANSFER_IN;
|
||||
end
|
||||
end else begin
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
@ -323,30 +324,30 @@ always @* begin
|
||||
// output bus is narrower
|
||||
|
||||
// do not accept new data
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
// is this the last cycle?
|
||||
if (cycle_count_reg == CYCLE_COUNT-1) begin
|
||||
// last cycle by counter value
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else if (temp_tkeep_reg[cycle_count_reg*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH] != {CYCLE_KEEP_WIDTH{1'b1}}) begin
|
||||
// last cycle by tkeep fall in current cycle
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else if (temp_tkeep_reg[(cycle_count_reg+1)*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH] == {CYCLE_KEEP_WIDTH{1'b0}}) begin
|
||||
// last cycle by tkeep fall at end of current cycle
|
||||
last_cycle = 1;
|
||||
last_cycle = 1'b1;
|
||||
end else begin
|
||||
last_cycle = 0;
|
||||
last_cycle = 1'b0;
|
||||
end
|
||||
|
||||
// output current part of stored word (output narrower)
|
||||
output_axis_tdata_int = temp_tdata_reg[cycle_count_reg*CYCLE_DATA_WIDTH +: CYCLE_DATA_WIDTH];
|
||||
output_axis_tkeep_int = temp_tkeep_reg[cycle_count_reg*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH];
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = temp_tlast_reg & last_cycle;
|
||||
output_axis_tuser_int = temp_tuser_reg & last_cycle;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// word transfer out
|
||||
|
||||
cycle_count_next = cycle_count_reg + 1;
|
||||
@ -354,7 +355,7 @@ always @* begin
|
||||
if (last_cycle) begin
|
||||
// terminated by counter or tlast signal
|
||||
|
||||
input_axis_tready_next = 1;
|
||||
input_axis_tready_next = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
// more words to write
|
||||
@ -371,38 +372,39 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
cycle_count_reg <= 0;
|
||||
temp_tdata_reg <= 0;
|
||||
temp_tkeep_reg <= 0;
|
||||
temp_tlast_reg <= 0;
|
||||
temp_tuser_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
cycle_count_reg <= 8'd0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
input_axis_tready_reg <= input_axis_tready_next;
|
||||
|
||||
temp_tdata_reg <= temp_tdata_next;
|
||||
temp_tkeep_reg <= temp_tkeep_next;
|
||||
temp_tlast_reg <= temp_tlast_next;
|
||||
temp_tuser_reg <= temp_tuser_next;
|
||||
|
||||
cycle_count_reg <= cycle_count_next;
|
||||
end
|
||||
|
||||
temp_tdata_reg <= temp_tdata_next;
|
||||
temp_tkeep_reg <= temp_tkeep_next;
|
||||
temp_tlast_reg <= temp_tlast_next;
|
||||
temp_tuser_reg <= temp_tuser_next;
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_reg = {OUTPUT_DATA_WIDTH{1'b0}};
|
||||
reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_reg = {OUTPUT_KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [OUTPUT_DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [OUTPUT_KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [OUTPUT_DATA_WIDTH-1:0] temp_axis_tdata_reg = {OUTPUT_DATA_WIDTH{1'b0}};
|
||||
reg [OUTPUT_KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {OUTPUT_KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -410,56 +412,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready and currently valid, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -61,129 +61,163 @@ module axis_async_fifo #
|
||||
output wire output_axis_tuser
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_gray_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_gray_next;
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg input_rst_sync1 = 1;
|
||||
reg input_rst_sync2 = 1;
|
||||
reg input_rst_sync3 = 1;
|
||||
reg output_rst_sync1 = 1;
|
||||
reg output_rst_sync2 = 1;
|
||||
reg output_rst_sync3 = 1;
|
||||
reg input_rst_sync1_reg = 1'b1;
|
||||
reg input_rst_sync2_reg = 1'b1;
|
||||
reg input_rst_sync3_reg = 1'b1;
|
||||
reg output_rst_sync1_reg = 1'b1;
|
||||
reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
// (gray code equivalent of first MSB different but rest same)
|
||||
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
|
||||
wire full = ((wr_ptr_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
|
||||
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
|
||||
wire write = input_axis_tvalid & ~full;
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = data_out_reg;
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3_reg;
|
||||
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3;
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
input_rst_sync1 <= 1;
|
||||
input_rst_sync2 <= 1;
|
||||
input_rst_sync3 <= 1;
|
||||
input_rst_sync1_reg <= 1'b1;
|
||||
input_rst_sync2_reg <= 1'b1;
|
||||
input_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
input_rst_sync1 <= 0;
|
||||
input_rst_sync2 <= input_rst_sync1 | output_rst_sync1;
|
||||
input_rst_sync3 <= input_rst_sync2;
|
||||
input_rst_sync1_reg <= 1'b0;
|
||||
input_rst_sync2_reg <= input_rst_sync1_reg | output_rst_sync1_reg;
|
||||
input_rst_sync3_reg <= input_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
output_rst_sync1 <= 1;
|
||||
output_rst_sync2 <= 1;
|
||||
output_rst_sync3 <= 1;
|
||||
output_rst_sync1_reg <= 1'b1;
|
||||
output_rst_sync2_reg <= 1'b1;
|
||||
output_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
output_rst_sync1 <= 0;
|
||||
output_rst_sync2 <= output_rst_sync1;
|
||||
output_rst_sync3 <= output_rst_sync2;
|
||||
output_rst_sync1_reg <= 1'b0;
|
||||
output_rst_sync2_reg <= output_rst_sync1_reg;
|
||||
output_rst_sync3_reg <= output_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_gray_next = wr_ptr_gray_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full) begin
|
||||
// not full, perform write
|
||||
write = 1'b1;
|
||||
wr_ptr_next = wr_ptr_reg + 1;
|
||||
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// write
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_gray <= 0;
|
||||
end else if (write) begin
|
||||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_next = wr_ptr + 1;
|
||||
wr_ptr <= wr_ptr_next;
|
||||
wr_ptr_gray <= wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
if (input_rst_sync3_reg) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_gray_reg <= wr_ptr_gray_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
rd_ptr_gray_sync1 <= 0;
|
||||
rd_ptr_gray_sync2 <= 0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
rd_ptr_gray_sync1 <= rd_ptr_gray;
|
||||
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
|
||||
rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg;
|
||||
rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
rd_ptr <= 0;
|
||||
rd_ptr_gray <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr_next = rd_ptr + 1;
|
||||
rd_ptr <= rd_ptr_next;
|
||||
rd_ptr_gray <= rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
wr_ptr_gray_sync1 <= 0;
|
||||
wr_ptr_gray_sync2 <= 0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_gray_sync1 <= wr_ptr_gray;
|
||||
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tuser_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -64,129 +64,165 @@ module axis_async_fifo_64 #
|
||||
output wire output_axis_tuser
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_gray_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_gray_next;
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg input_rst_sync1 = 1;
|
||||
reg input_rst_sync2 = 1;
|
||||
reg input_rst_sync3 = 1;
|
||||
reg output_rst_sync1 = 1;
|
||||
reg output_rst_sync2 = 1;
|
||||
reg output_rst_sync3 = 1;
|
||||
reg input_rst_sync1_reg = 1'b1;
|
||||
reg input_rst_sync2_reg = 1'b1;
|
||||
reg input_rst_sync3_reg = 1'b1;
|
||||
reg output_rst_sync1_reg = 1'b1;
|
||||
reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {KEEP_WIDTH{1'b0}}, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
// (gray code equivalent of first MSB different but rest same)
|
||||
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
|
||||
wire full = ((wr_ptr_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
|
||||
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
|
||||
wire write = input_axis_tvalid & ~full;
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = data_out_reg;
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3_reg;
|
||||
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3;
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
input_rst_sync1 <= 1;
|
||||
input_rst_sync2 <= 1;
|
||||
input_rst_sync3 <= 1;
|
||||
input_rst_sync1_reg <= 1'b1;
|
||||
input_rst_sync2_reg <= 1'b1;
|
||||
input_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
input_rst_sync1 <= 0;
|
||||
input_rst_sync2 <= input_rst_sync1 | output_rst_sync1;
|
||||
input_rst_sync3 <= input_rst_sync2;
|
||||
input_rst_sync1_reg <= 1'b0;
|
||||
input_rst_sync2_reg <= input_rst_sync1_reg | output_rst_sync1_reg;
|
||||
input_rst_sync3_reg <= input_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
output_rst_sync1 <= 1;
|
||||
output_rst_sync2 <= 1;
|
||||
output_rst_sync3 <= 1;
|
||||
output_rst_sync1_reg <= 1'b1;
|
||||
output_rst_sync2_reg <= 1'b1;
|
||||
output_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
output_rst_sync1 <= 0;
|
||||
output_rst_sync2 <= output_rst_sync1;
|
||||
output_rst_sync3 <= output_rst_sync2;
|
||||
output_rst_sync1_reg <= 1'b0;
|
||||
output_rst_sync2_reg <= output_rst_sync1_reg;
|
||||
output_rst_sync3_reg <= output_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_gray_next = wr_ptr_gray_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full) begin
|
||||
// not full, perform write
|
||||
write = 1'b1;
|
||||
wr_ptr_next = wr_ptr_reg + 1;
|
||||
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// write
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_gray <= 0;
|
||||
end else if (write) begin
|
||||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_next = wr_ptr + 1;
|
||||
wr_ptr <= wr_ptr_next;
|
||||
wr_ptr_gray <= wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
if (input_rst_sync3_reg) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_gray_reg <= wr_ptr_gray_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
rd_ptr_gray_sync1 <= 0;
|
||||
rd_ptr_gray_sync2 <= 0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
rd_ptr_gray_sync1 <= rd_ptr_gray;
|
||||
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
|
||||
rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg;
|
||||
rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
rd_ptr <= 0;
|
||||
rd_ptr_gray <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr_next = rd_ptr + 1;
|
||||
rd_ptr <= rd_ptr_next;
|
||||
rd_ptr_gray <= rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
wr_ptr_gray_sync1 <= 0;
|
||||
wr_ptr_gray_sync2 <= 0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_gray_sync1 <= wr_ptr_gray;
|
||||
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tuser_reg, output_axis_tkeep_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -71,226 +71,267 @@ module axis_async_frame_fifo #
|
||||
output wire output_status_good_frame
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_gray_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_gray_next;
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg input_rst_sync1 = 1;
|
||||
reg input_rst_sync2 = 1;
|
||||
reg input_rst_sync3 = 1;
|
||||
reg output_rst_sync1 = 1;
|
||||
reg output_rst_sync2 = 1;
|
||||
reg output_rst_sync3 = 1;
|
||||
reg input_rst_sync1_reg = 1'b1;
|
||||
reg input_rst_sync2_reg = 1'b1;
|
||||
reg input_rst_sync3_reg = 1'b1;
|
||||
reg output_rst_sync1_reg = 1'b1;
|
||||
reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg drop_frame = 1'b0;
|
||||
reg overflow_reg = 1'b0;
|
||||
reg bad_frame_reg = 1'b0;
|
||||
reg good_frame_reg = 1'b0;
|
||||
reg [DATA_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg overflow_sync1 = 1'b0;
|
||||
reg overflow_sync2 = 1'b0;
|
||||
reg overflow_sync3 = 1'b0;
|
||||
reg overflow_sync4 = 1'b0;
|
||||
reg bad_frame_sync1 = 1'b0;
|
||||
reg bad_frame_sync2 = 1'b0;
|
||||
reg bad_frame_sync3 = 1'b0;
|
||||
reg bad_frame_sync4 = 1'b0;
|
||||
reg good_frame_sync1 = 1'b0;
|
||||
reg good_frame_sync2 = 1'b0;
|
||||
reg good_frame_sync3 = 1'b0;
|
||||
reg good_frame_sync4 = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] data_out_reg = {1'b0, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
// (gray code equivalent of first MSB different but rest same)
|
||||
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
|
||||
wire full = ((wr_ptr_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
|
||||
// overflow in single packet
|
||||
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
|
||||
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
// overflow within packet
|
||||
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
|
||||
|
||||
wire write = input_axis_tvalid & (~full | DROP_WHEN_FULL);
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tdata} = data_out_reg;
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
reg bad_frame_reg = 1'b0, bad_frame_next;
|
||||
reg good_frame_reg = 1'b0, good_frame_next;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3;
|
||||
reg overflow_sync1_reg = 1'b0;
|
||||
reg overflow_sync2_reg = 1'b0;
|
||||
reg overflow_sync3_reg = 1'b0;
|
||||
reg overflow_sync4_reg = 1'b0;
|
||||
reg bad_frame_sync1_reg = 1'b0;
|
||||
reg bad_frame_sync2_reg = 1'b0;
|
||||
reg bad_frame_sync3_reg = 1'b0;
|
||||
reg bad_frame_sync4_reg = 1'b0;
|
||||
reg good_frame_sync1_reg = 1'b0;
|
||||
reg good_frame_sync2_reg = 1'b0;
|
||||
reg good_frame_sync3_reg = 1'b0;
|
||||
reg good_frame_sync4_reg = 1'b0;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3_reg;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
|
||||
assign input_status_overflow = overflow_reg;
|
||||
assign input_status_bad_frame = bad_frame_reg;
|
||||
assign input_status_good_frame = good_frame_reg;
|
||||
|
||||
assign output_status_overflow = overflow_sync3 ^ overflow_sync4;
|
||||
assign output_status_bad_frame = bad_frame_sync3 ^ bad_frame_sync4;
|
||||
assign output_status_good_frame = good_frame_sync3 ^ good_frame_sync4;
|
||||
assign output_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg;
|
||||
assign output_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg;
|
||||
assign output_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
input_rst_sync1 <= 1;
|
||||
input_rst_sync2 <= 1;
|
||||
input_rst_sync3 <= 1;
|
||||
input_rst_sync1_reg <= 1'b1;
|
||||
input_rst_sync2_reg <= 1'b1;
|
||||
input_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
input_rst_sync1 <= 0;
|
||||
input_rst_sync2 <= input_rst_sync1 | output_rst_sync1;
|
||||
input_rst_sync3 <= input_rst_sync2;
|
||||
input_rst_sync1_reg <= 1'b0;
|
||||
input_rst_sync2_reg <= input_rst_sync1_reg | output_rst_sync1_reg;
|
||||
input_rst_sync3_reg <= input_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
output_rst_sync1 <= 1;
|
||||
output_rst_sync2 <= 1;
|
||||
output_rst_sync3 <= 1;
|
||||
output_rst_sync1_reg <= 1'b1;
|
||||
output_rst_sync2_reg <= 1'b1;
|
||||
output_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
output_rst_sync1 <= 0;
|
||||
output_rst_sync2 <= output_rst_sync1;
|
||||
output_rst_sync3 <= output_rst_sync2;
|
||||
output_rst_sync1_reg <= 1'b0;
|
||||
output_rst_sync2_reg <= output_rst_sync1_reg;
|
||||
output_rst_sync3_reg <= output_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// write
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_cur <= 0;
|
||||
wr_ptr_gray <= 0;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
end else if (write) begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
if (full | full_cur | drop_frame) begin
|
||||
// buffer full, hold current pointer, drop packet at end
|
||||
drop_frame <= 1;
|
||||
if (input_axis_tlast) begin
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 1;
|
||||
end
|
||||
end else begin
|
||||
mem[wr_ptr_cur[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_cur <= wr_ptr_cur + 1;
|
||||
if (input_axis_tlast) begin
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
bad_frame_reg <= 1;
|
||||
end else begin
|
||||
// good packet, push new write pointer
|
||||
wr_ptr_next = wr_ptr_cur + 1;
|
||||
wr_ptr <= wr_ptr_next;
|
||||
wr_ptr_gray <= wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
good_frame_reg <= 1;
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b0;
|
||||
bad_frame_next = 1'b0;
|
||||
good_frame_next = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg;
|
||||
wr_ptr_gray_next = wr_ptr_gray_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full | DROP_WHEN_FULL) begin
|
||||
// not full, perform write
|
||||
if (full | full_cur | drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_next = 1'b1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
write = 1'b1;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
bad_frame_next = 1'b1;
|
||||
end else begin
|
||||
// good packet, update write pointer
|
||||
wr_ptr_next = wr_ptr_cur_reg + 1;
|
||||
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
good_frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3_reg) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b0;
|
||||
bad_frame_reg <= 1'b0;
|
||||
good_frame_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_cur_reg <= wr_ptr_cur_next;
|
||||
wr_ptr_gray_reg <= wr_ptr_gray_next;
|
||||
|
||||
drop_frame_reg <= drop_frame_next;
|
||||
overflow_reg <= overflow_next;
|
||||
bad_frame_reg <= bad_frame_next;
|
||||
good_frame_reg <= good_frame_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
rd_ptr_gray_sync1 <= 0;
|
||||
rd_ptr_gray_sync2 <= 0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
rd_ptr_gray_sync1 <= rd_ptr_gray;
|
||||
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
|
||||
rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg;
|
||||
rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
rd_ptr <= 0;
|
||||
rd_ptr_gray <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr_next = rd_ptr + 1;
|
||||
rd_ptr <= rd_ptr_next;
|
||||
rd_ptr_gray <= rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
wr_ptr_gray_sync1 <= 0;
|
||||
wr_ptr_gray_sync2 <= 0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_gray_sync1 <= wr_ptr_gray;
|
||||
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// status synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
overflow_sync1 <= 1'b0;
|
||||
bad_frame_sync1 <= 1'b0;
|
||||
good_frame_sync1 <= 1'b0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
overflow_sync1_reg <= 1'b0;
|
||||
bad_frame_sync1_reg <= 1'b0;
|
||||
good_frame_sync1_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_sync1 <= overflow_sync1 ^ overflow_reg;
|
||||
bad_frame_sync1 <= bad_frame_sync1 ^ bad_frame_reg;
|
||||
good_frame_sync1 <= good_frame_sync1 ^ good_frame_reg;
|
||||
overflow_sync1_reg <= overflow_sync1_reg ^ overflow_reg;
|
||||
bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg;
|
||||
good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
overflow_sync2 <= 1'b0;
|
||||
overflow_sync3 <= 1'b0;
|
||||
bad_frame_sync2 <= 1'b0;
|
||||
bad_frame_sync3 <= 1'b0;
|
||||
good_frame_sync2 <= 1'b0;
|
||||
good_frame_sync3 <= 1'b0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
overflow_sync2_reg <= 1'b0;
|
||||
overflow_sync3_reg <= 1'b0;
|
||||
bad_frame_sync2_reg <= 1'b0;
|
||||
bad_frame_sync3_reg <= 1'b0;
|
||||
good_frame_sync2_reg <= 1'b0;
|
||||
good_frame_sync3_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_sync2 <= overflow_sync1;
|
||||
overflow_sync3 <= overflow_sync2;
|
||||
overflow_sync4 <= overflow_sync3;
|
||||
bad_frame_sync2 <= bad_frame_sync1;
|
||||
bad_frame_sync3 <= bad_frame_sync2;
|
||||
bad_frame_sync4 <= bad_frame_sync3;
|
||||
good_frame_sync2 <= good_frame_sync1;
|
||||
good_frame_sync3 <= good_frame_sync2;
|
||||
good_frame_sync4 <= good_frame_sync3;
|
||||
overflow_sync2_reg <= overflow_sync1_reg;
|
||||
overflow_sync3_reg <= overflow_sync2_reg;
|
||||
overflow_sync4_reg <= overflow_sync3_reg;
|
||||
bad_frame_sync2_reg <= bad_frame_sync1_reg;
|
||||
bad_frame_sync3_reg <= bad_frame_sync2_reg;
|
||||
bad_frame_sync4_reg <= bad_frame_sync3_reg;
|
||||
good_frame_sync2_reg <= good_frame_sync1_reg;
|
||||
good_frame_sync3_reg <= good_frame_sync2_reg;
|
||||
good_frame_sync4_reg <= good_frame_sync3_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -74,226 +74,269 @@ module axis_async_frame_fifo_64 #
|
||||
output wire output_status_good_frame
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_gray_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_gray_next;
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg input_rst_sync1 = 1;
|
||||
reg input_rst_sync2 = 1;
|
||||
reg input_rst_sync3 = 1;
|
||||
reg output_rst_sync1 = 1;
|
||||
reg output_rst_sync2 = 1;
|
||||
reg output_rst_sync3 = 1;
|
||||
reg input_rst_sync1_reg = 1'b1;
|
||||
reg input_rst_sync2_reg = 1'b1;
|
||||
reg input_rst_sync3_reg = 1'b1;
|
||||
reg output_rst_sync1_reg = 1'b1;
|
||||
reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg drop_frame = 1'b0;
|
||||
reg overflow_reg = 1'b0;
|
||||
reg bad_frame_reg = 1'b0;
|
||||
reg good_frame_reg = 1'b0;
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg overflow_sync1 = 1'b0;
|
||||
reg overflow_sync2 = 1'b0;
|
||||
reg overflow_sync3 = 1'b0;
|
||||
reg overflow_sync4 = 1'b0;
|
||||
reg bad_frame_sync1 = 1'b0;
|
||||
reg bad_frame_sync2 = 1'b0;
|
||||
reg bad_frame_sync3 = 1'b0;
|
||||
reg bad_frame_sync4 = 1'b0;
|
||||
reg good_frame_sync1 = 1'b0;
|
||||
reg good_frame_sync2 = 1'b0;
|
||||
reg good_frame_sync3 = 1'b0;
|
||||
reg good_frame_sync4 = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_out_reg = {1'b0, {KEEP_WIDTH{1'b0}}, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
// (gray code equivalent of first MSB different but rest same)
|
||||
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
|
||||
wire full = ((wr_ptr_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
|
||||
(wr_ptr_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
|
||||
// overflow in single packet
|
||||
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
|
||||
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
// overflow within packet
|
||||
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
|
||||
|
||||
wire write = input_axis_tvalid & (~full | DROP_WHEN_FULL);
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = data_out_reg;
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
reg bad_frame_reg = 1'b0, bad_frame_next;
|
||||
reg good_frame_reg = 1'b0, good_frame_next;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3;
|
||||
reg overflow_sync1_reg = 1'b0;
|
||||
reg overflow_sync2_reg = 1'b0;
|
||||
reg overflow_sync3_reg = 1'b0;
|
||||
reg overflow_sync4_reg = 1'b0;
|
||||
reg bad_frame_sync1_reg = 1'b0;
|
||||
reg bad_frame_sync2_reg = 1'b0;
|
||||
reg bad_frame_sync3_reg = 1'b0;
|
||||
reg bad_frame_sync4_reg = 1'b0;
|
||||
reg good_frame_sync1_reg = 1'b0;
|
||||
reg good_frame_sync2_reg = 1'b0;
|
||||
reg good_frame_sync3_reg = 1'b0;
|
||||
reg good_frame_sync4_reg = 1'b0;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3_reg;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
|
||||
assign input_status_overflow = overflow_reg;
|
||||
assign input_status_bad_frame = bad_frame_reg;
|
||||
assign input_status_good_frame = good_frame_reg;
|
||||
|
||||
assign output_status_overflow = overflow_sync3 ^ overflow_sync4;
|
||||
assign output_status_bad_frame = bad_frame_sync3 ^ bad_frame_sync4;
|
||||
assign output_status_good_frame = good_frame_sync3 ^ good_frame_sync4;
|
||||
assign output_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg;
|
||||
assign output_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg;
|
||||
assign output_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
input_rst_sync1 <= 1;
|
||||
input_rst_sync2 <= 1;
|
||||
input_rst_sync3 <= 1;
|
||||
input_rst_sync1_reg <= 1'b1;
|
||||
input_rst_sync2_reg <= 1'b1;
|
||||
input_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
input_rst_sync1 <= 0;
|
||||
input_rst_sync2 <= input_rst_sync1 | output_rst_sync1;
|
||||
input_rst_sync3 <= input_rst_sync2;
|
||||
input_rst_sync1_reg <= 1'b0;
|
||||
input_rst_sync2_reg <= input_rst_sync1_reg | output_rst_sync1_reg;
|
||||
input_rst_sync3_reg <= input_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk or posedge async_rst) begin
|
||||
if (async_rst) begin
|
||||
output_rst_sync1 <= 1;
|
||||
output_rst_sync2 <= 1;
|
||||
output_rst_sync3 <= 1;
|
||||
output_rst_sync1_reg <= 1'b1;
|
||||
output_rst_sync2_reg <= 1'b1;
|
||||
output_rst_sync3_reg <= 1'b1;
|
||||
end else begin
|
||||
output_rst_sync1 <= 0;
|
||||
output_rst_sync2 <= output_rst_sync1;
|
||||
output_rst_sync3 <= output_rst_sync2;
|
||||
output_rst_sync1_reg <= 1'b0;
|
||||
output_rst_sync2_reg <= output_rst_sync1_reg;
|
||||
output_rst_sync3_reg <= output_rst_sync2_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// write
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_cur <= 0;
|
||||
wr_ptr_gray <= 0;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
end else if (write) begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
if (full | full_cur | drop_frame) begin
|
||||
// buffer full, hold current pointer, drop packet at end
|
||||
drop_frame <= 1;
|
||||
if (input_axis_tlast) begin
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 1;
|
||||
end
|
||||
end else begin
|
||||
mem[wr_ptr_cur[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_cur <= wr_ptr_cur + 1;
|
||||
if (input_axis_tlast) begin
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
bad_frame_reg <= 1;
|
||||
end else begin
|
||||
// good packet, push new write pointer
|
||||
wr_ptr_next = wr_ptr_cur + 1;
|
||||
wr_ptr <= wr_ptr_next;
|
||||
wr_ptr_gray <= wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
good_frame_reg <= 1;
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b0;
|
||||
bad_frame_next = 1'b0;
|
||||
good_frame_next = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg;
|
||||
wr_ptr_gray_next = wr_ptr_gray_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full | DROP_WHEN_FULL) begin
|
||||
// not full, perform write
|
||||
if (full | full_cur | drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_next = 1'b1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
write = 1'b1;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
bad_frame_next = 1'b1;
|
||||
end else begin
|
||||
// good packet, update write pointer
|
||||
wr_ptr_next = wr_ptr_cur_reg + 1;
|
||||
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
|
||||
good_frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3_reg) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b0;
|
||||
bad_frame_reg <= 1'b0;
|
||||
good_frame_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_cur_reg <= wr_ptr_cur_next;
|
||||
wr_ptr_gray_reg <= wr_ptr_gray_next;
|
||||
|
||||
drop_frame_reg <= drop_frame_next;
|
||||
overflow_reg <= overflow_next;
|
||||
bad_frame_reg <= bad_frame_next;
|
||||
good_frame_reg <= good_frame_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
rd_ptr_gray_sync1 <= 0;
|
||||
rd_ptr_gray_sync2 <= 0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
rd_ptr_gray_sync1 <= rd_ptr_gray;
|
||||
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
|
||||
rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg;
|
||||
rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
rd_ptr <= 0;
|
||||
rd_ptr_gray <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr_next = rd_ptr + 1;
|
||||
rd_ptr <= rd_ptr_next;
|
||||
rd_ptr_gray <= rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end
|
||||
end
|
||||
|
||||
// pointer synchronization
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
wr_ptr_gray_sync1 <= 0;
|
||||
wr_ptr_gray_sync2 <= 0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
wr_ptr_gray_sync1 <= wr_ptr_gray;
|
||||
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// status synchronization
|
||||
always @(posedge input_clk) begin
|
||||
if (input_rst_sync3) begin
|
||||
overflow_sync1 <= 1'b0;
|
||||
bad_frame_sync1 <= 1'b0;
|
||||
good_frame_sync1 <= 1'b0;
|
||||
if (input_rst_sync3_reg) begin
|
||||
overflow_sync1_reg <= 1'b0;
|
||||
bad_frame_sync1_reg <= 1'b0;
|
||||
good_frame_sync1_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_sync1 <= overflow_sync1 ^ overflow_reg;
|
||||
bad_frame_sync1 <= bad_frame_sync1 ^ bad_frame_reg;
|
||||
good_frame_sync1 <= good_frame_sync1 ^ good_frame_reg;
|
||||
overflow_sync1_reg <= overflow_sync1_reg ^ overflow_reg;
|
||||
bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg;
|
||||
good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3) begin
|
||||
overflow_sync2 <= 1'b0;
|
||||
overflow_sync3 <= 1'b0;
|
||||
bad_frame_sync2 <= 1'b0;
|
||||
bad_frame_sync3 <= 1'b0;
|
||||
good_frame_sync2 <= 1'b0;
|
||||
good_frame_sync3 <= 1'b0;
|
||||
if (output_rst_sync3_reg) begin
|
||||
overflow_sync2_reg <= 1'b0;
|
||||
overflow_sync3_reg <= 1'b0;
|
||||
bad_frame_sync2_reg <= 1'b0;
|
||||
bad_frame_sync3_reg <= 1'b0;
|
||||
good_frame_sync2_reg <= 1'b0;
|
||||
good_frame_sync3_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_sync2 <= overflow_sync1;
|
||||
overflow_sync3 <= overflow_sync2;
|
||||
overflow_sync4 <= overflow_sync3;
|
||||
bad_frame_sync2 <= bad_frame_sync1;
|
||||
bad_frame_sync3 <= bad_frame_sync2;
|
||||
bad_frame_sync4 <= bad_frame_sync3;
|
||||
good_frame_sync2 <= good_frame_sync1;
|
||||
good_frame_sync3 <= good_frame_sync2;
|
||||
good_frame_sync4 <= good_frame_sync3;
|
||||
overflow_sync2_reg <= overflow_sync1_reg;
|
||||
overflow_sync3_reg <= overflow_sync2_reg;
|
||||
overflow_sync4_reg <= overflow_sync3_reg;
|
||||
bad_frame_sync2_reg <= bad_frame_sync1_reg;
|
||||
bad_frame_sync3_reg <= bad_frame_sync2_reg;
|
||||
bad_frame_sync4_reg <= bad_frame_sync3_reg;
|
||||
good_frame_sync2_reg <= good_frame_sync1_reg;
|
||||
good_frame_sync3_reg <= good_frame_sync2_reg;
|
||||
good_frame_sync4_reg <= good_frame_sync3_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tkeep_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -103,21 +103,21 @@ module {{name}} #
|
||||
{%- endfor %}
|
||||
);
|
||||
{% for p in ports %}
|
||||
reg [DATA_WIDTH-1:0] input_{{p}}_axis_tdata_reg = 0;
|
||||
reg input_{{p}}_axis_tvalid_reg = 0;
|
||||
reg input_{{p}}_axis_tlast_reg = 0;
|
||||
reg input_{{p}}_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_{{p}}_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg input_{{p}}_axis_tvalid_reg = 1'b0;
|
||||
reg input_{{p}}_axis_tlast_reg = 1'b0;
|
||||
reg input_{{p}}_axis_tuser_reg = 1'b0;
|
||||
{% endfor %}
|
||||
|
||||
{%- for p in ports %}
|
||||
reg [DATA_WIDTH-1:0] output_{{p}}_axis_tdata_reg = 0;
|
||||
reg output_{{p}}_axis_tvalid_reg = 0;
|
||||
reg output_{{p}}_axis_tlast_reg = 0;
|
||||
reg output_{{p}}_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_{{p}}_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_{{p}}_axis_tvalid_reg = 1'b0;
|
||||
reg output_{{p}}_axis_tlast_reg = 1'b0;
|
||||
reg output_{{p}}_axis_tuser_reg = 1'b0;
|
||||
{% endfor %}
|
||||
|
||||
{%- for p in ports %}
|
||||
reg [{{w-1}}:0] output_{{p}}_select_reg = 0;
|
||||
reg [{{w-1}}:0] output_{{p}}_select_reg = {{w}}'d0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
assign output_{{p}}_axis_tdata = output_{{p}}_axis_tdata_reg;
|
||||
@ -129,44 +129,48 @@ assign output_{{p}}_axis_tuser = output_{{p}}_axis_tuser_reg;
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_select_reg <= 0;
|
||||
output_{{p}}_select_reg <= {{w}}'d0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
input_{{p}}_axis_tdata_reg <= 0;
|
||||
input_{{p}}_axis_tvalid_reg <= 0;
|
||||
input_{{p}}_axis_tlast_reg <= 0;
|
||||
input_{{p}}_axis_tuser_reg <= 0;
|
||||
input_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
output_{{p}}_axis_tdata_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 0;
|
||||
output_{{p}}_axis_tlast_reg <= 0;
|
||||
output_{{p}}_axis_tuser_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
end else begin
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tdata_reg <= input_{{p}}_axis_tdata;
|
||||
input_{{p}}_axis_tvalid_reg <= input_{{p}}_axis_tvalid;
|
||||
input_{{p}}_axis_tlast_reg <= input_{{p}}_axis_tlast;
|
||||
input_{{p}}_axis_tuser_reg <= input_{{p}}_axis_tuser;
|
||||
{% endfor %}
|
||||
{%- for p in ports %}
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
output_{{p}}_select_reg <= output_{{p}}_select;
|
||||
{%- endfor %}
|
||||
{%- for p in ports %}
|
||||
|
||||
case (output_{{p}}_select_reg)
|
||||
{%- for q in ports %}
|
||||
{{w}}'d{{q}}: begin
|
||||
output_{{p}}_axis_tdata_reg <= input_{{q}}_axis_tdata_reg;
|
||||
output_{{p}}_axis_tvalid_reg <= input_{{q}}_axis_tvalid_reg;
|
||||
output_{{p}}_axis_tlast_reg <= input_{{q}}_axis_tlast_reg;
|
||||
output_{{p}}_axis_tuser_reg <= input_{{q}}_axis_tuser_reg;
|
||||
end
|
||||
{{w}}'d{{q}}: output_{{p}}_axis_tvalid_reg <= input_{{q}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
{%- endfor %}
|
||||
end
|
||||
{%- for p in ports %}
|
||||
|
||||
input_{{p}}_axis_tdata_reg <= input_{{p}}_axis_tdata;
|
||||
input_{{p}}_axis_tlast_reg <= input_{{p}}_axis_tlast;
|
||||
input_{{p}}_axis_tuser_reg <= input_{{p}}_axis_tuser;
|
||||
{%- endfor %}
|
||||
{%- for p in ports %}
|
||||
|
||||
case (output_{{p}}_select_reg)
|
||||
{%- for q in ports %}
|
||||
{{w}}'d{{q}}: begin
|
||||
output_{{p}}_axis_tdata_reg <= input_{{q}}_axis_tdata_reg;
|
||||
output_{{p}}_axis_tlast_reg <= input_{{q}}_axis_tlast_reg;
|
||||
output_{{p}}_axis_tuser_reg <= input_{{q}}_axis_tuser_reg;
|
||||
end
|
||||
{%- endfor %}
|
||||
endcase
|
||||
{%- endfor %}
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -92,50 +92,50 @@ module axis_crosspoint_4x4 #
|
||||
input wire [1:0] output_3_select
|
||||
);
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_0_axis_tdata_reg = 0;
|
||||
reg input_0_axis_tvalid_reg = 0;
|
||||
reg input_0_axis_tlast_reg = 0;
|
||||
reg input_0_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_0_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg input_0_axis_tvalid_reg = 1'b0;
|
||||
reg input_0_axis_tlast_reg = 1'b0;
|
||||
reg input_0_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_1_axis_tdata_reg = 0;
|
||||
reg input_1_axis_tvalid_reg = 0;
|
||||
reg input_1_axis_tlast_reg = 0;
|
||||
reg input_1_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_1_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg input_1_axis_tvalid_reg = 1'b0;
|
||||
reg input_1_axis_tlast_reg = 1'b0;
|
||||
reg input_1_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_2_axis_tdata_reg = 0;
|
||||
reg input_2_axis_tvalid_reg = 0;
|
||||
reg input_2_axis_tlast_reg = 0;
|
||||
reg input_2_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_2_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg input_2_axis_tvalid_reg = 1'b0;
|
||||
reg input_2_axis_tlast_reg = 1'b0;
|
||||
reg input_2_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_3_axis_tdata_reg = 0;
|
||||
reg input_3_axis_tvalid_reg = 0;
|
||||
reg input_3_axis_tlast_reg = 0;
|
||||
reg input_3_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_3_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg input_3_axis_tvalid_reg = 1'b0;
|
||||
reg input_3_axis_tlast_reg = 1'b0;
|
||||
reg input_3_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_0_axis_tdata_reg = 0;
|
||||
reg output_0_axis_tvalid_reg = 0;
|
||||
reg output_0_axis_tlast_reg = 0;
|
||||
reg output_0_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_0_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_0_axis_tvalid_reg = 1'b0;
|
||||
reg output_0_axis_tlast_reg = 1'b0;
|
||||
reg output_0_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_1_axis_tdata_reg = 0;
|
||||
reg output_1_axis_tvalid_reg = 0;
|
||||
reg output_1_axis_tlast_reg = 0;
|
||||
reg output_1_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_1_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_1_axis_tvalid_reg = 1'b0;
|
||||
reg output_1_axis_tlast_reg = 1'b0;
|
||||
reg output_1_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_2_axis_tdata_reg = 0;
|
||||
reg output_2_axis_tvalid_reg = 0;
|
||||
reg output_2_axis_tlast_reg = 0;
|
||||
reg output_2_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_2_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_2_axis_tvalid_reg = 1'b0;
|
||||
reg output_2_axis_tlast_reg = 1'b0;
|
||||
reg output_2_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_3_axis_tdata_reg = 0;
|
||||
reg output_3_axis_tvalid_reg = 0;
|
||||
reg output_3_axis_tlast_reg = 0;
|
||||
reg output_3_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_3_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_3_axis_tvalid_reg = 1'b0;
|
||||
reg output_3_axis_tlast_reg = 1'b0;
|
||||
reg output_3_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [1:0] output_0_select_reg = 0;
|
||||
reg [1:0] output_1_select_reg = 0;
|
||||
reg [1:0] output_2_select_reg = 0;
|
||||
reg [1:0] output_3_select_reg = 0;
|
||||
reg [1:0] output_0_select_reg = 2'd0;
|
||||
reg [1:0] output_1_select_reg = 2'd0;
|
||||
reg [1:0] output_2_select_reg = 2'd0;
|
||||
reg [1:0] output_3_select_reg = 2'd0;
|
||||
|
||||
assign output_0_axis_tdata = output_0_axis_tdata_reg;
|
||||
assign output_0_axis_tvalid = output_0_axis_tvalid_reg;
|
||||
@ -160,64 +160,25 @@ assign output_3_axis_tuser = output_3_axis_tuser_reg;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_0_select_reg <= 0;
|
||||
output_1_select_reg <= 0;
|
||||
output_2_select_reg <= 0;
|
||||
output_3_select_reg <= 0;
|
||||
output_0_select_reg <= 2'd0;
|
||||
output_1_select_reg <= 2'd0;
|
||||
output_2_select_reg <= 2'd0;
|
||||
output_3_select_reg <= 2'd0;
|
||||
|
||||
input_0_axis_tdata_reg <= 0;
|
||||
input_0_axis_tvalid_reg <= 0;
|
||||
input_0_axis_tlast_reg <= 0;
|
||||
input_0_axis_tuser_reg <= 0;
|
||||
input_1_axis_tdata_reg <= 0;
|
||||
input_1_axis_tvalid_reg <= 0;
|
||||
input_1_axis_tlast_reg <= 0;
|
||||
input_1_axis_tuser_reg <= 0;
|
||||
input_2_axis_tdata_reg <= 0;
|
||||
input_2_axis_tvalid_reg <= 0;
|
||||
input_2_axis_tlast_reg <= 0;
|
||||
input_2_axis_tuser_reg <= 0;
|
||||
input_3_axis_tdata_reg <= 0;
|
||||
input_3_axis_tvalid_reg <= 0;
|
||||
input_3_axis_tlast_reg <= 0;
|
||||
input_3_axis_tuser_reg <= 0;
|
||||
input_0_axis_tvalid_reg <= 1'b0;
|
||||
input_1_axis_tvalid_reg <= 1'b0;
|
||||
input_2_axis_tvalid_reg <= 1'b0;
|
||||
input_3_axis_tvalid_reg <= 1'b0;
|
||||
|
||||
output_0_axis_tdata_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 0;
|
||||
output_0_axis_tlast_reg <= 0;
|
||||
output_0_axis_tuser_reg <= 0;
|
||||
output_1_axis_tdata_reg <= 0;
|
||||
output_1_axis_tvalid_reg <= 0;
|
||||
output_1_axis_tlast_reg <= 0;
|
||||
output_1_axis_tuser_reg <= 0;
|
||||
output_2_axis_tdata_reg <= 0;
|
||||
output_2_axis_tvalid_reg <= 0;
|
||||
output_2_axis_tlast_reg <= 0;
|
||||
output_2_axis_tuser_reg <= 0;
|
||||
output_3_axis_tdata_reg <= 0;
|
||||
output_3_axis_tvalid_reg <= 0;
|
||||
output_3_axis_tlast_reg <= 0;
|
||||
output_3_axis_tuser_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 1'b0;
|
||||
output_1_axis_tvalid_reg <= 1'b0;
|
||||
output_2_axis_tvalid_reg <= 1'b0;
|
||||
output_3_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
input_0_axis_tdata_reg <= input_0_axis_tdata;
|
||||
input_0_axis_tvalid_reg <= input_0_axis_tvalid;
|
||||
input_0_axis_tlast_reg <= input_0_axis_tlast;
|
||||
input_0_axis_tuser_reg <= input_0_axis_tuser;
|
||||
|
||||
input_1_axis_tdata_reg <= input_1_axis_tdata;
|
||||
input_1_axis_tvalid_reg <= input_1_axis_tvalid;
|
||||
input_1_axis_tlast_reg <= input_1_axis_tlast;
|
||||
input_1_axis_tuser_reg <= input_1_axis_tuser;
|
||||
|
||||
input_2_axis_tdata_reg <= input_2_axis_tdata;
|
||||
input_2_axis_tvalid_reg <= input_2_axis_tvalid;
|
||||
input_2_axis_tlast_reg <= input_2_axis_tlast;
|
||||
input_2_axis_tuser_reg <= input_2_axis_tuser;
|
||||
|
||||
input_3_axis_tdata_reg <= input_3_axis_tdata;
|
||||
input_3_axis_tvalid_reg <= input_3_axis_tvalid;
|
||||
input_3_axis_tlast_reg <= input_3_axis_tlast;
|
||||
input_3_axis_tuser_reg <= input_3_axis_tuser;
|
||||
|
||||
output_0_select_reg <= output_0_select;
|
||||
output_1_select_reg <= output_1_select;
|
||||
@ -225,113 +186,141 @@ always @(posedge clk) begin
|
||||
output_3_select_reg <= output_3_select;
|
||||
|
||||
case (output_0_select_reg)
|
||||
2'd0: begin
|
||||
output_0_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_0_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_0_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_0_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_0_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_0_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_0_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_0_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_0_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_0_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_0_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_0_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_1_select_reg)
|
||||
2'd0: begin
|
||||
output_1_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_1_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_1_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_1_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_1_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_1_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_1_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_1_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_1_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_1_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_1_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_1_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_2_select_reg)
|
||||
2'd0: begin
|
||||
output_2_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_2_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_2_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_2_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_2_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_2_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_2_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_2_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_2_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_2_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_2_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_2_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_3_select_reg)
|
||||
2'd0: begin
|
||||
output_3_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_3_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_3_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_3_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_3_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_3_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_3_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_3_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_3_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_3_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_3_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_3_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
end
|
||||
|
||||
input_0_axis_tdata_reg <= input_0_axis_tdata;
|
||||
input_0_axis_tlast_reg <= input_0_axis_tlast;
|
||||
input_0_axis_tuser_reg <= input_0_axis_tuser;
|
||||
|
||||
input_1_axis_tdata_reg <= input_1_axis_tdata;
|
||||
input_1_axis_tlast_reg <= input_1_axis_tlast;
|
||||
input_1_axis_tuser_reg <= input_1_axis_tuser;
|
||||
|
||||
input_2_axis_tdata_reg <= input_2_axis_tdata;
|
||||
input_2_axis_tlast_reg <= input_2_axis_tlast;
|
||||
input_2_axis_tuser_reg <= input_2_axis_tuser;
|
||||
|
||||
input_3_axis_tdata_reg <= input_3_axis_tdata;
|
||||
input_3_axis_tlast_reg <= input_3_axis_tlast;
|
||||
input_3_axis_tuser_reg <= input_3_axis_tuser;
|
||||
|
||||
case (output_0_select_reg)
|
||||
2'd0: begin
|
||||
output_0_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_0_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_0_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_0_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_0_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_0_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_0_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_0_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_1_select_reg)
|
||||
2'd0: begin
|
||||
output_1_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_1_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_1_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_1_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_1_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_1_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_1_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_1_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_2_select_reg)
|
||||
2'd0: begin
|
||||
output_2_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_2_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_2_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_2_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_2_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_2_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_2_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_2_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_3_select_reg)
|
||||
2'd0: begin
|
||||
output_3_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_3_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_3_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_3_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_3_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_3_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_3_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_3_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -106,23 +106,23 @@ module {{name}} #
|
||||
{%- endfor %}
|
||||
);
|
||||
{% for p in ports %}
|
||||
reg [DATA_WIDTH-1:0] input_{{p}}_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] input_{{p}}_axis_tkeep_reg = 0;
|
||||
reg input_{{p}}_axis_tvalid_reg = 0;
|
||||
reg input_{{p}}_axis_tlast_reg = 0;
|
||||
reg input_{{p}}_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_{{p}}_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] input_{{p}}_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg input_{{p}}_axis_tvalid_reg = 1'b0;
|
||||
reg input_{{p}}_axis_tlast_reg = 1'b0;
|
||||
reg input_{{p}}_axis_tuser_reg = 1'b0;
|
||||
{% endfor %}
|
||||
|
||||
{%- for p in ports %}
|
||||
reg [DATA_WIDTH-1:0] output_{{p}}_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_{{p}}_axis_tkeep_reg = 0;
|
||||
reg output_{{p}}_axis_tvalid_reg = 0;
|
||||
reg output_{{p}}_axis_tlast_reg = 0;
|
||||
reg output_{{p}}_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_{{p}}_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_{{p}}_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_{{p}}_axis_tvalid_reg = 1'b0;
|
||||
reg output_{{p}}_axis_tlast_reg = 1'b0;
|
||||
reg output_{{p}}_axis_tuser_reg = 1'b0;
|
||||
{% endfor %}
|
||||
|
||||
{%- for p in ports %}
|
||||
reg [{{w-1}}:0] output_{{p}}_select_reg = 0;
|
||||
reg [{{w-1}}:0] output_{{p}}_select_reg = {{w}}'d0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
assign output_{{p}}_axis_tdata = output_{{p}}_axis_tdata_reg;
|
||||
@ -135,48 +135,50 @@ assign output_{{p}}_axis_tuser = output_{{p}}_axis_tuser_reg;
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_select_reg <= 0;
|
||||
output_{{p}}_select_reg <= {{w}}'d0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
input_{{p}}_axis_tdata_reg <= 0;
|
||||
input_{{p}}_axis_tkeep_reg <= 0;
|
||||
input_{{p}}_axis_tvalid_reg <= 0;
|
||||
input_{{p}}_axis_tlast_reg <= 0;
|
||||
input_{{p}}_axis_tuser_reg <= 0;
|
||||
input_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
output_{{p}}_axis_tdata_reg <= 0;
|
||||
output_{{p}}_axis_tkeep_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 0;
|
||||
output_{{p}}_axis_tlast_reg <= 0;
|
||||
output_{{p}}_axis_tuser_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
end else begin
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tdata_reg <= input_{{p}}_axis_tdata;
|
||||
input_{{p}}_axis_tkeep_reg <= input_{{p}}_axis_tkeep;
|
||||
input_{{p}}_axis_tvalid_reg <= input_{{p}}_axis_tvalid;
|
||||
input_{{p}}_axis_tlast_reg <= input_{{p}}_axis_tlast;
|
||||
input_{{p}}_axis_tuser_reg <= input_{{p}}_axis_tuser;
|
||||
{% endfor %}
|
||||
{%- for p in ports %}
|
||||
{%- endfor %}
|
||||
{% for p in ports %}
|
||||
output_{{p}}_select_reg <= output_{{p}}_select;
|
||||
{%- endfor %}
|
||||
{%- for p in ports %}
|
||||
|
||||
case (output_{{p}}_select_reg)
|
||||
{%- for q in ports %}
|
||||
{{w}}'d{{q}}: begin
|
||||
output_{{p}}_axis_tdata_reg <= input_{{q}}_axis_tdata_reg;
|
||||
output_{{p}}_axis_tkeep_reg <= input_{{q}}_axis_tkeep_reg;
|
||||
output_{{p}}_axis_tvalid_reg <= input_{{q}}_axis_tvalid_reg;
|
||||
output_{{p}}_axis_tlast_reg <= input_{{q}}_axis_tlast_reg;
|
||||
output_{{p}}_axis_tuser_reg <= input_{{q}}_axis_tuser_reg;
|
||||
end
|
||||
{{w}}'d{{q}}: output_{{p}}_axis_tvalid_reg <= input_{{q}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
{%- endfor %}
|
||||
end
|
||||
{%- for p in ports %}
|
||||
|
||||
input_{{p}}_axis_tdata_reg <= input_{{p}}_axis_tdata;
|
||||
input_{{p}}_axis_tkeep_reg <= input_{{p}}_axis_tkeep;
|
||||
input_{{p}}_axis_tlast_reg <= input_{{p}}_axis_tlast;
|
||||
input_{{p}}_axis_tuser_reg <= input_{{p}}_axis_tuser;
|
||||
{%- endfor %}
|
||||
{%- for p in ports %}
|
||||
|
||||
case (output_{{p}}_select_reg)
|
||||
{%- for q in ports %}
|
||||
{{w}}'d{{q}}: begin
|
||||
output_{{p}}_axis_tdata_reg <= input_{{q}}_axis_tdata_reg;
|
||||
output_{{p}}_axis_tkeep_reg <= input_{{q}}_axis_tkeep_reg;
|
||||
output_{{p}}_axis_tlast_reg <= input_{{q}}_axis_tlast_reg;
|
||||
output_{{p}}_axis_tuser_reg <= input_{{q}}_axis_tuser_reg;
|
||||
end
|
||||
{%- endfor %}
|
||||
endcase
|
||||
{%- endfor %}
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -101,58 +101,58 @@ module axis_crosspoint_64_4x4 #
|
||||
input wire [1:0] output_3_select
|
||||
);
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_0_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] input_0_axis_tkeep_reg = 0;
|
||||
reg input_0_axis_tvalid_reg = 0;
|
||||
reg input_0_axis_tlast_reg = 0;
|
||||
reg input_0_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_0_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] input_0_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg input_0_axis_tvalid_reg = 1'b0;
|
||||
reg input_0_axis_tlast_reg = 1'b0;
|
||||
reg input_0_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_1_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] input_1_axis_tkeep_reg = 0;
|
||||
reg input_1_axis_tvalid_reg = 0;
|
||||
reg input_1_axis_tlast_reg = 0;
|
||||
reg input_1_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_1_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] input_1_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg input_1_axis_tvalid_reg = 1'b0;
|
||||
reg input_1_axis_tlast_reg = 1'b0;
|
||||
reg input_1_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_2_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] input_2_axis_tkeep_reg = 0;
|
||||
reg input_2_axis_tvalid_reg = 0;
|
||||
reg input_2_axis_tlast_reg = 0;
|
||||
reg input_2_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_2_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] input_2_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg input_2_axis_tvalid_reg = 1'b0;
|
||||
reg input_2_axis_tlast_reg = 1'b0;
|
||||
reg input_2_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] input_3_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] input_3_axis_tkeep_reg = 0;
|
||||
reg input_3_axis_tvalid_reg = 0;
|
||||
reg input_3_axis_tlast_reg = 0;
|
||||
reg input_3_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] input_3_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] input_3_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg input_3_axis_tvalid_reg = 1'b0;
|
||||
reg input_3_axis_tlast_reg = 1'b0;
|
||||
reg input_3_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_0_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_0_axis_tkeep_reg = 0;
|
||||
reg output_0_axis_tvalid_reg = 0;
|
||||
reg output_0_axis_tlast_reg = 0;
|
||||
reg output_0_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_0_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_0_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_0_axis_tvalid_reg = 1'b0;
|
||||
reg output_0_axis_tlast_reg = 1'b0;
|
||||
reg output_0_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_1_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_1_axis_tkeep_reg = 0;
|
||||
reg output_1_axis_tvalid_reg = 0;
|
||||
reg output_1_axis_tlast_reg = 0;
|
||||
reg output_1_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_1_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_1_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_1_axis_tvalid_reg = 1'b0;
|
||||
reg output_1_axis_tlast_reg = 1'b0;
|
||||
reg output_1_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_2_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_2_axis_tkeep_reg = 0;
|
||||
reg output_2_axis_tvalid_reg = 0;
|
||||
reg output_2_axis_tlast_reg = 0;
|
||||
reg output_2_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_2_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_2_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_2_axis_tvalid_reg = 1'b0;
|
||||
reg output_2_axis_tlast_reg = 1'b0;
|
||||
reg output_2_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_3_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_3_axis_tkeep_reg = 0;
|
||||
reg output_3_axis_tvalid_reg = 0;
|
||||
reg output_3_axis_tlast_reg = 0;
|
||||
reg output_3_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_3_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_3_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_3_axis_tvalid_reg = 1'b0;
|
||||
reg output_3_axis_tlast_reg = 1'b0;
|
||||
reg output_3_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [1:0] output_0_select_reg = 0;
|
||||
reg [1:0] output_1_select_reg = 0;
|
||||
reg [1:0] output_2_select_reg = 0;
|
||||
reg [1:0] output_3_select_reg = 0;
|
||||
reg [1:0] output_0_select_reg = 2'd0;
|
||||
reg [1:0] output_1_select_reg = 2'd0;
|
||||
reg [1:0] output_2_select_reg = 2'd0;
|
||||
reg [1:0] output_3_select_reg = 2'd0;
|
||||
|
||||
assign output_0_axis_tdata = output_0_axis_tdata_reg;
|
||||
assign output_0_axis_tkeep = output_0_axis_tkeep_reg;
|
||||
@ -181,76 +181,25 @@ assign output_3_axis_tuser = output_3_axis_tuser_reg;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_0_select_reg <= 0;
|
||||
output_1_select_reg <= 0;
|
||||
output_2_select_reg <= 0;
|
||||
output_3_select_reg <= 0;
|
||||
output_0_select_reg <= 2'd0;
|
||||
output_1_select_reg <= 2'd0;
|
||||
output_2_select_reg <= 2'd0;
|
||||
output_3_select_reg <= 2'd0;
|
||||
|
||||
input_0_axis_tdata_reg <= 0;
|
||||
input_0_axis_tkeep_reg <= 0;
|
||||
input_0_axis_tvalid_reg <= 0;
|
||||
input_0_axis_tlast_reg <= 0;
|
||||
input_0_axis_tuser_reg <= 0;
|
||||
input_1_axis_tdata_reg <= 0;
|
||||
input_1_axis_tkeep_reg <= 0;
|
||||
input_1_axis_tvalid_reg <= 0;
|
||||
input_1_axis_tlast_reg <= 0;
|
||||
input_1_axis_tuser_reg <= 0;
|
||||
input_2_axis_tdata_reg <= 0;
|
||||
input_2_axis_tkeep_reg <= 0;
|
||||
input_2_axis_tvalid_reg <= 0;
|
||||
input_2_axis_tlast_reg <= 0;
|
||||
input_2_axis_tuser_reg <= 0;
|
||||
input_3_axis_tdata_reg <= 0;
|
||||
input_3_axis_tkeep_reg <= 0;
|
||||
input_3_axis_tvalid_reg <= 0;
|
||||
input_3_axis_tlast_reg <= 0;
|
||||
input_3_axis_tuser_reg <= 0;
|
||||
input_0_axis_tvalid_reg <= 1'b0;
|
||||
input_1_axis_tvalid_reg <= 1'b0;
|
||||
input_2_axis_tvalid_reg <= 1'b0;
|
||||
input_3_axis_tvalid_reg <= 1'b0;
|
||||
|
||||
output_0_axis_tdata_reg <= 0;
|
||||
output_0_axis_tkeep_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 0;
|
||||
output_0_axis_tlast_reg <= 0;
|
||||
output_0_axis_tuser_reg <= 0;
|
||||
output_1_axis_tdata_reg <= 0;
|
||||
output_1_axis_tkeep_reg <= 0;
|
||||
output_1_axis_tvalid_reg <= 0;
|
||||
output_1_axis_tlast_reg <= 0;
|
||||
output_1_axis_tuser_reg <= 0;
|
||||
output_2_axis_tdata_reg <= 0;
|
||||
output_2_axis_tkeep_reg <= 0;
|
||||
output_2_axis_tvalid_reg <= 0;
|
||||
output_2_axis_tlast_reg <= 0;
|
||||
output_2_axis_tuser_reg <= 0;
|
||||
output_3_axis_tdata_reg <= 0;
|
||||
output_3_axis_tkeep_reg <= 0;
|
||||
output_3_axis_tvalid_reg <= 0;
|
||||
output_3_axis_tlast_reg <= 0;
|
||||
output_3_axis_tuser_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 1'b0;
|
||||
output_1_axis_tvalid_reg <= 1'b0;
|
||||
output_2_axis_tvalid_reg <= 1'b0;
|
||||
output_3_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
input_0_axis_tdata_reg <= input_0_axis_tdata;
|
||||
input_0_axis_tkeep_reg <= input_0_axis_tkeep;
|
||||
input_0_axis_tvalid_reg <= input_0_axis_tvalid;
|
||||
input_0_axis_tlast_reg <= input_0_axis_tlast;
|
||||
input_0_axis_tuser_reg <= input_0_axis_tuser;
|
||||
|
||||
input_1_axis_tdata_reg <= input_1_axis_tdata;
|
||||
input_1_axis_tkeep_reg <= input_1_axis_tkeep;
|
||||
input_1_axis_tvalid_reg <= input_1_axis_tvalid;
|
||||
input_1_axis_tlast_reg <= input_1_axis_tlast;
|
||||
input_1_axis_tuser_reg <= input_1_axis_tuser;
|
||||
|
||||
input_2_axis_tdata_reg <= input_2_axis_tdata;
|
||||
input_2_axis_tkeep_reg <= input_2_axis_tkeep;
|
||||
input_2_axis_tvalid_reg <= input_2_axis_tvalid;
|
||||
input_2_axis_tlast_reg <= input_2_axis_tlast;
|
||||
input_2_axis_tuser_reg <= input_2_axis_tuser;
|
||||
|
||||
input_3_axis_tdata_reg <= input_3_axis_tdata;
|
||||
input_3_axis_tkeep_reg <= input_3_axis_tkeep;
|
||||
input_3_axis_tvalid_reg <= input_3_axis_tvalid;
|
||||
input_3_axis_tlast_reg <= input_3_axis_tlast;
|
||||
input_3_axis_tuser_reg <= input_3_axis_tuser;
|
||||
|
||||
output_0_select_reg <= output_0_select;
|
||||
output_1_select_reg <= output_1_select;
|
||||
@ -258,129 +207,161 @@ always @(posedge clk) begin
|
||||
output_3_select_reg <= output_3_select;
|
||||
|
||||
case (output_0_select_reg)
|
||||
2'd0: begin
|
||||
output_0_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_0_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_0_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_0_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_0_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_0_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_0_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_0_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_0_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_0_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_0_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_0_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_0_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_1_select_reg)
|
||||
2'd0: begin
|
||||
output_1_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_1_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_1_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_1_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_1_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_1_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_1_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_1_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_1_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_1_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_1_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_1_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_1_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_2_select_reg)
|
||||
2'd0: begin
|
||||
output_2_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_2_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_2_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_2_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_2_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_2_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_2_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_2_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_2_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_2_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_2_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_2_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_2_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
|
||||
case (output_3_select_reg)
|
||||
2'd0: begin
|
||||
output_3_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_3_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_3_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_3_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_3_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_3_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_3_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_3_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
output_3_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
2'd0: output_3_axis_tvalid_reg <= input_0_axis_tvalid_reg;
|
||||
2'd1: output_3_axis_tvalid_reg <= input_1_axis_tvalid_reg;
|
||||
2'd2: output_3_axis_tvalid_reg <= input_2_axis_tvalid_reg;
|
||||
2'd3: output_3_axis_tvalid_reg <= input_3_axis_tvalid_reg;
|
||||
endcase
|
||||
end
|
||||
|
||||
input_0_axis_tdata_reg <= input_0_axis_tdata;
|
||||
input_0_axis_tkeep_reg <= input_0_axis_tkeep;
|
||||
input_0_axis_tlast_reg <= input_0_axis_tlast;
|
||||
input_0_axis_tuser_reg <= input_0_axis_tuser;
|
||||
|
||||
input_1_axis_tdata_reg <= input_1_axis_tdata;
|
||||
input_1_axis_tkeep_reg <= input_1_axis_tkeep;
|
||||
input_1_axis_tlast_reg <= input_1_axis_tlast;
|
||||
input_1_axis_tuser_reg <= input_1_axis_tuser;
|
||||
|
||||
input_2_axis_tdata_reg <= input_2_axis_tdata;
|
||||
input_2_axis_tkeep_reg <= input_2_axis_tkeep;
|
||||
input_2_axis_tlast_reg <= input_2_axis_tlast;
|
||||
input_2_axis_tuser_reg <= input_2_axis_tuser;
|
||||
|
||||
input_3_axis_tdata_reg <= input_3_axis_tdata;
|
||||
input_3_axis_tkeep_reg <= input_3_axis_tkeep;
|
||||
input_3_axis_tlast_reg <= input_3_axis_tlast;
|
||||
input_3_axis_tuser_reg <= input_3_axis_tuser;
|
||||
|
||||
case (output_0_select_reg)
|
||||
2'd0: begin
|
||||
output_0_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_0_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_0_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_0_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_0_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_0_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_0_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_0_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_0_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_0_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_1_select_reg)
|
||||
2'd0: begin
|
||||
output_1_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_1_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_1_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_1_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_1_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_1_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_1_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_1_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_1_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_1_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_2_select_reg)
|
||||
2'd0: begin
|
||||
output_2_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_2_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_2_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_2_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_2_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_2_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_2_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_2_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_2_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_2_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
|
||||
case (output_3_select_reg)
|
||||
2'd0: begin
|
||||
output_3_axis_tdata_reg <= input_0_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_0_axis_tkeep_reg;
|
||||
output_3_axis_tlast_reg <= input_0_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_0_axis_tuser_reg;
|
||||
end
|
||||
2'd1: begin
|
||||
output_3_axis_tdata_reg <= input_1_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_1_axis_tkeep_reg;
|
||||
output_3_axis_tlast_reg <= input_1_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_1_axis_tuser_reg;
|
||||
end
|
||||
2'd2: begin
|
||||
output_3_axis_tdata_reg <= input_2_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_2_axis_tkeep_reg;
|
||||
output_3_axis_tlast_reg <= input_2_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_2_axis_tuser_reg;
|
||||
end
|
||||
2'd3: begin
|
||||
output_3_axis_tdata_reg <= input_3_axis_tdata_reg;
|
||||
output_3_axis_tkeep_reg <= input_3_axis_tkeep_reg;
|
||||
output_3_axis_tlast_reg <= input_3_axis_tlast_reg;
|
||||
output_3_axis_tuser_reg <= input_3_axis_tuser_reg;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -103,15 +103,15 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -129,6 +129,10 @@ always @* begin
|
||||
current_output_tready = output_{{p}}_axis_tready;
|
||||
end
|
||||
{%- endfor %}
|
||||
default: begin
|
||||
current_output_tvalid = 1'b0;
|
||||
current_output_tready = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -136,7 +140,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (input_axis_tvalid & input_axis_tready) begin
|
||||
@ -145,7 +149,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -159,9 +163,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
select_reg <= {{w}}'d0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -170,77 +174,95 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
{%- for p in ports %}
|
||||
reg output_{{p}}_axis_tvalid_reg = 0;
|
||||
reg output_{{p}}_axis_tvalid_reg = 1'b0, output_{{p}}_axis_tvalid_next;
|
||||
{%- endfor %}
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
{% for p in ports %}
|
||||
assign output_{{p}}_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_{{p}}_axis_tvalid = output_{{p}}_axis_tvalid_reg;
|
||||
assign output_{{p}}_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_{{p}}_axis_tuser = output_axis_tuser_reg;
|
||||
{% endfor %}
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= output_{{p}}_axis_tvalid_next;
|
||||
{%- endfor %}
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
case (select_reg)
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
case (select_reg)
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -80,15 +80,15 @@ module axis_demux_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -116,6 +116,10 @@ always @* begin
|
||||
current_output_tvalid = output_3_axis_tvalid;
|
||||
current_output_tready = output_3_axis_tready;
|
||||
end
|
||||
default: begin
|
||||
current_output_tvalid = 1'b0;
|
||||
current_output_tready = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -123,7 +127,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (input_axis_tvalid & input_axis_tready) begin
|
||||
@ -132,7 +136,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -146,9 +150,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
select_reg <= 2'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -157,18 +161,23 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_0_axis_tvalid_reg = 0;
|
||||
reg output_1_axis_tvalid_reg = 0;
|
||||
reg output_2_axis_tvalid_reg = 0;
|
||||
reg output_3_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_0_axis_tvalid_reg = 1'b0, output_0_axis_tvalid_next;
|
||||
reg output_1_axis_tvalid_reg = 1'b0, output_1_axis_tvalid_next;
|
||||
reg output_2_axis_tvalid_reg = 1'b0, output_2_axis_tvalid_next;
|
||||
reg output_3_axis_tvalid_reg = 1'b0, output_3_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_0_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_0_axis_tvalid = output_0_axis_tvalid_reg;
|
||||
@ -190,63 +199,78 @@ assign output_3_axis_tvalid = output_3_axis_tvalid_reg;
|
||||
assign output_3_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_3_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_0_axis_tvalid_next = output_0_axis_tvalid_reg;
|
||||
output_1_axis_tvalid_next = output_1_axis_tvalid_reg;
|
||||
output_2_axis_tvalid_next = output_2_axis_tvalid_reg;
|
||||
output_3_axis_tvalid_next = output_3_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_0_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd0);
|
||||
output_1_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd1);
|
||||
output_2_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd2);
|
||||
output_3_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd3);
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_0_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd0);
|
||||
output_1_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd1);
|
||||
output_2_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd2);
|
||||
output_3_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd3);
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 0;
|
||||
output_1_axis_tvalid_reg <= 0;
|
||||
output_2_axis_tvalid_reg <= 0;
|
||||
output_3_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 1'b0;
|
||||
output_1_axis_tvalid_reg <= 1'b0;
|
||||
output_2_axis_tvalid_reg <= 1'b0;
|
||||
output_3_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_0_axis_tvalid_reg <= output_0_axis_tvalid_next;
|
||||
output_1_axis_tvalid_reg <= output_1_axis_tvalid_next;
|
||||
output_2_axis_tvalid_reg <= output_2_axis_tvalid_next;
|
||||
output_3_axis_tvalid_reg <= output_3_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
case (select_reg)
|
||||
2'd0: output_0_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd1: output_1_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd2: output_2_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd3: output_3_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
case (select_reg)
|
||||
2'd0: output_0_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd1: output_1_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd2: output_2_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd3: output_3_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
endcase
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -106,16 +106,16 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -133,6 +133,10 @@ always @* begin
|
||||
current_output_tready = output_{{p}}_axis_tready;
|
||||
end
|
||||
{%- endfor %}
|
||||
default: begin
|
||||
current_output_tvalid = 1'b0;
|
||||
current_output_tready = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -140,7 +144,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (input_axis_tvalid & input_axis_tready) begin
|
||||
@ -149,7 +153,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -164,9 +168,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
select_reg <= {{w}}'d0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -175,19 +179,24 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
{%- for p in ports %}
|
||||
reg output_{{p}}_axis_tvalid_reg = 0;
|
||||
reg output_{{p}}_axis_tvalid_reg = 1'b0, output_{{p}}_axis_tvalid_next;
|
||||
{%- endfor %}
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
{% for p in ports %}
|
||||
assign output_{{p}}_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_{{p}}_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -195,66 +204,76 @@ assign output_{{p}}_axis_tvalid = output_{{p}}_axis_tvalid_reg;
|
||||
assign output_{{p}}_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_{{p}}_axis_tuser = output_axis_tuser_reg;
|
||||
{% endfor %}
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= 0;
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= output_{{p}}_axis_tvalid_next;
|
||||
{%- endfor %}
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
case (select_reg)
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
case (select_reg)
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -86,16 +86,16 @@ module axis_demux_64_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -123,6 +123,10 @@ always @* begin
|
||||
current_output_tvalid = output_3_axis_tvalid;
|
||||
current_output_tready = output_3_axis_tready;
|
||||
end
|
||||
default: begin
|
||||
current_output_tvalid = 1'b0;
|
||||
current_output_tready = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -130,7 +134,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (input_axis_tvalid & input_axis_tready) begin
|
||||
@ -139,7 +143,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -154,9 +158,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
select_reg <= 2'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -165,20 +169,25 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_0_axis_tvalid_reg = 0;
|
||||
reg output_1_axis_tvalid_reg = 0;
|
||||
reg output_2_axis_tvalid_reg = 0;
|
||||
reg output_3_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_0_axis_tvalid_reg = 1'b0, output_0_axis_tvalid_next;
|
||||
reg output_1_axis_tvalid_reg = 1'b0, output_1_axis_tvalid_next;
|
||||
reg output_2_axis_tvalid_reg = 1'b0, output_2_axis_tvalid_next;
|
||||
reg output_3_axis_tvalid_reg = 1'b0, output_3_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_0_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_0_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -204,69 +213,81 @@ assign output_3_axis_tvalid = output_3_axis_tvalid_reg;
|
||||
assign output_3_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_3_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_0_axis_tvalid_next = output_0_axis_tvalid_reg;
|
||||
output_1_axis_tvalid_next = output_1_axis_tvalid_reg;
|
||||
output_2_axis_tvalid_next = output_2_axis_tvalid_reg;
|
||||
output_3_axis_tvalid_next = output_3_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_0_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd0);
|
||||
output_1_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd1);
|
||||
output_2_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd2);
|
||||
output_3_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd3);
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_0_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd0);
|
||||
output_1_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd1);
|
||||
output_2_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd2);
|
||||
output_3_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd3);
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 0;
|
||||
output_1_axis_tvalid_reg <= 0;
|
||||
output_2_axis_tvalid_reg <= 0;
|
||||
output_3_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_0_axis_tvalid_reg <= 1'b0;
|
||||
output_1_axis_tvalid_reg <= 1'b0;
|
||||
output_2_axis_tvalid_reg <= 1'b0;
|
||||
output_3_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_0_axis_tvalid_reg <= output_0_axis_tvalid_next;
|
||||
output_1_axis_tvalid_reg <= output_1_axis_tvalid_next;
|
||||
output_2_axis_tvalid_reg <= output_2_axis_tvalid_next;
|
||||
output_3_axis_tvalid_reg <= output_3_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (current_output_tready | ~current_output_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
case (select_reg)
|
||||
2'd0: output_0_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd1: output_1_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd2: output_2_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
2'd3: output_3_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (current_output_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
case (select_reg)
|
||||
2'd0: output_0_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd1: output_1_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd2: output_2_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
2'd3: output_3_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
endcase
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013 Alex Forencich
|
||||
Copyright (c) 2013-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -57,60 +57,93 @@ module axis_fifo #
|
||||
output wire output_axis_tuser
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
wire full = ((wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]));
|
||||
wire full = ((wr_ptr_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = wr_ptr == rd_ptr;
|
||||
wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
|
||||
wire write = input_axis_tvalid & ~full;
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = data_out_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign input_axis_tready = ~full;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// write
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr <= 0;
|
||||
end else if (write) begin
|
||||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr <= wr_ptr + 1;
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full) begin
|
||||
// not full, perform write
|
||||
write = 1'b1;
|
||||
wr_ptr_next = wr_ptr_reg + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr <= rd_ptr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tuser_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013 Alex Forencich
|
||||
Copyright (c) 2013-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -60,60 +60,96 @@ module axis_fifo_64 #
|
||||
output wire output_axis_tuser
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {KEEP_WIDTH{1'b0}}, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
wire full = ((wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]));
|
||||
wire full = ((wr_ptr_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = wr_ptr == rd_ptr;
|
||||
wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
|
||||
wire write = input_axis_tvalid & ~full;
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = data_out_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign input_axis_tready = ~full;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// write
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr <= 0;
|
||||
end else if (write) begin
|
||||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr <= wr_ptr + 1;
|
||||
// FIFO write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full) begin
|
||||
// not full, perform write
|
||||
write = 1'b1;
|
||||
wr_ptr_next = wr_ptr_reg + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr <= rd_ptr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// FIFO read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
// empty, invalidate
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tuser_reg, output_axis_tkeep_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -64,106 +64,147 @@ module axis_frame_fifo #
|
||||
output wire good_frame
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
|
||||
reg drop_frame = 1'b0;
|
||||
reg overflow_reg = 1'b0;
|
||||
reg bad_frame_reg = 1'b0;
|
||||
reg good_frame_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH+1-1:0] data_out_reg = {1'b0, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+1-1:0] data_in = {input_axis_tlast, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
wire full = ((wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]));
|
||||
wire full = ((wr_ptr_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = wr_ptr == rd_ptr;
|
||||
// overflow in single packet
|
||||
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
|
||||
wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
// overflow within packet
|
||||
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
|
||||
|
||||
wire write = input_axis_tvalid & (~full | DROP_WHEN_FULL);
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tdata} = data_out_reg;
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
reg bad_frame_reg = 1'b0, bad_frame_next;
|
||||
reg good_frame_reg = 1'b0, good_frame_next;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL);
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
|
||||
assign overflow = overflow_reg;
|
||||
assign bad_frame = bad_frame_reg;
|
||||
assign good_frame = good_frame_reg;
|
||||
|
||||
// write
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_cur <= 0;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
end else if (write) begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
if (full | full_cur | drop_frame) begin
|
||||
// buffer full, hold current pointer, drop packet at end
|
||||
drop_frame <= 1;
|
||||
if (input_axis_tlast) begin
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 1;
|
||||
end
|
||||
end else begin
|
||||
mem[wr_ptr_cur[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_cur <= wr_ptr_cur + 1;
|
||||
if (input_axis_tlast) begin
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
bad_frame_reg <= 1;
|
||||
end else begin
|
||||
// good packet, push new write pointer
|
||||
wr_ptr <= wr_ptr_cur + 1;
|
||||
good_frame_reg <= 1;
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b0;
|
||||
bad_frame_next = 1'b0;
|
||||
good_frame_next = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full | DROP_WHEN_FULL) begin
|
||||
// not full, perform write
|
||||
if (full | full_cur | drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_next = 1'b1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
write = 1'b1;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
bad_frame_next = 1'b1;
|
||||
end else begin
|
||||
// good packet, update write pointer
|
||||
wr_ptr_next = wr_ptr_cur_reg + 1;
|
||||
good_frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b0;
|
||||
bad_frame_reg <= 1'b0;
|
||||
good_frame_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_cur_reg <= wr_ptr_cur_next;
|
||||
|
||||
drop_frame_reg <= drop_frame_next;
|
||||
overflow_reg <= overflow_next;
|
||||
bad_frame_reg <= bad_frame_next;
|
||||
good_frame_reg <= good_frame_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr <= rd_ptr + 1;
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
// empty, invalidate
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -67,106 +67,148 @@ module axis_frame_fifo_64 #
|
||||
output wire good_frame
|
||||
);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_next;
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
|
||||
reg drop_frame = 1'b0;
|
||||
reg overflow_reg = 1'b0;
|
||||
reg bad_frame_reg = 1'b0;
|
||||
reg good_frame_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] data_out_reg = {1'b0, {KEEP_WIDTH{1'b0}}, {DATA_WIDTH{1'b0}}};
|
||||
|
||||
//(* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0;
|
||||
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+1-1:0] data_in = {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
wire full = ((wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]));
|
||||
wire full = ((wr_ptr_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
|
||||
// empty when pointers match exactly
|
||||
wire empty = wr_ptr == rd_ptr;
|
||||
// overflow in single packet
|
||||
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
|
||||
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
|
||||
wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
// overflow within packet
|
||||
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
|
||||
|
||||
wire write = input_axis_tvalid & (~full | DROP_WHEN_FULL);
|
||||
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = data_out_reg;
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
reg bad_frame_reg = 1'b0, bad_frame_next;
|
||||
reg good_frame_reg = 1'b0, good_frame_next;
|
||||
|
||||
assign input_axis_tready = (~full | DROP_WHEN_FULL);
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
|
||||
assign overflow = overflow_reg;
|
||||
assign bad_frame = bad_frame_reg;
|
||||
assign good_frame = good_frame_reg;
|
||||
|
||||
// write
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr <= 0;
|
||||
wr_ptr_cur <= 0;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
end else if (write) begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
if (full | full_cur | drop_frame) begin
|
||||
// buffer full, hold current pointer, drop packet at end
|
||||
drop_frame <= 1;
|
||||
if (input_axis_tlast) begin
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
drop_frame <= 0;
|
||||
overflow_reg <= 1;
|
||||
end
|
||||
end else begin
|
||||
mem[wr_ptr_cur[ADDR_WIDTH-1:0]] <= data_in;
|
||||
wr_ptr_cur <= wr_ptr_cur + 1;
|
||||
if (input_axis_tlast) begin
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur <= wr_ptr;
|
||||
bad_frame_reg <= 1;
|
||||
end else begin
|
||||
// good packet, push new write pointer
|
||||
wr_ptr <= wr_ptr_cur + 1;
|
||||
good_frame_reg <= 1;
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b0;
|
||||
bad_frame_next = 1'b0;
|
||||
good_frame_next = 1'b0;
|
||||
|
||||
wr_ptr_next = wr_ptr_reg;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg;
|
||||
|
||||
if (input_axis_tvalid) begin
|
||||
// input data valid
|
||||
if (~full | DROP_WHEN_FULL) begin
|
||||
// not full, perform write
|
||||
if (full | full_cur | drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_next = 1'b1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
drop_frame_next = 1'b0;
|
||||
overflow_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
write = 1'b1;
|
||||
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
|
||||
if (input_axis_tlast) begin
|
||||
// end of frame
|
||||
if (input_axis_tuser) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur_next = wr_ptr_reg;
|
||||
bad_frame_next = 1'b1;
|
||||
end else begin
|
||||
// good packet, update write pointer
|
||||
wr_ptr_next = wr_ptr_cur_reg + 1;
|
||||
good_frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b0;
|
||||
bad_frame_reg <= 1'b0;
|
||||
good_frame_reg <= 1'b0;
|
||||
end else begin
|
||||
overflow_reg <= 0;
|
||||
bad_frame_reg <= 0;
|
||||
good_frame_reg <= 0;
|
||||
wr_ptr_reg <= wr_ptr_next;
|
||||
wr_ptr_cur_reg <= wr_ptr_cur_next;
|
||||
|
||||
drop_frame_reg <= drop_frame_next;
|
||||
overflow_reg <= overflow_next;
|
||||
bad_frame_reg <= bad_frame_next;
|
||||
good_frame_reg <= good_frame_next;
|
||||
end
|
||||
|
||||
if (write) begin
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
end
|
||||
end
|
||||
|
||||
// read
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr <= 0;
|
||||
end else if (read) begin
|
||||
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||||
rd_ptr <= rd_ptr + 1;
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// source ready output
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
output_axis_tvalid_reg <= ~empty;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_reg;
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (read) begin
|
||||
{output_axis_tlast_reg, output_axis_tkeep_reg, output_axis_tdata_reg} <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -118,25 +118,25 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg [2:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
reg [{{w-1}}:0] port_sel_reg = 0, port_sel_next;
|
||||
reg [2:0] frame_ptr_reg = 3'd0, frame_ptr_next;
|
||||
reg [{{w-1}}:0] port_sel_reg = {{w}}'d0, port_sel_next;
|
||||
|
||||
reg busy_reg = 0, busy_next;
|
||||
reg busy_reg = 1'b0, busy_next;
|
||||
|
||||
reg [7:0] input_tdata;
|
||||
reg input_tvalid;
|
||||
reg input_tlast;
|
||||
reg input_tuser;
|
||||
|
||||
reg output_tuser_reg = 0, output_tuser_next;
|
||||
reg output_tuser_reg = 1'b0, output_tuser_next;
|
||||
{% for p in ports %}
|
||||
reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next;
|
||||
reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next;
|
||||
{%- endfor %}
|
||||
|
||||
// internal datapath
|
||||
reg [7:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -163,31 +163,31 @@ end
|
||||
integer offset, i;
|
||||
|
||||
always @* begin
|
||||
state_next = 2'bz;
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
port_sel_next = port_sel_reg;
|
||||
{% for p in ports %}
|
||||
input_{{p}}_axis_tready_next = 0;
|
||||
input_{{p}}_axis_tready_next = 1'b0;
|
||||
{%- endfor %}
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = 8'd0;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
output_tuser_next = output_tuser_reg;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state - wait for data
|
||||
frame_ptr_next = 0;
|
||||
port_sel_next = 0;
|
||||
output_tuser_next = 0;
|
||||
frame_ptr_next = 3'd0;
|
||||
port_sel_next = {{w}}'d0;
|
||||
output_tuser_next = 1'b0;
|
||||
|
||||
if (TAG_ENABLE) begin
|
||||
// next cycle if started will send tag, so do not enable input
|
||||
input_0_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
end else begin
|
||||
// next cycle if started will send data, so enable input
|
||||
input_0_axis_tready_next = output_axis_tready_int_early;
|
||||
@ -197,19 +197,19 @@ always @* begin
|
||||
// input 0 valid; start transferring data
|
||||
if (TAG_ENABLE) begin
|
||||
// tag enabled, so transmit it
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first tag byte
|
||||
frame_ptr_next = 1;
|
||||
frame_ptr_next = 3'd1;
|
||||
output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8];
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_WRITE_TAG;
|
||||
end else begin
|
||||
// tag disabled, so transmit data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first data byte
|
||||
output_axis_tdata_int = input_0_axis_tdata;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_TRANSFER;
|
||||
end
|
||||
@ -219,11 +219,11 @@ always @* begin
|
||||
end
|
||||
STATE_WRITE_TAG: begin
|
||||
// write tag data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output ready, so send tag byte
|
||||
state_next = STATE_WRITE_TAG;
|
||||
frame_ptr_next = frame_ptr_reg + 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
|
||||
offset = 0;
|
||||
if (TAG_ENABLE) begin
|
||||
@ -252,7 +252,7 @@ always @* begin
|
||||
{%- endfor %}
|
||||
endcase
|
||||
|
||||
if (input_tvalid & output_axis_tready_int) begin
|
||||
if (input_tvalid & output_axis_tready_int_reg) begin
|
||||
// output ready, transfer byte
|
||||
state_next = STATE_TRANSFER;
|
||||
output_axis_tdata_int = input_tdata;
|
||||
@ -265,12 +265,12 @@ always @* begin
|
||||
output_tuser_next = output_tuser_next | input_tuser;
|
||||
// disable input
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tready_next = 0;
|
||||
input_{{p}}_axis_tready_next = 1'b0;
|
||||
{%- endfor %}
|
||||
|
||||
if (port_sel_reg == {{n-1}}) begin
|
||||
if (port_sel_reg == {{w}}'d{{n-1}}) begin
|
||||
// last port - send tlast and tuser and revert to idle
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = output_tuser_next;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
@ -292,13 +292,13 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_ptr_reg <= 0;
|
||||
port_sel_reg <= 0;
|
||||
frame_ptr_reg <= 3'd0;
|
||||
port_sel_reg <= {{w}}'d0;
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tready_reg <= 0;
|
||||
input_{{p}}_axis_tready_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
output_tuser_reg <= 0;
|
||||
busy_reg <= 0;
|
||||
output_tuser_reg <= 1'b0;
|
||||
busy_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
@ -316,65 +316,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [7:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [7:0] output_axis_tdata_reg = 8'd0;
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [7:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [7:0] temp_axis_tdata_reg = 8'd0;
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -95,27 +95,27 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg [2:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
reg [1:0] port_sel_reg = 0, port_sel_next;
|
||||
reg [2:0] frame_ptr_reg = 3'd0, frame_ptr_next;
|
||||
reg [1:0] port_sel_reg = 2'd0, port_sel_next;
|
||||
|
||||
reg busy_reg = 0, busy_next;
|
||||
reg busy_reg = 1'b0, busy_next;
|
||||
|
||||
reg [7:0] input_tdata;
|
||||
reg input_tvalid;
|
||||
reg input_tlast;
|
||||
reg input_tuser;
|
||||
|
||||
reg output_tuser_reg = 0, output_tuser_next;
|
||||
reg output_tuser_reg = 1'b0, output_tuser_next;
|
||||
|
||||
reg input_0_axis_tready_reg = 0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 0, input_3_axis_tready_next;
|
||||
reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [7:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -160,33 +160,33 @@ end
|
||||
integer offset, i;
|
||||
|
||||
always @* begin
|
||||
state_next = 2'bz;
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
port_sel_next = port_sel_reg;
|
||||
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = 8'd0;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
output_tuser_next = output_tuser_reg;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state - wait for data
|
||||
frame_ptr_next = 0;
|
||||
port_sel_next = 0;
|
||||
output_tuser_next = 0;
|
||||
frame_ptr_next = 3'd0;
|
||||
port_sel_next = 2'd0;
|
||||
output_tuser_next = 1'b0;
|
||||
|
||||
if (TAG_ENABLE) begin
|
||||
// next cycle if started will send tag, so do not enable input
|
||||
input_0_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
end else begin
|
||||
// next cycle if started will send data, so enable input
|
||||
input_0_axis_tready_next = output_axis_tready_int_early;
|
||||
@ -196,19 +196,19 @@ always @* begin
|
||||
// input 0 valid; start transferring data
|
||||
if (TAG_ENABLE) begin
|
||||
// tag enabled, so transmit it
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first tag byte
|
||||
frame_ptr_next = 1;
|
||||
frame_ptr_next = 3'd1;
|
||||
output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8];
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_WRITE_TAG;
|
||||
end else begin
|
||||
// tag disabled, so transmit data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first data byte
|
||||
output_axis_tdata_int = input_0_axis_tdata;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_TRANSFER;
|
||||
end
|
||||
@ -218,11 +218,11 @@ always @* begin
|
||||
end
|
||||
STATE_WRITE_TAG: begin
|
||||
// write tag data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output ready, so send tag byte
|
||||
state_next = STATE_WRITE_TAG;
|
||||
frame_ptr_next = frame_ptr_reg + 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
|
||||
offset = 0;
|
||||
if (TAG_ENABLE) begin
|
||||
@ -252,7 +252,7 @@ always @* begin
|
||||
2'd3: input_3_axis_tready_next = output_axis_tready_int_early;
|
||||
endcase
|
||||
|
||||
if (input_tvalid & output_axis_tready_int) begin
|
||||
if (input_tvalid & output_axis_tready_int_reg) begin
|
||||
// output ready, transfer byte
|
||||
state_next = STATE_TRANSFER;
|
||||
output_axis_tdata_int = input_tdata;
|
||||
@ -264,14 +264,14 @@ always @* begin
|
||||
// save tuser - assert tuser out if ANY tuser asserts received
|
||||
output_tuser_next = output_tuser_next | input_tuser;
|
||||
// disable input
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
if (port_sel_reg == 3) begin
|
||||
if (port_sel_reg == 2'd3) begin
|
||||
// last port - send tlast and tuser and revert to idle
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = output_tuser_next;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
@ -294,14 +294,14 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_ptr_reg <= 0;
|
||||
port_sel_reg <= 0;
|
||||
input_0_axis_tready_reg <= 0;
|
||||
input_1_axis_tready_reg <= 0;
|
||||
input_2_axis_tready_reg <= 0;
|
||||
input_3_axis_tready_reg <= 0;
|
||||
output_tuser_reg <= 0;
|
||||
busy_reg <= 0;
|
||||
frame_ptr_reg <= 3'd0;
|
||||
port_sel_reg <= 2'd0;
|
||||
input_0_axis_tready_reg <= 1'b0;
|
||||
input_1_axis_tready_reg <= 1'b0;
|
||||
input_2_axis_tready_reg <= 1'b0;
|
||||
input_3_axis_tready_reg <= 1'b0;
|
||||
output_tuser_reg <= 1'b0;
|
||||
busy_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
@ -321,65 +321,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [7:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [7:0] output_axis_tdata_reg = 8'd0;
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [7:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [7:0] temp_axis_tdata_reg = 8'd0;
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,33 +98,33 @@ reg [2:0] state_reg = STATE_IDLE, state_next;
|
||||
// datapath control signals
|
||||
reg store_last_word;
|
||||
|
||||
reg [15:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_next;
|
||||
|
||||
// frame length counters
|
||||
reg [15:0] short_counter_reg = 0, short_counter_next = 0;
|
||||
reg [15:0] long_counter_reg = 0, long_counter_next = 0;
|
||||
reg [15:0] short_counter_reg = 16'd0, short_counter_next = 16'd0;
|
||||
reg [15:0] long_counter_reg = 16'd0, long_counter_next = 16'd0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] last_word_data_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] last_word_keep_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] last_word_data_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] last_word_keep_reg = {KEEP_WIDTH{1'b0}};
|
||||
|
||||
reg last_cycle_tuser_reg = 0, last_cycle_tuser_next;
|
||||
reg last_cycle_tuser_reg = 1'b0, last_cycle_tuser_next;
|
||||
|
||||
reg status_valid_reg = 0, status_valid_next;
|
||||
reg status_frame_pad_reg = 0, status_frame_pad_next;
|
||||
reg status_frame_truncate_reg = 0, status_frame_truncate_next;
|
||||
reg [15:0] status_frame_length_reg = 0, status_frame_length_next;
|
||||
reg [15:0] status_frame_original_length_reg = 0, status_frame_original_length_next;
|
||||
reg status_valid_reg = 1'b0, status_valid_next;
|
||||
reg status_frame_pad_reg = 1'b0, status_frame_pad_next;
|
||||
reg status_frame_truncate_reg = 1'b0, status_frame_truncate_next;
|
||||
reg [15:0] status_frame_length_reg = 16'd0, status_frame_length_next;
|
||||
reg [15:0] status_frame_original_length_reg = 16'd0, status_frame_original_length_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
assign status_valid = status_valid_reg;
|
||||
@ -138,20 +138,20 @@ integer i, word_cnt;
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
store_last_word = 0;
|
||||
store_last_word = 1'b0;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
|
||||
short_counter_next = short_counter_reg;
|
||||
long_counter_next = long_counter_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
last_cycle_tuser_next = last_cycle_tuser_reg;
|
||||
|
||||
@ -188,31 +188,31 @@ always @* begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg <= word_cnt) begin
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg);
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = word_cnt > long_counter_reg;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
output_axis_tvalid_int = 0;
|
||||
store_last_word = 1;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
store_last_word = 1'b1;
|
||||
state_next = STATE_TRUNCATE;
|
||||
end
|
||||
end else begin
|
||||
@ -221,32 +221,32 @@ always @* begin
|
||||
if (short_counter_reg > word_cnt) begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
last_cycle_tuser_next = input_axis_tuser;
|
||||
state_next = STATE_PAD;
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-(length_min - frame_ptr_reg));
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = frame_ptr_reg+word_cnt;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -282,31 +282,31 @@ always @* begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg <= word_cnt) begin
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg);
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = word_cnt > long_counter_reg;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
output_axis_tvalid_int = 0;
|
||||
store_last_word = 1;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
store_last_word = 1'b1;
|
||||
state_next = STATE_TRUNCATE;
|
||||
end
|
||||
end else begin
|
||||
@ -315,32 +315,32 @@ always @* begin
|
||||
if (short_counter_reg > word_cnt) begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
last_cycle_tuser_next = input_axis_tuser;
|
||||
state_next = STATE_PAD;
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg);
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = frame_ptr_reg+word_cnt;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -355,39 +355,39 @@ always @* begin
|
||||
end
|
||||
STATE_PAD: begin
|
||||
// pad to minimum length
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (short_counter_reg <= KEEP_WIDTH) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg);
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = last_cycle_tuser_reg;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -417,13 +417,13 @@ always @* begin
|
||||
frame_ptr_next = frame_ptr_reg+KEEP_WIDTH;
|
||||
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 1;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b1;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -440,18 +440,11 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_ptr_reg <= 0;
|
||||
short_counter_reg <= 0;
|
||||
long_counter_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
last_word_data_reg <= 0;
|
||||
last_word_keep_reg <= 0;
|
||||
last_cycle_tuser_reg <= 0;
|
||||
status_valid_reg <= 0;
|
||||
status_frame_pad_reg <= 0;
|
||||
status_frame_truncate_reg <= 0;
|
||||
status_frame_length_reg <= 0;
|
||||
status_frame_original_length_reg <= 0;
|
||||
frame_ptr_reg <= 16'd0;
|
||||
short_counter_reg <= 16'd0;
|
||||
long_counter_reg <= 16'd0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
status_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
@ -462,33 +455,39 @@ always @(posedge clk) begin
|
||||
|
||||
input_axis_tready_reg <= input_axis_tready_next;
|
||||
|
||||
last_cycle_tuser_reg <= last_cycle_tuser_next;
|
||||
|
||||
status_valid_reg <= status_valid_next;
|
||||
status_frame_pad_reg <= status_frame_pad_next;
|
||||
status_frame_truncate_reg <= status_frame_truncate_next;
|
||||
status_frame_length_reg <= status_frame_length_next;
|
||||
status_frame_original_length_reg <= status_frame_original_length_next;
|
||||
end
|
||||
|
||||
if (store_last_word) begin
|
||||
last_word_data_reg <= output_axis_tdata_int;
|
||||
last_word_keep_reg <= output_axis_tkeep_int;
|
||||
end
|
||||
last_cycle_tuser_reg <= last_cycle_tuser_next;
|
||||
|
||||
status_frame_pad_reg <= status_frame_pad_next;
|
||||
status_frame_truncate_reg <= status_frame_truncate_next;
|
||||
status_frame_length_reg <= status_frame_length_next;
|
||||
status_frame_original_length_reg <= status_frame_original_length_next;
|
||||
|
||||
if (store_last_word) begin
|
||||
last_word_data_reg <= output_axis_tdata_int;
|
||||
last_word_keep_reg <= output_axis_tkeep_int;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -496,56 +495,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready and currently valid, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -103,16 +103,16 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
{% for p in ports %}
|
||||
reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next;
|
||||
reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next;
|
||||
{%- endfor %}
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -127,6 +127,7 @@ always @* begin
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: selected_input_tvalid = input_{{p}}_axis_tvalid;
|
||||
{%- endfor %}
|
||||
default: selected_input_tvalid = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -147,6 +148,13 @@ always @* begin
|
||||
current_input_tuser = input_{{p}}_axis_tuser;
|
||||
end
|
||||
{%- endfor %}
|
||||
default: begin
|
||||
current_input_tdata = {DATA_WIDTH{1'b0}};
|
||||
current_input_tvalid = 1'b0;
|
||||
current_input_tready = 1'b0;
|
||||
current_input_tlast = 1'b0;
|
||||
current_input_tuser = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -154,7 +162,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
{% for p in ports %}
|
||||
input_{{p}}_axis_tready_next = 0;
|
||||
input_{{p}}_axis_tready_next = 1'b0;
|
||||
{%- endfor %}
|
||||
|
||||
if (frame_reg) begin
|
||||
@ -164,7 +172,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & selected_input_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -184,10 +192,10 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
select_reg <= {{w}}'d0;
|
||||
frame_reg <= 1'b0;
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tready_reg <= 0;
|
||||
input_{{p}}_axis_tready_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
@ -199,65 +207,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -80,18 +80,18 @@ module axis_mux_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_0_axis_tready_reg = 0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 0, input_3_axis_tready_next;
|
||||
reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -109,6 +109,7 @@ always @* begin
|
||||
2'd1: selected_input_tvalid = input_1_axis_tvalid;
|
||||
2'd2: selected_input_tvalid = input_2_axis_tvalid;
|
||||
2'd3: selected_input_tvalid = input_3_axis_tvalid;
|
||||
default: selected_input_tvalid = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -148,6 +149,13 @@ always @* begin
|
||||
current_input_tlast = input_3_axis_tlast;
|
||||
current_input_tuser = input_3_axis_tuser;
|
||||
end
|
||||
default: begin
|
||||
current_input_tdata = {DATA_WIDTH{1'b0}};
|
||||
current_input_tvalid = 1'b0;
|
||||
current_input_tready = 1'b0;
|
||||
current_input_tlast = 1'b0;
|
||||
current_input_tuser = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -155,10 +163,10 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (current_input_tvalid & current_input_tready) begin
|
||||
@ -167,7 +175,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & selected_input_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -188,12 +196,12 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_0_axis_tready_reg <= 0;
|
||||
input_1_axis_tready_reg <= 0;
|
||||
input_2_axis_tready_reg <= 0;
|
||||
input_3_axis_tready_reg <= 0;
|
||||
select_reg <= 2'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_0_axis_tready_reg <= 1'b0;
|
||||
input_1_axis_tready_reg <= 1'b0;
|
||||
input_2_axis_tready_reg <= 1'b0;
|
||||
input_3_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -205,65 +213,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -106,17 +106,17 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
{% for p in ports %}
|
||||
reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next;
|
||||
reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next;
|
||||
{%- endfor %}
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -131,6 +131,7 @@ always @* begin
|
||||
{%- for p in ports %}
|
||||
{{w}}'d{{p}}: selected_input_tvalid = input_{{p}}_axis_tvalid;
|
||||
{%- endfor %}
|
||||
default: selected_input_tvalid = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -153,6 +154,14 @@ always @* begin
|
||||
current_input_tuser = input_{{p}}_axis_tuser;
|
||||
end
|
||||
{%- endfor %}
|
||||
default: begin
|
||||
current_input_tdata = {DATA_WIDTH{1'b0}};
|
||||
current_input_tkeep = {KEEP_WIDTH{1'b0}};
|
||||
current_input_tvalid = 1'b0;
|
||||
current_input_tready = 1'b0;
|
||||
current_input_tlast = 1'b0;
|
||||
current_input_tuser = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -160,7 +169,7 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
{% for p in ports %}
|
||||
input_{{p}}_axis_tready_next = 0;
|
||||
input_{{p}}_axis_tready_next = 1'b0;
|
||||
{%- endfor %}
|
||||
|
||||
if (frame_reg) begin
|
||||
@ -170,7 +179,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & selected_input_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -191,10 +200,10 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
select_reg <= {{w}}'d0;
|
||||
frame_reg <= 1'b0;
|
||||
{%- for p in ports %}
|
||||
input_{{p}}_axis_tready_reg <= 0;
|
||||
input_{{p}}_axis_tready_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
@ -206,17 +215,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -224,56 +238,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -86,19 +86,19 @@ module axis_mux_64_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_0_axis_tready_reg = 0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 0, input_3_axis_tready_next;
|
||||
reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -116,6 +116,7 @@ always @* begin
|
||||
2'd1: selected_input_tvalid = input_1_axis_tvalid;
|
||||
2'd2: selected_input_tvalid = input_2_axis_tvalid;
|
||||
2'd3: selected_input_tvalid = input_3_axis_tvalid;
|
||||
default: selected_input_tvalid = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -160,6 +161,14 @@ always @* begin
|
||||
current_input_tlast = input_3_axis_tlast;
|
||||
current_input_tuser = input_3_axis_tuser;
|
||||
end
|
||||
default: begin
|
||||
current_input_tdata = {DATA_WIDTH{1'b0}};
|
||||
current_input_tkeep = {KEEP_WIDTH{1'b0}};
|
||||
current_input_tvalid = 1'b0;
|
||||
current_input_tready = 1'b0;
|
||||
current_input_tlast = 1'b0;
|
||||
current_input_tuser = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -167,10 +176,10 @@ always @* begin
|
||||
select_next = select_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
if (frame_reg) begin
|
||||
if (current_input_tvalid & current_input_tready) begin
|
||||
@ -179,7 +188,7 @@ always @* begin
|
||||
end
|
||||
end else if (enable & selected_input_tvalid) begin
|
||||
// start of frame, grab select value
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
select_next = select;
|
||||
end
|
||||
|
||||
@ -201,12 +210,12 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_0_axis_tready_reg <= 0;
|
||||
input_1_axis_tready_reg <= 0;
|
||||
input_2_axis_tready_reg <= 0;
|
||||
input_3_axis_tready_reg <= 0;
|
||||
select_reg <= 2'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_0_axis_tready_reg <= 1'b0;
|
||||
input_1_axis_tready_reg <= 1'b0;
|
||||
input_2_axis_tready_reg <= 1'b0;
|
||||
input_3_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -218,17 +227,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -236,56 +250,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -66,21 +66,22 @@ module axis_rate_limit #
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg [23:0] acc_reg = 0, acc_next;
|
||||
reg [23:0] acc_reg = 24'd0, acc_next;
|
||||
reg pause;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
always @* begin
|
||||
acc_next = acc_reg;
|
||||
pause = 0;
|
||||
pause = 1'b0;
|
||||
frame_next = frame_reg;
|
||||
|
||||
if (acc_reg >= rate_num) begin
|
||||
@ -97,7 +98,7 @@ always @* begin
|
||||
if (rate_by_frame) begin
|
||||
pause = ~frame_next;
|
||||
end else begin
|
||||
pause = 1;
|
||||
pause = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
@ -111,9 +112,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
acc_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
acc_reg <= 24'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
acc_reg <= acc_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -122,65 +123,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -70,21 +70,22 @@ module axis_rate_limit_64 #
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg [23:0] acc_reg = 0, acc_next;
|
||||
reg [23:0] acc_reg = 24'd0, acc_next;
|
||||
reg pause;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
always @* begin
|
||||
acc_next = acc_reg;
|
||||
pause = 0;
|
||||
pause = 1'b0;
|
||||
frame_next = frame_reg;
|
||||
|
||||
if (acc_reg >= rate_num) begin
|
||||
@ -101,7 +102,7 @@ always @* begin
|
||||
if (rate_by_frame) begin
|
||||
pause = ~frame_next;
|
||||
end else begin
|
||||
pause = 1;
|
||||
pause = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
@ -116,9 +117,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
acc_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
acc_reg <= 24'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
acc_reg <= acc_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -127,17 +128,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -145,56 +151,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -57,17 +57,22 @@ module axis_register #
|
||||
);
|
||||
|
||||
// datapath registers
|
||||
reg input_axis_tready_reg = 0;
|
||||
reg input_axis_tready_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_input_to_output;
|
||||
reg store_axis_input_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
@ -76,48 +81,63 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire input_axis_tready_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~input_axis_tvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_input_to_output = 1'b0;
|
||||
store_axis_input_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (input_axis_tready_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = input_axis_tvalid;
|
||||
store_axis_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = input_axis_tvalid;
|
||||
store_axis_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
input_axis_tready_reg <= 0;
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
input_axis_tready_reg <= output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~input_axis_tvalid);
|
||||
input_axis_tready_reg <= input_axis_tready_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (input_axis_tready_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= input_axis_tdata;
|
||||
output_axis_tvalid_reg <= input_axis_tvalid;
|
||||
output_axis_tlast_reg <= input_axis_tlast;
|
||||
output_axis_tuser_reg <= input_axis_tuser;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= input_axis_tdata;
|
||||
temp_axis_tvalid_reg <= input_axis_tvalid;
|
||||
temp_axis_tlast_reg <= input_axis_tlast;
|
||||
temp_axis_tuser_reg <= input_axis_tuser;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_input_to_output) begin
|
||||
output_axis_tdata_reg <= input_axis_tdata;
|
||||
output_axis_tlast_reg <= input_axis_tlast;
|
||||
output_axis_tuser_reg <= input_axis_tuser;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_input_to_temp) begin
|
||||
temp_axis_tdata_reg <= input_axis_tdata;
|
||||
temp_axis_tlast_reg <= input_axis_tlast;
|
||||
temp_axis_tuser_reg <= input_axis_tuser;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -60,19 +60,24 @@ module axis_register_64 #
|
||||
);
|
||||
|
||||
// datapath registers
|
||||
reg input_axis_tready_reg = 0;
|
||||
reg input_axis_tready_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_input_to_output;
|
||||
reg store_axis_input_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
@ -82,54 +87,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire input_axis_tready_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~input_axis_tvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_input_to_output = 1'b0;
|
||||
store_axis_input_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (input_axis_tready_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = input_axis_tvalid;
|
||||
store_axis_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = input_axis_tvalid;
|
||||
store_axis_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
input_axis_tready_reg <= 0;
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
input_axis_tready_reg <= output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~input_axis_tvalid);
|
||||
input_axis_tready_reg <= input_axis_tready_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (input_axis_tready_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= input_axis_tdata;
|
||||
output_axis_tkeep_reg <= input_axis_tkeep;
|
||||
output_axis_tvalid_reg <= input_axis_tvalid;
|
||||
output_axis_tlast_reg <= input_axis_tlast;
|
||||
output_axis_tuser_reg <= input_axis_tuser;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= input_axis_tdata;
|
||||
temp_axis_tkeep_reg <= input_axis_tkeep;
|
||||
temp_axis_tvalid_reg <= input_axis_tvalid;
|
||||
temp_axis_tlast_reg <= input_axis_tlast;
|
||||
temp_axis_tuser_reg <= input_axis_tuser;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_input_to_output) begin
|
||||
output_axis_tdata_reg <= input_axis_tdata;
|
||||
output_axis_tkeep_reg <= input_axis_tkeep;
|
||||
output_axis_tlast_reg <= input_axis_tlast;
|
||||
output_axis_tuser_reg <= input_axis_tuser;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_input_to_temp) begin
|
||||
temp_axis_tdata_reg <= input_axis_tdata;
|
||||
temp_axis_tkeep_reg <= input_axis_tkeep;
|
||||
temp_axis_tlast_reg <= input_axis_tlast;
|
||||
temp_axis_tuser_reg <= input_axis_tuser;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -91,7 +91,7 @@ reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
reg [TICK_COUNT_WIDTH-1:0] tick_count_reg = 0, tick_count_next;
|
||||
reg [BYTE_COUNT_WIDTH-1:0] byte_count_reg = 0, byte_count_next;
|
||||
reg [FRAME_COUNT_WIDTH-1:0] frame_count_reg = 0, frame_count_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg store_output;
|
||||
reg [$clog2(TOTAL_LENGTH)-1:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
@ -100,12 +100,12 @@ reg [TICK_COUNT_WIDTH-1:0] tick_count_output_reg = 0;
|
||||
reg [BYTE_COUNT_WIDTH-1:0] byte_count_output_reg = 0;
|
||||
reg [FRAME_COUNT_WIDTH-1:0] frame_count_output_reg = 0;
|
||||
|
||||
reg busy_reg = 0;
|
||||
reg busy_reg = 1'b0;
|
||||
|
||||
// internal datapath
|
||||
reg [7:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -115,19 +115,19 @@ assign busy = busy_reg;
|
||||
integer offset, i, bit_cnt;
|
||||
|
||||
always @* begin
|
||||
state_next = 2'bz;
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
tick_count_next = tick_count_reg;
|
||||
byte_count_next = byte_count_reg;
|
||||
frame_count_next = frame_count_reg;
|
||||
frame_next = frame_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = 8'd0;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
store_output = 0;
|
||||
store_output = 1'b0;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
|
||||
@ -136,13 +136,13 @@ always @* begin
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
if (trigger) begin
|
||||
store_output = 1;
|
||||
store_output = 1'b1;
|
||||
tick_count_next = 0;
|
||||
byte_count_next = 0;
|
||||
frame_count_next = 0;
|
||||
frame_ptr_next = 0;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
frame_ptr_next = 1;
|
||||
if (TAG_ENABLE) begin
|
||||
output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8];
|
||||
@ -153,7 +153,7 @@ always @* begin
|
||||
end else if (FRAME_COUNT_ENABLE) begin
|
||||
output_axis_tdata_int = frame_count_reg[(FRAME_COUNT_BYTE_WIDTH-1)*8 +: 8];
|
||||
end
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
|
||||
state_next = STATE_OUTPUT_DATA;
|
||||
@ -162,10 +162,10 @@ always @* begin
|
||||
end
|
||||
end
|
||||
STATE_OUTPUT_DATA: begin
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
state_next = STATE_OUTPUT_DATA;
|
||||
frame_ptr_next = frame_ptr_reg + 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
|
||||
offset = 0;
|
||||
if (TAG_ENABLE) begin
|
||||
@ -201,7 +201,7 @@ always @* begin
|
||||
end
|
||||
end
|
||||
if (frame_ptr_reg == offset-1) begin
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
@ -229,11 +229,11 @@ always @* begin
|
||||
// count frames
|
||||
if (monitor_axis_tlast) begin
|
||||
// end of frame
|
||||
frame_next = 0;
|
||||
frame_next = 1'b0;
|
||||
end else if (~frame_reg) begin
|
||||
// first word after end of frame
|
||||
frame_count_next = frame_count_next + 1;
|
||||
frame_next = 1;
|
||||
frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -244,12 +244,9 @@ always @(posedge clk) begin
|
||||
tick_count_reg <= 0;
|
||||
byte_count_reg <= 0;
|
||||
frame_count_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
frame_reg <= 1'b0;
|
||||
frame_ptr_reg <= 0;
|
||||
busy_reg <= 0;
|
||||
tick_count_output_reg <= 0;
|
||||
byte_count_output_reg <= 0;
|
||||
frame_count_output_reg <= 0;
|
||||
busy_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
tick_count_reg <= tick_count_next;
|
||||
@ -260,74 +257,93 @@ always @(posedge clk) begin
|
||||
|
||||
busy_reg <= state_next != STATE_IDLE;
|
||||
|
||||
if (store_output) begin
|
||||
tick_count_output_reg <= tick_count_reg;
|
||||
byte_count_output_reg <= byte_count_reg;
|
||||
frame_count_output_reg <= frame_count_reg;
|
||||
end
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
tick_count_output_reg <= tick_count_reg;
|
||||
byte_count_output_reg <= byte_count_reg;
|
||||
frame_count_output_reg <= frame_count_reg;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [7:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [7:0] output_axis_tdata_reg = 8'd0;
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [7:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [7:0] temp_axis_tdata_reg = 8'd0;
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -59,7 +59,7 @@ module axis_tap #
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -72,17 +72,17 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_next = frame_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
frame_next = ~tap_axis_tlast;
|
||||
@ -92,7 +92,7 @@ always @* begin
|
||||
STATE_IDLE: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// start of frame
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
output_axis_tlast_int = tap_axis_tlast;
|
||||
@ -112,7 +112,7 @@ always @* begin
|
||||
STATE_TRANSFER: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// transfer data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
output_axis_tlast_int = tap_axis_tlast;
|
||||
@ -130,11 +130,11 @@ always @* begin
|
||||
end
|
||||
end
|
||||
STATE_TRUNCATE: begin
|
||||
if (output_axis_tready_int) begin
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tuser_int = 1;
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = 1'b1;
|
||||
if (frame_next) begin
|
||||
state_next = STATE_WAIT;
|
||||
end else begin
|
||||
@ -161,7 +161,7 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_reg <= 0;
|
||||
frame_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -169,65 +169,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +63,7 @@ module axis_tap_64 #
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -76,18 +76,18 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_next = frame_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
frame_next = ~tap_axis_tlast;
|
||||
@ -97,7 +97,7 @@ always @* begin
|
||||
STATE_IDLE: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// start of frame
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tkeep_int = tap_axis_tkeep;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
@ -118,7 +118,7 @@ always @* begin
|
||||
STATE_TRANSFER: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// transfer data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tkeep_int = tap_axis_tkeep;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
@ -137,12 +137,12 @@ always @* begin
|
||||
end
|
||||
end
|
||||
STATE_TRUNCATE: begin
|
||||
if (output_axis_tready_int) begin
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tuser_int = 1;
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {{KEEP_WIDTH-1{1'b0}}, 1'b1};
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = 1'b1;
|
||||
if (frame_next) begin
|
||||
state_next = STATE_WAIT;
|
||||
end else begin
|
||||
@ -169,7 +169,7 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_reg <= 0;
|
||||
frame_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -177,17 +177,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -195,56 +200,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
output_axis_tkeep_reg <= 0;
|
||||
output_axis_tvalid_reg <= 0;
|
||||
output_axis_tlast_reg <= 0;
|
||||
output_axis_tuser_reg <= 0;
|
||||
output_axis_tready_int <= 0;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
output_axis_tready_int_reg <= output_axis_tready_int_early;
|
||||
temp_axis_tvalid_reg <= temp_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
// input is ready
|
||||
if (output_axis_tready | ~output_axis_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tvalid_reg <= output_axis_tvalid_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end else if (output_axis_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tvalid_reg <= temp_axis_tvalid_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tkeep_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
output_axis_tdata_reg <= output_axis_tdata_int;
|
||||
output_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
output_axis_tdata_reg <= temp_axis_tdata_reg;
|
||||
output_axis_tkeep_reg <= temp_axis_tkeep_reg;
|
||||
output_axis_tlast_reg <= temp_axis_tlast_reg;
|
||||
output_axis_tuser_reg <= temp_axis_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user