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:
parent
0a79f24d3c
commit
0d22a35bd8
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
cycle_count_reg <= cycle_count_next;
|
||||
end
|
||||
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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
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;
|
||||
// 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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -103,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 @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tdata_reg <= 0;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= 0;
|
||||
{%- 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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
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;
|
||||
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_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;
|
||||
output_{{p}}_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
endcase
|
||||
temp_axis_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
{%- 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
|
||||
|
||||
// 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;
|
||||
temp_axis_tdata_reg <= 0;
|
||||
temp_axis_tvalid_reg <= 0;
|
||||
temp_axis_tlast_reg <= 0;
|
||||
temp_axis_tuser_reg <= 0;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -80,15 +80,15 @@ module axis_demux_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
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;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_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
|
||||
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
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -106,16 +106,16 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -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 @(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;
|
||||
{%- 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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg;
|
||||
{%- endfor %}
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}});
|
||||
{%- endfor %}
|
||||
endcase
|
||||
output_axis_tlast_reg <= output_axis_tlast_int;
|
||||
output_axis_tuser_reg <= output_axis_tuser_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
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;
|
||||
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
|
||||
{%- for p in ports %}
|
||||
output_{{p}}_axis_tvalid_reg <= 1'b0;
|
||||
{%- endfor %}
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
{%- 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
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -86,16 +86,16 @@ module axis_demux_64_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
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;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_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
|
||||
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
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -95,27 +95,27 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg [2:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
reg [1:0] port_sel_reg = 0, port_sel_next;
|
||||
reg [2:0] frame_ptr_reg = 3'd0, frame_ptr_next;
|
||||
reg [1:0] port_sel_reg = 2'd0, port_sel_next;
|
||||
|
||||
reg busy_reg = 0, busy_next;
|
||||
reg busy_reg = 1'b0, busy_next;
|
||||
|
||||
reg [7:0] input_tdata;
|
||||
reg input_tvalid;
|
||||
reg input_tlast;
|
||||
reg input_tuser;
|
||||
|
||||
reg output_tuser_reg = 0, output_tuser_next;
|
||||
reg output_tuser_reg = 1'b0, output_tuser_next;
|
||||
|
||||
reg input_0_axis_tready_reg = 0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 0, input_3_axis_tready_next;
|
||||
reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [7:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -160,33 +160,33 @@ end
|
||||
integer offset, i;
|
||||
|
||||
always @* begin
|
||||
state_next = 2'bz;
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
port_sel_next = port_sel_reg;
|
||||
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = 8'd0;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
output_tuser_next = output_tuser_reg;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state - wait for data
|
||||
frame_ptr_next = 0;
|
||||
port_sel_next = 0;
|
||||
output_tuser_next = 0;
|
||||
frame_ptr_next = 3'd0;
|
||||
port_sel_next = 2'd0;
|
||||
output_tuser_next = 1'b0;
|
||||
|
||||
if (TAG_ENABLE) begin
|
||||
// next cycle if started will send tag, so do not enable input
|
||||
input_0_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
end else begin
|
||||
// next cycle if started will send data, so enable input
|
||||
input_0_axis_tready_next = output_axis_tready_int_early;
|
||||
@ -196,19 +196,19 @@ always @* begin
|
||||
// input 0 valid; start transferring data
|
||||
if (TAG_ENABLE) begin
|
||||
// tag enabled, so transmit it
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first tag byte
|
||||
frame_ptr_next = 1;
|
||||
frame_ptr_next = 3'd1;
|
||||
output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8];
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_WRITE_TAG;
|
||||
end else begin
|
||||
// tag disabled, so transmit data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output is ready, so short-circuit first data byte
|
||||
output_axis_tdata_int = input_0_axis_tdata;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
end
|
||||
state_next = STATE_TRANSFER;
|
||||
end
|
||||
@ -218,11 +218,11 @@ always @* begin
|
||||
end
|
||||
STATE_WRITE_TAG: begin
|
||||
// write tag data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
// output ready, so send tag byte
|
||||
state_next = STATE_WRITE_TAG;
|
||||
frame_ptr_next = frame_ptr_reg + 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
|
||||
offset = 0;
|
||||
if (TAG_ENABLE) begin
|
||||
@ -252,7 +252,7 @@ always @* begin
|
||||
2'd3: input_3_axis_tready_next = output_axis_tready_int_early;
|
||||
endcase
|
||||
|
||||
if (input_tvalid & output_axis_tready_int) begin
|
||||
if (input_tvalid & output_axis_tready_int_reg) begin
|
||||
// output ready, transfer byte
|
||||
state_next = STATE_TRANSFER;
|
||||
output_axis_tdata_int = input_tdata;
|
||||
@ -264,14 +264,14 @@ always @* begin
|
||||
// save tuser - assert tuser out if ANY tuser asserts received
|
||||
output_tuser_next = output_tuser_next | input_tuser;
|
||||
// disable input
|
||||
input_0_axis_tready_next = 0;
|
||||
input_1_axis_tready_next = 0;
|
||||
input_2_axis_tready_next = 0;
|
||||
input_3_axis_tready_next = 0;
|
||||
input_0_axis_tready_next = 1'b0;
|
||||
input_1_axis_tready_next = 1'b0;
|
||||
input_2_axis_tready_next = 1'b0;
|
||||
input_3_axis_tready_next = 1'b0;
|
||||
|
||||
if (port_sel_reg == 3) begin
|
||||
if (port_sel_reg == 2'd3) begin
|
||||
// last port - send tlast and tuser and revert to idle
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = output_tuser_next;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
@ -294,14 +294,14 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_ptr_reg <= 0;
|
||||
port_sel_reg <= 0;
|
||||
input_0_axis_tready_reg <= 0;
|
||||
input_1_axis_tready_reg <= 0;
|
||||
input_2_axis_tready_reg <= 0;
|
||||
input_3_axis_tready_reg <= 0;
|
||||
output_tuser_reg <= 0;
|
||||
busy_reg <= 0;
|
||||
frame_ptr_reg <= 3'd0;
|
||||
port_sel_reg <= 2'd0;
|
||||
input_0_axis_tready_reg <= 1'b0;
|
||||
input_1_axis_tready_reg <= 1'b0;
|
||||
input_2_axis_tready_reg <= 1'b0;
|
||||
input_3_axis_tready_reg <= 1'b0;
|
||||
output_tuser_reg <= 1'b0;
|
||||
busy_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
@ -321,65 +321,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [7:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [7:0] output_axis_tdata_reg = 8'd0;
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [7:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [7:0] temp_axis_tdata_reg = 8'd0;
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,33 +98,33 @@ reg [2:0] state_reg = STATE_IDLE, state_next;
|
||||
// datapath control signals
|
||||
reg store_last_word;
|
||||
|
||||
reg [15:0] frame_ptr_reg = 0, frame_ptr_next;
|
||||
reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_next;
|
||||
|
||||
// frame length counters
|
||||
reg [15:0] short_counter_reg = 0, short_counter_next = 0;
|
||||
reg [15:0] long_counter_reg = 0, long_counter_next = 0;
|
||||
reg [15:0] short_counter_reg = 16'd0, short_counter_next = 16'd0;
|
||||
reg [15:0] long_counter_reg = 16'd0, long_counter_next = 16'd0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] last_word_data_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] last_word_keep_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] last_word_data_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] last_word_keep_reg = {KEEP_WIDTH{1'b0}};
|
||||
|
||||
reg last_cycle_tuser_reg = 0, last_cycle_tuser_next;
|
||||
reg last_cycle_tuser_reg = 1'b0, last_cycle_tuser_next;
|
||||
|
||||
reg status_valid_reg = 0, status_valid_next;
|
||||
reg status_frame_pad_reg = 0, status_frame_pad_next;
|
||||
reg status_frame_truncate_reg = 0, status_frame_truncate_next;
|
||||
reg [15:0] status_frame_length_reg = 0, status_frame_length_next;
|
||||
reg [15:0] status_frame_original_length_reg = 0, status_frame_original_length_next;
|
||||
reg status_valid_reg = 1'b0, status_valid_next;
|
||||
reg status_frame_pad_reg = 1'b0, status_frame_pad_next;
|
||||
reg status_frame_truncate_reg = 1'b0, status_frame_truncate_next;
|
||||
reg [15:0] status_frame_length_reg = 16'd0, status_frame_length_next;
|
||||
reg [15:0] status_frame_original_length_reg = 16'd0, status_frame_original_length_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
assign status_valid = status_valid_reg;
|
||||
@ -138,20 +138,20 @@ integer i, word_cnt;
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
store_last_word = 0;
|
||||
store_last_word = 1'b0;
|
||||
|
||||
frame_ptr_next = frame_ptr_reg;
|
||||
|
||||
short_counter_next = short_counter_reg;
|
||||
long_counter_next = long_counter_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
last_cycle_tuser_next = last_cycle_tuser_reg;
|
||||
|
||||
@ -188,31 +188,31 @@ always @* begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg <= word_cnt) begin
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg);
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = word_cnt > long_counter_reg;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
output_axis_tvalid_int = 0;
|
||||
store_last_word = 1;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
store_last_word = 1'b1;
|
||||
state_next = STATE_TRUNCATE;
|
||||
end
|
||||
end else begin
|
||||
@ -221,32 +221,32 @@ always @* begin
|
||||
if (short_counter_reg > word_cnt) begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
last_cycle_tuser_next = input_axis_tuser;
|
||||
state_next = STATE_PAD;
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-(length_min - frame_ptr_reg));
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = frame_ptr_reg+word_cnt;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -282,31 +282,31 @@ always @* begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg <= word_cnt) begin
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg);
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = word_cnt > long_counter_reg;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
output_axis_tvalid_int = 0;
|
||||
store_last_word = 1;
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
store_last_word = 1'b1;
|
||||
state_next = STATE_TRUNCATE;
|
||||
end
|
||||
end else begin
|
||||
@ -315,32 +315,32 @@ always @* begin
|
||||
if (short_counter_reg > word_cnt) begin
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
last_cycle_tuser_next = input_axis_tuser;
|
||||
state_next = STATE_PAD;
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg);
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = frame_ptr_reg+word_cnt;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -355,39 +355,39 @@ always @* begin
|
||||
end
|
||||
STATE_PAD: begin
|
||||
// pad to minimum length
|
||||
input_axis_tready_next = 0;
|
||||
input_axis_tready_next = 1'b0;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b1}};
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
frame_ptr_next = frame_ptr_reg + KEEP_WIDTH;
|
||||
|
||||
if (short_counter_reg > KEEP_WIDTH) begin
|
||||
short_counter_next = short_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
short_counter_next = 0;
|
||||
short_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (long_counter_reg > KEEP_WIDTH) begin
|
||||
long_counter_next = long_counter_reg - KEEP_WIDTH;
|
||||
end else begin
|
||||
long_counter_next = 0;
|
||||
long_counter_next = 16'd0;
|
||||
end
|
||||
|
||||
if (short_counter_reg <= KEEP_WIDTH) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 1;
|
||||
status_frame_truncate_next = 0;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b1;
|
||||
status_frame_truncate_next = 1'b0;
|
||||
status_frame_length_next = length_min;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg);
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = last_cycle_tuser_reg;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -417,13 +417,13 @@ always @* begin
|
||||
frame_ptr_next = frame_ptr_reg+KEEP_WIDTH;
|
||||
|
||||
if (input_axis_tlast) begin
|
||||
status_valid_next = 1;
|
||||
status_frame_pad_next = 0;
|
||||
status_frame_truncate_next = 1;
|
||||
status_valid_next = 1'b1;
|
||||
status_frame_pad_next = 1'b0;
|
||||
status_frame_truncate_next = 1'b1;
|
||||
status_frame_length_next = length_max;
|
||||
status_frame_original_length_next = frame_ptr_reg+word_cnt;
|
||||
input_axis_tready_next = output_axis_tready_int_early & status_ready;
|
||||
frame_ptr_next = 0;
|
||||
frame_ptr_next = 16'd0;
|
||||
short_counter_next = length_min;
|
||||
long_counter_next = length_max;
|
||||
state_next = STATE_IDLE;
|
||||
@ -440,18 +440,11 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_ptr_reg <= 0;
|
||||
short_counter_reg <= 0;
|
||||
long_counter_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
last_word_data_reg <= 0;
|
||||
last_word_keep_reg <= 0;
|
||||
last_cycle_tuser_reg <= 0;
|
||||
status_valid_reg <= 0;
|
||||
status_frame_pad_reg <= 0;
|
||||
status_frame_truncate_reg <= 0;
|
||||
status_frame_length_reg <= 0;
|
||||
status_frame_original_length_reg <= 0;
|
||||
frame_ptr_reg <= 16'd0;
|
||||
short_counter_reg <= 16'd0;
|
||||
long_counter_reg <= 16'd0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
status_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
|
||||
@ -462,9 +455,11 @@ always @(posedge clk) begin
|
||||
|
||||
input_axis_tready_reg <= input_axis_tready_next;
|
||||
|
||||
status_valid_reg <= status_valid_next;
|
||||
end
|
||||
|
||||
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;
|
||||
@ -474,21 +469,25 @@ always @(posedge clk) begin
|
||||
last_word_data_reg <= output_axis_tdata_int;
|
||||
last_word_keep_reg <= output_axis_tkeep_int;
|
||||
end
|
||||
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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
output_axis_tvalid_next = output_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
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;
|
||||
// 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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
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
|
||||
|
||||
|
112
rtl/axis_mux.py
112
rtl/axis_mux.py
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
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
|
||||
|
||||
|
130
rtl/axis_mux_4.v
130
rtl/axis_mux_4.v
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ def generate(ports=4, name=None, output=None):
|
||||
|
||||
t = Template(u"""/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -106,17 +106,17 @@ module {{name}} #
|
||||
input wire [{{w-1}}:0] select
|
||||
);
|
||||
|
||||
reg [{{w-1}}:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
{% for p in ports %}
|
||||
reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next;
|
||||
reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next;
|
||||
{%- endfor %}
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -86,19 +86,19 @@ module axis_mux_64_4 #
|
||||
input wire [1:0] select
|
||||
);
|
||||
|
||||
reg [1:0] select_reg = 0, select_next;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg [1:0] select_reg = 2'd0, select_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_0_axis_tready_reg = 0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 0, input_3_axis_tready_next;
|
||||
reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next;
|
||||
reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next;
|
||||
reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next;
|
||||
reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -66,21 +66,22 @@ module axis_rate_limit #
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg [23:0] acc_reg = 0, acc_next;
|
||||
reg [23:0] acc_reg = 24'd0, acc_next;
|
||||
reg pause;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
always @* begin
|
||||
acc_next = acc_reg;
|
||||
pause = 0;
|
||||
pause = 1'b0;
|
||||
frame_next = frame_reg;
|
||||
|
||||
if (acc_reg >= rate_num) begin
|
||||
@ -97,7 +98,7 @@ always @* begin
|
||||
if (rate_by_frame) begin
|
||||
pause = ~frame_next;
|
||||
end else begin
|
||||
pause = 1;
|
||||
pause = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
@ -111,9 +112,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
acc_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
acc_reg <= 24'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
acc_reg <= acc_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -122,65 +123,83 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -70,21 +70,22 @@ module axis_rate_limit_64 #
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
|
||||
reg [23:0] acc_reg = 0, acc_next;
|
||||
reg [23:0] acc_reg = 24'd0, acc_next;
|
||||
reg pause;
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
reg input_axis_tready_reg = 1'b0, input_axis_tready_next;
|
||||
|
||||
reg input_axis_tready_reg = 0, input_axis_tready_next;
|
||||
assign input_axis_tready = input_axis_tready_reg;
|
||||
|
||||
always @* begin
|
||||
acc_next = acc_reg;
|
||||
pause = 0;
|
||||
pause = 1'b0;
|
||||
frame_next = frame_reg;
|
||||
|
||||
if (acc_reg >= rate_num) begin
|
||||
@ -101,7 +102,7 @@ always @* begin
|
||||
if (rate_by_frame) begin
|
||||
pause = ~frame_next;
|
||||
end else begin
|
||||
pause = 1;
|
||||
pause = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
@ -116,9 +117,9 @@ end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
acc_reg <= 0;
|
||||
frame_reg <= 0;
|
||||
input_axis_tready_reg <= 0;
|
||||
acc_reg <= 24'd0;
|
||||
frame_reg <= 1'b0;
|
||||
input_axis_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
acc_reg <= acc_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -127,17 +128,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -145,56 +151,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014 Alex Forencich
|
||||
Copyright (c) 2014-2015 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -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;
|
||||
|
||||
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
|
||||
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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
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
|
||||
|
||||
|
120
rtl/axis_tap.v
120
rtl/axis_tap.v
@ -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 @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +63,7 @@ module axis_tap_64 #
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_int;
|
||||
reg output_axis_tvalid_int;
|
||||
reg output_axis_tready_int = 0;
|
||||
reg output_axis_tready_int_reg = 1'b0;
|
||||
reg output_axis_tlast_int;
|
||||
reg output_axis_tuser_int;
|
||||
wire output_axis_tready_int_early;
|
||||
@ -76,18 +76,18 @@ localparam [1:0]
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg frame_reg = 0, frame_next;
|
||||
reg frame_reg = 1'b0, frame_next;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
frame_next = frame_reg;
|
||||
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 0;
|
||||
output_axis_tvalid_int = 0;
|
||||
output_axis_tlast_int = 0;
|
||||
output_axis_tuser_int = 0;
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {KEEP_WIDTH{1'b0}};
|
||||
output_axis_tvalid_int = 1'b0;
|
||||
output_axis_tlast_int = 1'b0;
|
||||
output_axis_tuser_int = 1'b0;
|
||||
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
frame_next = ~tap_axis_tlast;
|
||||
@ -97,7 +97,7 @@ always @* begin
|
||||
STATE_IDLE: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// start of frame
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tkeep_int = tap_axis_tkeep;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
@ -118,7 +118,7 @@ always @* begin
|
||||
STATE_TRANSFER: begin
|
||||
if (tap_axis_tready & tap_axis_tvalid) begin
|
||||
// transfer data
|
||||
if (output_axis_tready_int) begin
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = tap_axis_tdata;
|
||||
output_axis_tkeep_int = tap_axis_tkeep;
|
||||
output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready;
|
||||
@ -137,12 +137,12 @@ always @* begin
|
||||
end
|
||||
end
|
||||
STATE_TRUNCATE: begin
|
||||
if (output_axis_tready_int) begin
|
||||
output_axis_tdata_int = 0;
|
||||
output_axis_tkeep_int = 1;
|
||||
output_axis_tvalid_int = 1;
|
||||
output_axis_tlast_int = 1;
|
||||
output_axis_tuser_int = 1;
|
||||
if (output_axis_tready_int_reg) begin
|
||||
output_axis_tdata_int = {DATA_WIDTH{1'b0}};
|
||||
output_axis_tkeep_int = {{KEEP_WIDTH-1{1'b0}}, 1'b1};
|
||||
output_axis_tvalid_int = 1'b1;
|
||||
output_axis_tlast_int = 1'b1;
|
||||
output_axis_tuser_int = 1'b1;
|
||||
if (frame_next) begin
|
||||
state_next = STATE_WAIT;
|
||||
end else begin
|
||||
@ -169,7 +169,7 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
frame_reg <= 0;
|
||||
frame_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
frame_reg <= frame_next;
|
||||
@ -177,17 +177,22 @@ always @(posedge clk) begin
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0;
|
||||
reg output_axis_tvalid_reg = 0;
|
||||
reg output_axis_tlast_reg = 0;
|
||||
reg output_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
reg output_axis_tlast_reg = 1'b0;
|
||||
reg output_axis_tuser_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0;
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0;
|
||||
reg temp_axis_tvalid_reg = 0;
|
||||
reg temp_axis_tlast_reg = 0;
|
||||
reg temp_axis_tuser_reg = 0;
|
||||
reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next;
|
||||
reg temp_axis_tlast_reg = 1'b0;
|
||||
reg temp_axis_tuser_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign output_axis_tdata = output_axis_tdata_reg;
|
||||
assign output_axis_tkeep = output_axis_tkeep_reg;
|
||||
@ -195,56 +200,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
assign output_axis_tlast = output_axis_tlast_reg;
|
||||
assign output_axis_tuser = output_axis_tuser_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int);
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int));
|
||||
|
||||
always @(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;
|
||||
end else begin
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
output_axis_tready_int <= output_axis_tready_int_early;
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
temp_axis_tvalid_next = temp_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready_int) begin
|
||||
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_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;
|
||||
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_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;
|
||||
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_tvalid_reg <= 1'b0;
|
||||
output_axis_tready_int_reg <= 1'b0;
|
||||
temp_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
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
|
||||
|
||||
// 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_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
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_axis_tdata_reg <= output_axis_tdata_int;
|
||||
temp_axis_tkeep_reg <= output_axis_tkeep_int;
|
||||
temp_axis_tlast_reg <= output_axis_tlast_int;
|
||||
temp_axis_tuser_reg <= output_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user