1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Update output registers, remove extraneous resets, fix constant widths

This commit is contained in:
Alex Forencich 2015-11-08 23:05:38 -08:00
parent 0a79f24d3c
commit 0d22a35bd8
17 changed files with 1594 additions and 1317 deletions

View File

@ -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

View File

@ -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;
@ -136,7 +136,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 +145,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 +159,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 +170,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

View File

@ -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;
@ -123,7 +123,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 +132,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 +146,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 +157,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 +195,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

View File

@ -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;
@ -140,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
@ -149,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
@ -164,9 +164,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 +175,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 +200,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

View File

@ -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;
@ -130,7 +130,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 +139,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 +154,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 +165,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 +209,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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
@ -154,7 +154,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 +164,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 +184,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 +199,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

View File

@ -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;
@ -155,10 +155,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 +167,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 +188,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 +205,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

View File

@ -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;
@ -160,7 +160,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 +170,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 +191,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 +206,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 +229,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

View File

@ -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;
@ -167,10 +167,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 +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
@ -201,12 +201,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 +218,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 +241,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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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