diff --git a/rtl/axis_adapter.v b/rtl/axis_adapter.v index 1eed1403b..c5f4358c5 100644 --- a/rtl/axis_adapter.v +++ b/rtl/axis_adapter.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 @@ -101,25 +101,26 @@ localparam [2:0] reg [2:0] state_reg = STATE_IDLE, state_next; -reg [7:0] cycle_count_reg = 0, cycle_count_next; +reg [7:0] cycle_count_reg = 8'd0, cycle_count_next; reg last_cycle; -reg [DATA_WIDTH-1:0] temp_tdata_reg = 0, temp_tdata_next; -reg [KEEP_WIDTH-1:0] temp_tkeep_reg = 0, temp_tkeep_next; -reg temp_tlast_reg = 0, temp_tlast_next; -reg temp_tuser_reg = 0, temp_tuser_next; +reg [DATA_WIDTH-1:0] temp_tdata_reg = {DATA_WIDTH{1'b0}}, temp_tdata_next; +reg [KEEP_WIDTH-1:0] temp_tkeep_reg = {KEEP_WIDTH{1'b0}}, temp_tkeep_next; +reg temp_tlast_reg = 1'b0, temp_tlast_next; +reg temp_tuser_reg = 1'b0, temp_tuser_next; // internal datapath reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_int; reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; + assign input_axis_tready = input_axis_tready_reg; always @* begin @@ -132,13 +133,13 @@ always @* begin temp_tlast_next = temp_tlast_reg; temp_tuser_next = temp_tuser_reg; - output_axis_tdata_int = 0; - output_axis_tkeep_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = {OUTPUT_DATA_WIDTH{1'b0}}; + output_axis_tkeep_int = {OUTPUT_KEEP_WIDTH{1'b0}}; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; case (state_reg) STATE_IDLE: begin @@ -161,7 +162,7 @@ always @* begin // output bus is wider // accept new data - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; if (input_axis_tready & input_axis_tvalid) begin // word transfer in - store it in data register @@ -173,15 +174,15 @@ always @* begin temp_tuser_next = input_axis_tuser; // first input cycle complete - cycle_count_next = 1; + cycle_count_next = 8'd1; if (input_axis_tlast) begin // got last signal on first cycle, so output it - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; state_next = STATE_TRANSFER_OUT; end else begin // otherwise, transfer in the rest of the words - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; state_next = STATE_TRANSFER_IN; end end else begin @@ -191,24 +192,24 @@ always @* begin // output bus is narrower // accept new data - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; if (input_axis_tready & input_axis_tvalid) begin // word transfer in - store it in data register - cycle_count_next = 0; + cycle_count_next = 8'd0; // is this the last cycle? if (CYCLE_COUNT == 1) begin // last cycle by counter value - last_cycle = 1; + last_cycle = 1'b1; end else if (input_axis_tkeep[CYCLE_KEEP_WIDTH-1:0] != {CYCLE_KEEP_WIDTH{1'b1}}) begin // last cycle by tkeep fall in current cycle - last_cycle = 1; + last_cycle = 1'b1; end else if (input_axis_tkeep[(CYCLE_KEEP_WIDTH*2)-1:CYCLE_KEEP_WIDTH] == {CYCLE_KEEP_WIDTH{1'b0}}) begin // last cycle by tkeep fall at end of current cycle - last_cycle = 1; + last_cycle = 1'b1; end else begin - last_cycle = 0; + last_cycle = 1'b0; end // pass complete input word, zero-extended to temp register @@ -220,18 +221,18 @@ always @* begin // short-circuit and get first word out the door output_axis_tdata_int = input_axis_tdata[CYCLE_DATA_WIDTH-1:0]; output_axis_tkeep_int = input_axis_tkeep[CYCLE_KEEP_WIDTH-1:0]; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; output_axis_tlast_int = input_axis_tlast & last_cycle; output_axis_tuser_int = input_axis_tuser & last_cycle; - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // if output register is ready for first word, then move on to the next one - cycle_count_next = 1; + cycle_count_next = 8'd1; end - if (!last_cycle || !output_axis_tready_int) begin + if (!last_cycle || !output_axis_tready_int_reg) begin // continue outputting words - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; state_next = STATE_TRANSFER_OUT; end else begin state_next = STATE_IDLE; @@ -246,7 +247,7 @@ always @* begin // only used when output is wider // accept new data - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; if (input_axis_tready & input_axis_tvalid) begin // word transfer in - store in data register @@ -265,7 +266,7 @@ always @* begin state_next = STATE_TRANSFER_OUT; end else begin // more words to read - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; state_next = STATE_TRANSFER_IN; end end else begin @@ -279,16 +280,16 @@ always @* begin // output bus is wider // do not accept new data - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; // single-cycle output of entire stored word (output wider) output_axis_tdata_int = temp_tdata_reg; output_axis_tkeep_int = temp_tkeep_reg; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; output_axis_tlast_int = temp_tlast_reg; output_axis_tuser_int = temp_tuser_reg; - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // word transfer out if (input_axis_tready & input_axis_tvalid) begin @@ -301,19 +302,19 @@ always @* begin temp_tuser_next = input_axis_tuser; // first input cycle complete - cycle_count_next = 1; + cycle_count_next = 8'd1; if (input_axis_tlast) begin // got last signal on first cycle, so output it - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; state_next = STATE_TRANSFER_OUT; end else begin // otherwise, transfer in the rest of the words - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; state_next = STATE_TRANSFER_IN; end end else begin - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; state_next = STATE_IDLE; end end else begin @@ -323,30 +324,30 @@ always @* begin // output bus is narrower // do not accept new data - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; // is this the last cycle? if (cycle_count_reg == CYCLE_COUNT-1) begin // last cycle by counter value - last_cycle = 1; + last_cycle = 1'b1; end else if (temp_tkeep_reg[cycle_count_reg*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH] != {CYCLE_KEEP_WIDTH{1'b1}}) begin // last cycle by tkeep fall in current cycle - last_cycle = 1; + last_cycle = 1'b1; end else if (temp_tkeep_reg[(cycle_count_reg+1)*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH] == {CYCLE_KEEP_WIDTH{1'b0}}) begin // last cycle by tkeep fall at end of current cycle - last_cycle = 1; + last_cycle = 1'b1; end else begin - last_cycle = 0; + last_cycle = 1'b0; end // output current part of stored word (output narrower) output_axis_tdata_int = temp_tdata_reg[cycle_count_reg*CYCLE_DATA_WIDTH +: CYCLE_DATA_WIDTH]; output_axis_tkeep_int = temp_tkeep_reg[cycle_count_reg*CYCLE_KEEP_WIDTH +: CYCLE_KEEP_WIDTH]; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; output_axis_tlast_int = temp_tlast_reg & last_cycle; output_axis_tuser_int = temp_tuser_reg & last_cycle; - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // word transfer out cycle_count_next = cycle_count_reg + 1; @@ -354,7 +355,7 @@ always @* begin if (last_cycle) begin // terminated by counter or tlast signal - input_axis_tready_next = 1; + input_axis_tready_next = 1'b1; state_next = STATE_IDLE; end else begin // more words to write @@ -371,38 +372,39 @@ end always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; - cycle_count_reg <= 0; - temp_tdata_reg <= 0; - temp_tkeep_reg <= 0; - temp_tlast_reg <= 0; - temp_tuser_reg <= 0; - input_axis_tready_reg <= 0; + cycle_count_reg <= 8'd0; + input_axis_tready_reg <= 1'b0; end else begin state_reg <= state_next; input_axis_tready_reg <= input_axis_tready_next; - temp_tdata_reg <= temp_tdata_next; - temp_tkeep_reg <= temp_tkeep_next; - temp_tlast_reg <= temp_tlast_next; - temp_tuser_reg <= temp_tuser_next; - cycle_count_reg <= cycle_count_next; end + + temp_tdata_reg <= temp_tdata_next; + temp_tkeep_reg <= temp_tkeep_next; + temp_tlast_reg <= temp_tlast_next; + temp_tuser_reg <= temp_tuser_next; end // output datapath logic -reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [OUTPUT_DATA_WIDTH-1:0] output_axis_tdata_reg = {OUTPUT_DATA_WIDTH{1'b0}}; +reg [OUTPUT_KEEP_WIDTH-1:0] output_axis_tkeep_reg = {OUTPUT_KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [OUTPUT_DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [OUTPUT_KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [OUTPUT_DATA_WIDTH-1:0] temp_axis_tdata_reg = {OUTPUT_DATA_WIDTH{1'b0}}; +reg [OUTPUT_KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {OUTPUT_KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -410,56 +412,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready and currently valid, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_demux.py b/rtl/axis_demux.py index 8cd57b75d..28bb7ed2a 100755 --- a/rtl/axis_demux.py +++ b/rtl/axis_demux.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,15 +103,15 @@ module {{name}} # input wire [{{w-1}}:0] select ); -reg [{{w-1}}:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next; +reg frame_reg = 1'b0, frame_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -136,7 +136,7 @@ always @* begin select_next = select_reg; frame_next = frame_reg; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; if (frame_reg) begin if (input_axis_tvalid & input_axis_tready) begin @@ -145,7 +145,7 @@ always @* begin end end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -159,9 +159,9 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + select_reg <= {{w}}'d0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin select_reg <= select_next; frame_reg <= frame_next; @@ -170,77 +170,95 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; {%- for p in ports %} -reg output_{{p}}_axis_tvalid_reg = 0; +reg output_{{p}}_axis_tvalid_reg = 1'b0, output_{{p}}_axis_tvalid_next; {%- endfor %} -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; {% for p in ports %} assign output_{{p}}_axis_tdata = output_axis_tdata_reg; assign output_{{p}}_axis_tvalid = output_{{p}}_axis_tvalid_reg; assign output_{{p}}_axis_tlast = output_axis_tlast_reg; assign output_{{p}}_axis_tuser = output_axis_tuser_reg; {% endfor %} -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg; +{%- endfor %} + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (current_output_tready | ~current_output_tvalid) begin + // output is ready or currently not valid, transfer data to output +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}}); +{%- endfor %} + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (current_output_tready) begin + // input is not ready, but output is ready +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == {{w}}'d{{p}}); +{%- endfor %} + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; {%- for p in ports %} - output_{{p}}_axis_tvalid_reg <= 0; + output_{{p}}_axis_tvalid_reg <= 1'b0; {%- endfor %} - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; +{%- for p in ports %} + output_{{p}}_axis_tvalid_reg <= output_{{p}}_axis_tvalid_next; +{%- endfor %} + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (current_output_tready | ~current_output_tvalid) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - case (select_reg) -{%- for p in ports %} - {{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= output_axis_tvalid_int; -{%- endfor %} - endcase - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (current_output_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - case (select_reg) -{%- for p in ports %} - {{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= temp_axis_tvalid_reg; -{%- endfor %} - endcase - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_demux_4.v b/rtl/axis_demux_4.v index 493f5585f..6b853aebf 100644 --- a/rtl/axis_demux_4.v +++ b/rtl/axis_demux_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,15 +80,15 @@ module axis_demux_4 # input wire [1:0] select ); -reg [1:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [1:0] select_reg = 2'd0, select_next; +reg frame_reg = 1'b0, frame_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -123,7 +123,7 @@ always @* begin select_next = select_reg; frame_next = frame_reg; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; if (frame_reg) begin if (input_axis_tvalid & input_axis_tready) begin @@ -132,7 +132,7 @@ always @* begin end end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -146,9 +146,9 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + select_reg <= 2'd0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin select_reg <= select_next; frame_reg <= frame_next; @@ -157,18 +157,23 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg output_0_axis_tvalid_reg = 0; -reg output_1_axis_tvalid_reg = 0; -reg output_2_axis_tvalid_reg = 0; -reg output_3_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg output_0_axis_tvalid_reg = 1'b0, output_0_axis_tvalid_next; +reg output_1_axis_tvalid_reg = 1'b0, output_1_axis_tvalid_next; +reg output_2_axis_tvalid_reg = 1'b0, output_2_axis_tvalid_next; +reg output_3_axis_tvalid_reg = 1'b0, output_3_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_0_axis_tdata = output_axis_tdata_reg; assign output_0_axis_tvalid = output_0_axis_tvalid_reg; @@ -190,63 +195,78 @@ assign output_3_axis_tvalid = output_3_axis_tvalid_reg; assign output_3_axis_tlast = output_axis_tlast_reg; assign output_3_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_0_axis_tvalid_next = output_0_axis_tvalid_reg; + output_1_axis_tvalid_next = output_1_axis_tvalid_reg; + output_2_axis_tvalid_next = output_2_axis_tvalid_reg; + output_3_axis_tvalid_next = output_3_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (current_output_tready | ~current_output_tvalid) begin + // output is ready or currently not valid, transfer data to output + output_0_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd0); + output_1_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd1); + output_2_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd2); + output_3_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd3); + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (current_output_tready) begin + // input is not ready, but output is ready + output_0_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd0); + output_1_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd1); + output_2_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd2); + output_3_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd3); + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_0_axis_tvalid_reg <= 0; - output_1_axis_tvalid_reg <= 0; - output_2_axis_tvalid_reg <= 0; - output_3_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_0_axis_tvalid_reg <= 1'b0; + output_1_axis_tvalid_reg <= 1'b0; + output_2_axis_tvalid_reg <= 1'b0; + output_3_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_0_axis_tvalid_reg <= output_0_axis_tvalid_next; + output_1_axis_tvalid_reg <= output_1_axis_tvalid_next; + output_2_axis_tvalid_reg <= output_2_axis_tvalid_next; + output_3_axis_tvalid_reg <= output_3_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (current_output_tready | ~current_output_tvalid) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - case (select_reg) - 2'd0: output_0_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd1: output_1_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd2: output_2_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd3: output_3_axis_tvalid_reg <= output_axis_tvalid_int; - endcase - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (current_output_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - case (select_reg) - 2'd0: output_0_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd1: output_1_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd2: output_2_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd3: output_3_axis_tvalid_reg <= temp_axis_tvalid_reg; - endcase - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_demux_64.py b/rtl/axis_demux_64.py index 8b3271388..898bb6e60 100755 --- a/rtl/axis_demux_64.py +++ b/rtl/axis_demux_64.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 @@ -106,16 +106,16 @@ module {{name}} # input wire [{{w-1}}:0] select ); -reg [{{w-1}}:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next; +reg frame_reg = 1'b0, frame_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -140,7 +140,7 @@ always @* begin select_next = select_reg; frame_next = frame_reg; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; if (frame_reg) begin if (input_axis_tvalid & input_axis_tready) begin @@ -149,7 +149,7 @@ always @* begin end end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -164,9 +164,9 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + select_reg <= {{w}}'d0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin select_reg <= select_next; frame_reg <= frame_next; @@ -175,19 +175,24 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; {%- for p in ports %} -reg output_{{p}}_axis_tvalid_reg = 0; +reg output_{{p}}_axis_tvalid_reg = 1'b0, output_{{p}}_axis_tvalid_next; {%- endfor %} -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; {% for p in ports %} assign output_{{p}}_axis_tdata = output_axis_tdata_reg; assign output_{{p}}_axis_tkeep = output_axis_tkeep_reg; @@ -195,66 +200,76 @@ assign output_{{p}}_axis_tvalid = output_{{p}}_axis_tvalid_reg; assign output_{{p}}_axis_tlast = output_axis_tlast_reg; assign output_{{p}}_axis_tuser = output_axis_tuser_reg; {% endfor %} -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = output_{{p}}_axis_tvalid_reg; +{%- endfor %} + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (current_output_tready | ~current_output_tvalid) begin + // output is ready or currently not valid, transfer data to output +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = output_axis_tvalid_int & (select_reg == {{w}}'d{{p}}); +{%- endfor %} + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (current_output_tready) begin + // input is not ready, but output is ready +{%- for p in ports %} + output_{{p}}_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == {{w}}'d{{p}}); +{%- endfor %} + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; {%- for p in ports %} - output_{{p}}_axis_tvalid_reg <= 0; + output_{{p}}_axis_tvalid_reg <= 1'b0; {%- endfor %} - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; +{%- for p in ports %} + output_{{p}}_axis_tvalid_reg <= output_{{p}}_axis_tvalid_next; +{%- endfor %} + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (current_output_tready | ~current_output_tvalid) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - case (select_reg) -{%- for p in ports %} - {{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= output_axis_tvalid_int; -{%- endfor %} - endcase - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (current_output_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - case (select_reg) -{%- for p in ports %} - {{w}}'d{{p}}: output_{{p}}_axis_tvalid_reg <= temp_axis_tvalid_reg; -{%- endfor %} - endcase - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_demux_64_4.v b/rtl/axis_demux_64_4.v index e4fb0a441..489ce179e 100644 --- a/rtl/axis_demux_64_4.v +++ b/rtl/axis_demux_64_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 @@ -86,16 +86,16 @@ module axis_demux_64_4 # input wire [1:0] select ); -reg [1:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [1:0] select_reg = 2'd0, select_next; +reg frame_reg = 1'b0, frame_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -130,7 +130,7 @@ always @* begin select_next = select_reg; frame_next = frame_reg; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; if (frame_reg) begin if (input_axis_tvalid & input_axis_tready) begin @@ -139,7 +139,7 @@ always @* begin end end else if (enable & input_axis_tvalid & ~current_output_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -154,9 +154,9 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + select_reg <= 2'd0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin select_reg <= select_next; frame_reg <= frame_next; @@ -165,20 +165,25 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_0_axis_tvalid_reg = 0; -reg output_1_axis_tvalid_reg = 0; -reg output_2_axis_tvalid_reg = 0; -reg output_3_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_0_axis_tvalid_reg = 1'b0, output_0_axis_tvalid_next; +reg output_1_axis_tvalid_reg = 1'b0, output_1_axis_tvalid_next; +reg output_2_axis_tvalid_reg = 1'b0, output_2_axis_tvalid_next; +reg output_3_axis_tvalid_reg = 1'b0, output_3_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_0_axis_tdata = output_axis_tdata_reg; assign output_0_axis_tkeep = output_axis_tkeep_reg; @@ -204,69 +209,81 @@ assign output_3_axis_tvalid = output_3_axis_tvalid_reg; assign output_3_axis_tlast = output_axis_tlast_reg; assign output_3_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & ~current_output_tvalid) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = current_output_tready | (~temp_axis_tvalid_reg & (~current_output_tvalid | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_0_axis_tvalid_next = output_0_axis_tvalid_reg; + output_1_axis_tvalid_next = output_1_axis_tvalid_reg; + output_2_axis_tvalid_next = output_2_axis_tvalid_reg; + output_3_axis_tvalid_next = output_3_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (current_output_tready | ~current_output_tvalid) begin + // output is ready or currently not valid, transfer data to output + output_0_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd0); + output_1_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd1); + output_2_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd2); + output_3_axis_tvalid_next = output_axis_tvalid_int & (select_reg == 2'd3); + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (current_output_tready) begin + // input is not ready, but output is ready + output_0_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd0); + output_1_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd1); + output_2_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd2); + output_3_axis_tvalid_next = temp_axis_tvalid_reg & (select_reg == 2'd3); + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_0_axis_tvalid_reg <= 0; - output_1_axis_tvalid_reg <= 0; - output_2_axis_tvalid_reg <= 0; - output_3_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_0_axis_tvalid_reg <= 1'b0; + output_1_axis_tvalid_reg <= 1'b0; + output_2_axis_tvalid_reg <= 1'b0; + output_3_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_0_axis_tvalid_reg <= output_0_axis_tvalid_next; + output_1_axis_tvalid_reg <= output_1_axis_tvalid_next; + output_2_axis_tvalid_reg <= output_2_axis_tvalid_next; + output_3_axis_tvalid_reg <= output_3_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (current_output_tready | ~current_output_tvalid) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - case (select_reg) - 2'd0: output_0_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd1: output_1_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd2: output_2_axis_tvalid_reg <= output_axis_tvalid_int; - 2'd3: output_3_axis_tvalid_reg <= output_axis_tvalid_int; - endcase - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (current_output_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - case (select_reg) - 2'd0: output_0_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd1: output_1_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd2: output_2_axis_tvalid_reg <= temp_axis_tvalid_reg; - 2'd3: output_3_axis_tvalid_reg <= temp_axis_tvalid_reg; - endcase - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_frame_join.py b/rtl/axis_frame_join.py index 91c23bb95..63f7bd847 100755 --- a/rtl/axis_frame_join.py +++ b/rtl/axis_frame_join.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 @@ -118,25 +118,25 @@ localparam [1:0] reg [1:0] state_reg = STATE_IDLE, state_next; -reg [2:0] frame_ptr_reg = 0, frame_ptr_next; -reg [{{w-1}}:0] port_sel_reg = 0, port_sel_next; +reg [2:0] frame_ptr_reg = 3'd0, frame_ptr_next; +reg [{{w-1}}:0] port_sel_reg = {{w}}'d0, port_sel_next; -reg busy_reg = 0, busy_next; +reg busy_reg = 1'b0, busy_next; reg [7:0] input_tdata; reg input_tvalid; reg input_tlast; reg input_tuser; -reg output_tuser_reg = 0, output_tuser_next; +reg output_tuser_reg = 1'b0, output_tuser_next; {% for p in ports %} -reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next; +reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next; {%- endfor %} // internal datapath reg [7:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -163,31 +163,31 @@ end integer offset, i; always @* begin - state_next = 2'bz; + state_next = STATE_IDLE; frame_ptr_next = frame_ptr_reg; port_sel_next = port_sel_reg; {% for p in ports %} - input_{{p}}_axis_tready_next = 0; + input_{{p}}_axis_tready_next = 1'b0; {%- endfor %} - output_axis_tdata_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = 8'd0; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; output_tuser_next = output_tuser_reg; case (state_reg) STATE_IDLE: begin // idle state - wait for data - frame_ptr_next = 0; - port_sel_next = 0; - output_tuser_next = 0; + frame_ptr_next = 3'd0; + port_sel_next = {{w}}'d0; + output_tuser_next = 1'b0; if (TAG_ENABLE) begin // next cycle if started will send tag, so do not enable input - input_0_axis_tready_next = 0; + input_0_axis_tready_next = 1'b0; end else begin // next cycle if started will send data, so enable input input_0_axis_tready_next = output_axis_tready_int_early; @@ -197,19 +197,19 @@ always @* begin // input 0 valid; start transferring data if (TAG_ENABLE) begin // tag enabled, so transmit it - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output is ready, so short-circuit first tag byte - frame_ptr_next = 1; + frame_ptr_next = 3'd1; output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8]; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; end state_next = STATE_WRITE_TAG; end else begin // tag disabled, so transmit data - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output is ready, so short-circuit first data byte output_axis_tdata_int = input_0_axis_tdata; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; end state_next = STATE_TRANSFER; end @@ -219,11 +219,11 @@ always @* begin end STATE_WRITE_TAG: begin // write tag data - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output ready, so send tag byte state_next = STATE_WRITE_TAG; frame_ptr_next = frame_ptr_reg + 1; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; offset = 0; if (TAG_ENABLE) begin @@ -252,7 +252,7 @@ always @* begin {%- endfor %} endcase - if (input_tvalid & output_axis_tready_int) begin + if (input_tvalid & output_axis_tready_int_reg) begin // output ready, transfer byte state_next = STATE_TRANSFER; output_axis_tdata_int = input_tdata; @@ -265,12 +265,12 @@ always @* begin output_tuser_next = output_tuser_next | input_tuser; // disable input {%- for p in ports %} - input_{{p}}_axis_tready_next = 0; + input_{{p}}_axis_tready_next = 1'b0; {%- endfor %} - if (port_sel_reg == {{n-1}}) begin + if (port_sel_reg == {{w}}'d{{n-1}}) begin // last port - send tlast and tuser and revert to idle - output_axis_tlast_int = 1; + output_axis_tlast_int = 1'b1; output_axis_tuser_int = output_tuser_next; state_next = STATE_IDLE; end else begin @@ -292,13 +292,13 @@ end always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; - frame_ptr_reg <= 0; - port_sel_reg <= 0; + frame_ptr_reg <= 3'd0; + port_sel_reg <= {{w}}'d0; {%- for p in ports %} - input_{{p}}_axis_tready_reg <= 0; + input_{{p}}_axis_tready_reg <= 1'b0; {%- endfor %} - output_tuser_reg <= 0; - busy_reg <= 0; + output_tuser_reg <= 1'b0; + busy_reg <= 1'b0; end else begin state_reg <= state_next; @@ -316,65 +316,83 @@ always @(posedge clk) begin end // output datapath logic -reg [7:0] output_axis_tdata_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [7:0] output_axis_tdata_reg = 8'd0; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [7:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [7:0] temp_axis_tdata_reg = 8'd0; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_frame_join_4.v b/rtl/axis_frame_join_4.v index d57acf7cb..82298e3bd 100644 --- a/rtl/axis_frame_join_4.v +++ b/rtl/axis_frame_join_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 @@ -95,27 +95,27 @@ localparam [1:0] reg [1:0] state_reg = STATE_IDLE, state_next; -reg [2:0] frame_ptr_reg = 0, frame_ptr_next; -reg [1:0] port_sel_reg = 0, port_sel_next; +reg [2:0] frame_ptr_reg = 3'd0, frame_ptr_next; +reg [1:0] port_sel_reg = 2'd0, port_sel_next; -reg busy_reg = 0, busy_next; +reg busy_reg = 1'b0, busy_next; reg [7:0] input_tdata; reg input_tvalid; reg input_tlast; reg input_tuser; -reg output_tuser_reg = 0, output_tuser_next; +reg output_tuser_reg = 1'b0, output_tuser_next; -reg input_0_axis_tready_reg = 0, input_0_axis_tready_next; -reg input_1_axis_tready_reg = 0, input_1_axis_tready_next; -reg input_2_axis_tready_reg = 0, input_2_axis_tready_next; -reg input_3_axis_tready_reg = 0, input_3_axis_tready_next; +reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next; +reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next; +reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next; +reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next; // internal datapath reg [7:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -160,33 +160,33 @@ end integer offset, i; always @* begin - state_next = 2'bz; + state_next = STATE_IDLE; frame_ptr_next = frame_ptr_reg; port_sel_next = port_sel_reg; - input_0_axis_tready_next = 0; - input_1_axis_tready_next = 0; - input_2_axis_tready_next = 0; - input_3_axis_tready_next = 0; + input_0_axis_tready_next = 1'b0; + input_1_axis_tready_next = 1'b0; + input_2_axis_tready_next = 1'b0; + input_3_axis_tready_next = 1'b0; - output_axis_tdata_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = 8'd0; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; output_tuser_next = output_tuser_reg; case (state_reg) STATE_IDLE: begin // idle state - wait for data - frame_ptr_next = 0; - port_sel_next = 0; - output_tuser_next = 0; + frame_ptr_next = 3'd0; + port_sel_next = 2'd0; + output_tuser_next = 1'b0; if (TAG_ENABLE) begin // next cycle if started will send tag, so do not enable input - input_0_axis_tready_next = 0; + input_0_axis_tready_next = 1'b0; end else begin // next cycle if started will send data, so enable input input_0_axis_tready_next = output_axis_tready_int_early; @@ -196,19 +196,19 @@ always @* begin // input 0 valid; start transferring data if (TAG_ENABLE) begin // tag enabled, so transmit it - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output is ready, so short-circuit first tag byte - frame_ptr_next = 1; + frame_ptr_next = 3'd1; output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8]; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; end state_next = STATE_WRITE_TAG; end else begin // tag disabled, so transmit data - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output is ready, so short-circuit first data byte output_axis_tdata_int = input_0_axis_tdata; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; end state_next = STATE_TRANSFER; end @@ -218,11 +218,11 @@ always @* begin end STATE_WRITE_TAG: begin // write tag data - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin // output ready, so send tag byte state_next = STATE_WRITE_TAG; frame_ptr_next = frame_ptr_reg + 1; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; offset = 0; if (TAG_ENABLE) begin @@ -252,7 +252,7 @@ always @* begin 2'd3: input_3_axis_tready_next = output_axis_tready_int_early; endcase - if (input_tvalid & output_axis_tready_int) begin + if (input_tvalid & output_axis_tready_int_reg) begin // output ready, transfer byte state_next = STATE_TRANSFER; output_axis_tdata_int = input_tdata; @@ -264,14 +264,14 @@ always @* begin // save tuser - assert tuser out if ANY tuser asserts received output_tuser_next = output_tuser_next | input_tuser; // disable input - input_0_axis_tready_next = 0; - input_1_axis_tready_next = 0; - input_2_axis_tready_next = 0; - input_3_axis_tready_next = 0; + input_0_axis_tready_next = 1'b0; + input_1_axis_tready_next = 1'b0; + input_2_axis_tready_next = 1'b0; + input_3_axis_tready_next = 1'b0; - if (port_sel_reg == 3) begin + if (port_sel_reg == 2'd3) begin // last port - send tlast and tuser and revert to idle - output_axis_tlast_int = 1; + output_axis_tlast_int = 1'b1; output_axis_tuser_int = output_tuser_next; state_next = STATE_IDLE; end else begin @@ -294,14 +294,14 @@ end always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; - frame_ptr_reg <= 0; - port_sel_reg <= 0; - input_0_axis_tready_reg <= 0; - input_1_axis_tready_reg <= 0; - input_2_axis_tready_reg <= 0; - input_3_axis_tready_reg <= 0; - output_tuser_reg <= 0; - busy_reg <= 0; + frame_ptr_reg <= 3'd0; + port_sel_reg <= 2'd0; + input_0_axis_tready_reg <= 1'b0; + input_1_axis_tready_reg <= 1'b0; + input_2_axis_tready_reg <= 1'b0; + input_3_axis_tready_reg <= 1'b0; + output_tuser_reg <= 1'b0; + busy_reg <= 1'b0; end else begin state_reg <= state_next; @@ -321,65 +321,83 @@ always @(posedge clk) begin end // output datapath logic -reg [7:0] output_axis_tdata_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [7:0] output_axis_tdata_reg = 8'd0; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [7:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [7:0] temp_axis_tdata_reg = 8'd0; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_frame_length_adjust.v b/rtl/axis_frame_length_adjust.v index 6c1c2ae68..5b1073a6c 100644 --- a/rtl/axis_frame_length_adjust.v +++ b/rtl/axis_frame_length_adjust.v @@ -98,33 +98,33 @@ reg [2:0] state_reg = STATE_IDLE, state_next; // datapath control signals reg store_last_word; -reg [15:0] frame_ptr_reg = 0, frame_ptr_next; +reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_next; // frame length counters -reg [15:0] short_counter_reg = 0, short_counter_next = 0; -reg [15:0] long_counter_reg = 0, long_counter_next = 0; +reg [15:0] short_counter_reg = 16'd0, short_counter_next = 16'd0; +reg [15:0] long_counter_reg = 16'd0, long_counter_next = 16'd0; -reg [DATA_WIDTH-1:0] last_word_data_reg = 0; -reg [KEEP_WIDTH-1:0] last_word_keep_reg = 0; +reg [DATA_WIDTH-1:0] last_word_data_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] last_word_keep_reg = {KEEP_WIDTH{1'b0}}; -reg last_cycle_tuser_reg = 0, last_cycle_tuser_next; +reg last_cycle_tuser_reg = 1'b0, last_cycle_tuser_next; -reg status_valid_reg = 0, status_valid_next; -reg status_frame_pad_reg = 0, status_frame_pad_next; -reg status_frame_truncate_reg = 0, status_frame_truncate_next; -reg [15:0] status_frame_length_reg = 0, status_frame_length_next; -reg [15:0] status_frame_original_length_reg = 0, status_frame_original_length_next; +reg status_valid_reg = 1'b0, status_valid_next; +reg status_frame_pad_reg = 1'b0, status_frame_pad_next; +reg status_frame_truncate_reg = 1'b0, status_frame_truncate_next; +reg [15:0] status_frame_length_reg = 16'd0, status_frame_length_next; +reg [15:0] status_frame_original_length_reg = 16'd0, status_frame_original_length_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; -reg input_axis_tready_reg = 0, input_axis_tready_next; +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; assign input_axis_tready = input_axis_tready_reg; assign status_valid = status_valid_reg; @@ -138,20 +138,20 @@ integer i, word_cnt; always @* begin state_next = STATE_IDLE; - store_last_word = 0; + store_last_word = 1'b0; frame_ptr_next = frame_ptr_reg; short_counter_next = short_counter_reg; long_counter_next = long_counter_reg; - output_axis_tdata_int = 0; - output_axis_tkeep_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = {DATA_WIDTH{1'b0}}; + output_axis_tkeep_int = {KEEP_WIDTH{1'b0}}; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; last_cycle_tuser_next = last_cycle_tuser_reg; @@ -188,31 +188,31 @@ always @* begin if (short_counter_reg > KEEP_WIDTH) begin short_counter_next = short_counter_reg - KEEP_WIDTH; end else begin - short_counter_next = 0; + short_counter_next = 16'd0; end if (long_counter_reg > KEEP_WIDTH) begin long_counter_next = long_counter_reg - KEEP_WIDTH; end else begin - long_counter_next = 0; + long_counter_next = 16'd0; end if (long_counter_reg <= word_cnt) begin output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg); if (input_axis_tlast) begin - status_valid_next = 1; - status_frame_pad_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b0; status_frame_truncate_next = word_cnt > long_counter_reg; status_frame_length_next = length_max; status_frame_original_length_next = frame_ptr_reg+word_cnt; input_axis_tready_next = output_axis_tready_int_early & status_ready; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; end else begin - output_axis_tvalid_int = 0; - store_last_word = 1; + output_axis_tvalid_int = 1'b0; + store_last_word = 1'b1; state_next = STATE_TRUNCATE; end end else begin @@ -221,32 +221,32 @@ always @* begin if (short_counter_reg > word_cnt) begin if (short_counter_reg > KEEP_WIDTH) begin frame_ptr_next = frame_ptr_reg + KEEP_WIDTH; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; output_axis_tkeep_int = {KEEP_WIDTH{1'b1}}; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; last_cycle_tuser_next = input_axis_tuser; state_next = STATE_PAD; end else begin - status_valid_next = 1; - status_frame_pad_next = 1; - status_frame_truncate_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b1; + status_frame_truncate_next = 1'b0; status_frame_length_next = length_min; input_axis_tready_next = output_axis_tready_int_early & status_ready; output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-(length_min - frame_ptr_reg)); - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; end end else begin - status_valid_next = 1; - status_frame_pad_next = 0; - status_frame_truncate_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b0; + status_frame_truncate_next = 1'b0; status_frame_length_next = frame_ptr_reg+word_cnt; status_frame_original_length_next = frame_ptr_reg+word_cnt; input_axis_tready_next = output_axis_tready_int_early & status_ready; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; @@ -282,31 +282,31 @@ always @* begin if (short_counter_reg > KEEP_WIDTH) begin short_counter_next = short_counter_reg - KEEP_WIDTH; end else begin - short_counter_next = 0; + short_counter_next = 16'd0; end if (long_counter_reg > KEEP_WIDTH) begin long_counter_next = long_counter_reg - KEEP_WIDTH; end else begin - long_counter_next = 0; + long_counter_next = 16'd0; end if (long_counter_reg <= word_cnt) begin output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-long_counter_reg); if (input_axis_tlast) begin - status_valid_next = 1; - status_frame_pad_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b0; status_frame_truncate_next = word_cnt > long_counter_reg; status_frame_length_next = length_max; status_frame_original_length_next = frame_ptr_reg+word_cnt; input_axis_tready_next = output_axis_tready_int_early & status_ready; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; end else begin - output_axis_tvalid_int = 0; - store_last_word = 1; + output_axis_tvalid_int = 1'b0; + store_last_word = 1'b1; state_next = STATE_TRUNCATE; end end else begin @@ -315,32 +315,32 @@ always @* begin if (short_counter_reg > word_cnt) begin if (short_counter_reg > KEEP_WIDTH) begin frame_ptr_next = frame_ptr_reg + KEEP_WIDTH; - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; output_axis_tkeep_int = {KEEP_WIDTH{1'b1}}; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; last_cycle_tuser_next = input_axis_tuser; state_next = STATE_PAD; end else begin - status_valid_next = 1; - status_frame_pad_next = 1; - status_frame_truncate_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b1; + status_frame_truncate_next = 1'b0; status_frame_length_next = length_min; input_axis_tready_next = output_axis_tready_int_early & status_ready; output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg); - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; end end else begin - status_valid_next = 1; - status_frame_pad_next = 0; - status_frame_truncate_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b0; + status_frame_truncate_next = 1'b0; status_frame_length_next = frame_ptr_reg+word_cnt; status_frame_original_length_next = frame_ptr_reg+word_cnt; input_axis_tready_next = output_axis_tready_int_early & status_ready; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; @@ -355,39 +355,39 @@ always @* begin end STATE_PAD: begin // pad to minimum length - input_axis_tready_next = 0; + input_axis_tready_next = 1'b0; - output_axis_tdata_int = 0; + output_axis_tdata_int = {DATA_WIDTH{1'b0}}; output_axis_tkeep_int = {KEEP_WIDTH{1'b1}}; - output_axis_tvalid_int = 1; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tvalid_int = 1'b1; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin frame_ptr_next = frame_ptr_reg + KEEP_WIDTH; if (short_counter_reg > KEEP_WIDTH) begin short_counter_next = short_counter_reg - KEEP_WIDTH; end else begin - short_counter_next = 0; + short_counter_next = 16'd0; end if (long_counter_reg > KEEP_WIDTH) begin long_counter_next = long_counter_reg - KEEP_WIDTH; end else begin - long_counter_next = 0; + long_counter_next = 16'd0; end if (short_counter_reg <= KEEP_WIDTH) begin - status_valid_next = 1; - status_frame_pad_next = 1; - status_frame_truncate_next = 0; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b1; + status_frame_truncate_next = 1'b0; status_frame_length_next = length_min; input_axis_tready_next = output_axis_tready_int_early & status_ready; output_axis_tkeep_int = ({KEEP_WIDTH{1'b1}}) >> (KEEP_WIDTH-short_counter_reg); - output_axis_tlast_int = 1; + output_axis_tlast_int = 1'b1; output_axis_tuser_int = last_cycle_tuser_reg; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; @@ -417,13 +417,13 @@ always @* begin frame_ptr_next = frame_ptr_reg+KEEP_WIDTH; if (input_axis_tlast) begin - status_valid_next = 1; - status_frame_pad_next = 0; - status_frame_truncate_next = 1; + status_valid_next = 1'b1; + status_frame_pad_next = 1'b0; + status_frame_truncate_next = 1'b1; status_frame_length_next = length_max; status_frame_original_length_next = frame_ptr_reg+word_cnt; input_axis_tready_next = output_axis_tready_int_early & status_ready; - frame_ptr_next = 0; + frame_ptr_next = 16'd0; short_counter_next = length_min; long_counter_next = length_max; state_next = STATE_IDLE; @@ -440,18 +440,11 @@ end always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; - frame_ptr_reg <= 0; - short_counter_reg <= 0; - long_counter_reg <= 0; - input_axis_tready_reg <= 0; - last_word_data_reg <= 0; - last_word_keep_reg <= 0; - last_cycle_tuser_reg <= 0; - status_valid_reg <= 0; - status_frame_pad_reg <= 0; - status_frame_truncate_reg <= 0; - status_frame_length_reg <= 0; - status_frame_original_length_reg <= 0; + frame_ptr_reg <= 16'd0; + short_counter_reg <= 16'd0; + long_counter_reg <= 16'd0; + input_axis_tready_reg <= 1'b0; + status_valid_reg <= 1'b0; end else begin state_reg <= state_next; @@ -462,33 +455,39 @@ always @(posedge clk) begin input_axis_tready_reg <= input_axis_tready_next; - last_cycle_tuser_reg <= last_cycle_tuser_next; - status_valid_reg <= status_valid_next; - status_frame_pad_reg <= status_frame_pad_next; - status_frame_truncate_reg <= status_frame_truncate_next; - status_frame_length_reg <= status_frame_length_next; - status_frame_original_length_reg <= status_frame_original_length_next; + end - if (store_last_word) begin - last_word_data_reg <= output_axis_tdata_int; - last_word_keep_reg <= output_axis_tkeep_int; - end + last_cycle_tuser_reg <= last_cycle_tuser_next; + + status_frame_pad_reg <= status_frame_pad_next; + status_frame_truncate_reg <= status_frame_truncate_next; + status_frame_length_reg <= status_frame_length_next; + status_frame_original_length_reg <= status_frame_original_length_next; + + if (store_last_word) begin + last_word_data_reg <= output_axis_tdata_int; + last_word_keep_reg <= output_axis_tkeep_int; end end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -496,56 +495,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready and currently valid, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_mux.py b/rtl/axis_mux.py index 16fc4c9f9..4d3550e11 100755 --- a/rtl/axis_mux.py +++ b/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 @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_mux_4.v b/rtl/axis_mux_4.v index bafefba14..319acfd9f 100644 --- a/rtl/axis_mux_4.v +++ b/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 @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_mux_64.py b/rtl/axis_mux_64.py index cc5b5ede6..e38d19a96 100755 --- a/rtl/axis_mux_64.py +++ b/rtl/axis_mux_64.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 @@ -106,17 +106,17 @@ module {{name}} # input wire [{{w-1}}:0] select ); -reg [{{w-1}}:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next; +reg frame_reg = 1'b0, frame_next; {% for p in ports %} -reg input_{{p}}_axis_tready_reg = 0, input_{{p}}_axis_tready_next; +reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next; {%- endfor %} // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -160,7 +160,7 @@ always @* begin select_next = select_reg; frame_next = frame_reg; {% for p in ports %} - input_{{p}}_axis_tready_next = 0; + input_{{p}}_axis_tready_next = 1'b0; {%- endfor %} if (frame_reg) begin @@ -170,7 +170,7 @@ always @* begin end end else if (enable & selected_input_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -191,10 +191,10 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; + select_reg <= {{w}}'d0; + frame_reg <= 1'b0; {%- for p in ports %} - input_{{p}}_axis_tready_reg <= 0; + input_{{p}}_axis_tready_reg <= 1'b0; {%- endfor %} end else begin select_reg <= select_next; @@ -206,17 +206,22 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -224,56 +229,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_mux_64_4.v b/rtl/axis_mux_64_4.v index 624fad750..5e798aa35 100644 --- a/rtl/axis_mux_64_4.v +++ b/rtl/axis_mux_64_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 @@ -86,19 +86,19 @@ module axis_mux_64_4 # input wire [1:0] select ); -reg [1:0] select_reg = 0, select_next; -reg frame_reg = 0, frame_next; +reg [1:0] select_reg = 2'd0, select_next; +reg frame_reg = 1'b0, frame_next; -reg input_0_axis_tready_reg = 0, input_0_axis_tready_next; -reg input_1_axis_tready_reg = 0, input_1_axis_tready_next; -reg input_2_axis_tready_reg = 0, input_2_axis_tready_next; -reg input_3_axis_tready_reg = 0, input_3_axis_tready_next; +reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next; +reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next; +reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next; +reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next; // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -167,10 +167,10 @@ always @* begin select_next = select_reg; frame_next = frame_reg; - input_0_axis_tready_next = 0; - input_1_axis_tready_next = 0; - input_2_axis_tready_next = 0; - input_3_axis_tready_next = 0; + input_0_axis_tready_next = 1'b0; + input_1_axis_tready_next = 1'b0; + input_2_axis_tready_next = 1'b0; + input_3_axis_tready_next = 1'b0; if (frame_reg) begin if (current_input_tvalid & current_input_tready) begin @@ -179,7 +179,7 @@ always @* begin end end else if (enable & selected_input_tvalid) begin // start of frame, grab select value - frame_next = 1; + frame_next = 1'b1; select_next = select; end @@ -201,12 +201,12 @@ end always @(posedge clk) begin if (rst) begin - select_reg <= 0; - frame_reg <= 0; - input_0_axis_tready_reg <= 0; - input_1_axis_tready_reg <= 0; - input_2_axis_tready_reg <= 0; - input_3_axis_tready_reg <= 0; + select_reg <= 2'd0; + frame_reg <= 1'b0; + input_0_axis_tready_reg <= 1'b0; + input_1_axis_tready_reg <= 1'b0; + input_2_axis_tready_reg <= 1'b0; + input_3_axis_tready_reg <= 1'b0; end else begin select_reg <= select_next; frame_reg <= frame_next; @@ -218,17 +218,22 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -236,56 +241,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_rate_limit.v b/rtl/axis_rate_limit.v index fb0da33e8..835863bfd 100644 --- a/rtl/axis_rate_limit.v +++ b/rtl/axis_rate_limit.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 @@ -66,21 +66,22 @@ module axis_rate_limit # // internal datapath reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; -reg [23:0] acc_reg = 0, acc_next; +reg [23:0] acc_reg = 24'd0, acc_next; reg pause; -reg frame_reg = 0, frame_next; +reg frame_reg = 1'b0, frame_next; + +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; assign input_axis_tready = input_axis_tready_reg; always @* begin acc_next = acc_reg; - pause = 0; + pause = 1'b0; frame_next = frame_reg; if (acc_reg >= rate_num) begin @@ -97,7 +98,7 @@ always @* begin if (rate_by_frame) begin pause = ~frame_next; end else begin - pause = 1; + pause = 1'b1; end end @@ -111,9 +112,9 @@ end always @(posedge clk) begin if (rst) begin - acc_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + acc_reg <= 24'd0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin acc_reg <= acc_next; frame_reg <= frame_next; @@ -122,65 +123,83 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_rate_limit_64.v b/rtl/axis_rate_limit_64.v index be6cc1c2c..b527a3497 100644 --- a/rtl/axis_rate_limit_64.v +++ b/rtl/axis_rate_limit_64.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 @@ -70,21 +70,22 @@ module axis_rate_limit_64 # reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; -reg [23:0] acc_reg = 0, acc_next; +reg [23:0] acc_reg = 24'd0, acc_next; reg pause; -reg frame_reg = 0, frame_next; +reg frame_reg = 1'b0, frame_next; + +reg input_axis_tready_reg = 1'b0, input_axis_tready_next; -reg input_axis_tready_reg = 0, input_axis_tready_next; assign input_axis_tready = input_axis_tready_reg; always @* begin acc_next = acc_reg; - pause = 0; + pause = 1'b0; frame_next = frame_reg; if (acc_reg >= rate_num) begin @@ -101,7 +102,7 @@ always @* begin if (rate_by_frame) begin pause = ~frame_next; end else begin - pause = 1; + pause = 1'b1; end end @@ -116,9 +117,9 @@ end always @(posedge clk) begin if (rst) begin - acc_reg <= 0; - frame_reg <= 0; - input_axis_tready_reg <= 0; + acc_reg <= 24'd0; + frame_reg <= 1'b0; + input_axis_tready_reg <= 1'b0; end else begin acc_reg <= acc_next; frame_reg <= frame_next; @@ -127,17 +128,22 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -145,56 +151,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_stat_counter.v b/rtl/axis_stat_counter.v index 77b99e735..cabc98438 100644 --- a/rtl/axis_stat_counter.v +++ b/rtl/axis_stat_counter.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 @@ -91,7 +91,7 @@ reg [1:0] state_reg = STATE_IDLE, state_next; reg [TICK_COUNT_WIDTH-1:0] tick_count_reg = 0, tick_count_next; reg [BYTE_COUNT_WIDTH-1:0] byte_count_reg = 0, byte_count_next; reg [FRAME_COUNT_WIDTH-1:0] frame_count_reg = 0, frame_count_next; -reg frame_reg = 0, frame_next; +reg frame_reg = 1'b0, frame_next; reg store_output; reg [$clog2(TOTAL_LENGTH)-1:0] frame_ptr_reg = 0, frame_ptr_next; @@ -100,12 +100,12 @@ reg [TICK_COUNT_WIDTH-1:0] tick_count_output_reg = 0; reg [BYTE_COUNT_WIDTH-1:0] byte_count_output_reg = 0; reg [FRAME_COUNT_WIDTH-1:0] frame_count_output_reg = 0; -reg busy_reg = 0; +reg busy_reg = 1'b0; // internal datapath reg [7:0] output_axis_tdata_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -115,19 +115,19 @@ assign busy = busy_reg; integer offset, i, bit_cnt; always @* begin - state_next = 2'bz; + state_next = STATE_IDLE; tick_count_next = tick_count_reg; byte_count_next = byte_count_reg; frame_count_next = frame_count_reg; frame_next = frame_reg; - output_axis_tdata_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = 8'd0; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; - store_output = 0; + store_output = 1'b0; frame_ptr_next = frame_ptr_reg; @@ -136,13 +136,13 @@ always @* begin case (state_reg) STATE_IDLE: begin if (trigger) begin - store_output = 1; + store_output = 1'b1; tick_count_next = 0; byte_count_next = 0; frame_count_next = 0; frame_ptr_next = 0; - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin frame_ptr_next = 1; if (TAG_ENABLE) begin output_axis_tdata_int = tag[(TAG_BYTE_WIDTH-1)*8 +: 8]; @@ -153,7 +153,7 @@ always @* begin end else if (FRAME_COUNT_ENABLE) begin output_axis_tdata_int = frame_count_reg[(FRAME_COUNT_BYTE_WIDTH-1)*8 +: 8]; end - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; end state_next = STATE_OUTPUT_DATA; @@ -162,10 +162,10 @@ always @* begin end end STATE_OUTPUT_DATA: begin - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin state_next = STATE_OUTPUT_DATA; frame_ptr_next = frame_ptr_reg + 1; - output_axis_tvalid_int = 1; + output_axis_tvalid_int = 1'b1; offset = 0; if (TAG_ENABLE) begin @@ -201,7 +201,7 @@ always @* begin end end if (frame_ptr_reg == offset-1) begin - output_axis_tlast_int = 1; + output_axis_tlast_int = 1'b1; state_next = STATE_IDLE; end end else begin @@ -229,11 +229,11 @@ always @* begin // count frames if (monitor_axis_tlast) begin // end of frame - frame_next = 0; + frame_next = 1'b0; end else if (~frame_reg) begin // first word after end of frame frame_count_next = frame_count_next + 1; - frame_next = 1; + frame_next = 1'b1; end end end @@ -244,12 +244,9 @@ always @(posedge clk) begin tick_count_reg <= 0; byte_count_reg <= 0; frame_count_reg <= 0; - frame_reg <= 0; + frame_reg <= 1'b0; frame_ptr_reg <= 0; - busy_reg <= 0; - tick_count_output_reg <= 0; - byte_count_output_reg <= 0; - frame_count_output_reg <= 0; + busy_reg <= 1'b0; end else begin state_reg <= state_next; tick_count_reg <= tick_count_next; @@ -260,74 +257,93 @@ always @(posedge clk) begin busy_reg <= state_next != STATE_IDLE; - if (store_output) begin - tick_count_output_reg <= tick_count_reg; - byte_count_output_reg <= byte_count_reg; - frame_count_output_reg <= frame_count_reg; - end + end + + if (store_output) begin + tick_count_output_reg <= tick_count_reg; + byte_count_output_reg <= byte_count_reg; + frame_count_output_reg <= frame_count_reg; end end // output datapath logic -reg [7:0] output_axis_tdata_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [7:0] output_axis_tdata_reg = 8'd0; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [7:0] temp_axis_tdata_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [7:0] temp_axis_tdata_reg = 8'd0; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_tap.v b/rtl/axis_tap.v index b4fa25f91..77165a17c 100644 --- a/rtl/axis_tap.v +++ b/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 @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end diff --git a/rtl/axis_tap_64.v b/rtl/axis_tap_64.v index bed8668bc..0080d5be4 100644 --- a/rtl/axis_tap_64.v +++ b/rtl/axis_tap_64.v @@ -63,7 +63,7 @@ module axis_tap_64 # reg [DATA_WIDTH-1:0] output_axis_tdata_int; reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; reg output_axis_tvalid_int; -reg output_axis_tready_int = 0; +reg output_axis_tready_int_reg = 1'b0; reg output_axis_tlast_int; reg output_axis_tuser_int; wire output_axis_tready_int_early; @@ -76,18 +76,18 @@ localparam [1:0] reg [1:0] state_reg = STATE_IDLE, state_next; -reg frame_reg = 0, frame_next; +reg frame_reg = 1'b0, frame_next; always @* begin state_next = STATE_IDLE; frame_next = frame_reg; - output_axis_tdata_int = 0; - output_axis_tkeep_int = 0; - output_axis_tvalid_int = 0; - output_axis_tlast_int = 0; - output_axis_tuser_int = 0; + output_axis_tdata_int = {DATA_WIDTH{1'b0}}; + output_axis_tkeep_int = {KEEP_WIDTH{1'b0}}; + output_axis_tvalid_int = 1'b0; + output_axis_tlast_int = 1'b0; + output_axis_tuser_int = 1'b0; if (tap_axis_tready & tap_axis_tvalid) begin frame_next = ~tap_axis_tlast; @@ -97,7 +97,7 @@ always @* begin STATE_IDLE: begin if (tap_axis_tready & tap_axis_tvalid) begin // start of frame - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin output_axis_tdata_int = tap_axis_tdata; output_axis_tkeep_int = tap_axis_tkeep; output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready; @@ -118,7 +118,7 @@ always @* begin STATE_TRANSFER: begin if (tap_axis_tready & tap_axis_tvalid) begin // transfer data - if (output_axis_tready_int) begin + if (output_axis_tready_int_reg) begin output_axis_tdata_int = tap_axis_tdata; output_axis_tkeep_int = tap_axis_tkeep; output_axis_tvalid_int = tap_axis_tvalid & tap_axis_tready; @@ -137,12 +137,12 @@ always @* begin end end STATE_TRUNCATE: begin - if (output_axis_tready_int) begin - output_axis_tdata_int = 0; - output_axis_tkeep_int = 1; - output_axis_tvalid_int = 1; - output_axis_tlast_int = 1; - output_axis_tuser_int = 1; + if (output_axis_tready_int_reg) begin + output_axis_tdata_int = {DATA_WIDTH{1'b0}}; + output_axis_tkeep_int = {{KEEP_WIDTH-1{1'b0}}, 1'b1}; + output_axis_tvalid_int = 1'b1; + output_axis_tlast_int = 1'b1; + output_axis_tuser_int = 1'b1; if (frame_next) begin state_next = STATE_WAIT; end else begin @@ -169,7 +169,7 @@ end always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; - frame_reg <= 0; + frame_reg <= 1'b0; end else begin state_reg <= state_next; frame_reg <= frame_next; @@ -177,17 +177,22 @@ always @(posedge clk) begin end // output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = 0; -reg output_axis_tvalid_reg = 0; -reg output_axis_tlast_reg = 0; -reg output_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; +reg output_axis_tlast_reg = 1'b0; +reg output_axis_tuser_reg = 1'b0; -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = 0; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = 0; -reg temp_axis_tvalid_reg = 0; -reg temp_axis_tlast_reg = 0; -reg temp_axis_tuser_reg = 0; +reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; +reg temp_axis_tlast_reg = 1'b0; +reg temp_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; assign output_axis_tdata = output_axis_tdata_reg; assign output_axis_tkeep = output_axis_tkeep_reg; @@ -195,56 +200,66 @@ assign output_axis_tvalid = output_axis_tvalid_reg; assign output_axis_tlast = output_axis_tlast_reg; assign output_axis_tuser = output_axis_tuser_reg; -// enable ready input next cycle if output is ready or if there is space in both output registers or if there is space in the temp register that will not be filled next cycle -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & ~output_axis_tvalid_reg) | (~temp_axis_tvalid_reg & ~output_axis_tvalid_int); +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + output_axis_tvalid_next = output_axis_tvalid_reg; + temp_axis_tvalid_next = temp_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (output_axis_tready_int_reg) begin + // input is ready + if (output_axis_tready | ~output_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + output_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_axis_tvalid_next = output_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (output_axis_tready) begin + // input is not ready, but output is ready + output_axis_tvalid_next = temp_axis_tvalid_reg; + temp_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end always @(posedge clk) begin if (rst) begin - output_axis_tdata_reg <= 0; - output_axis_tkeep_reg <= 0; - output_axis_tvalid_reg <= 0; - output_axis_tlast_reg <= 0; - output_axis_tuser_reg <= 0; - output_axis_tready_int <= 0; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; + output_axis_tvalid_reg <= 1'b0; + output_axis_tready_int_reg <= 1'b0; + temp_axis_tvalid_reg <= 1'b0; end else begin - // transfer sink ready state to source - output_axis_tready_int <= output_axis_tready_int_early; + output_axis_tvalid_reg <= output_axis_tvalid_next; + output_axis_tready_int_reg <= output_axis_tready_int_early; + temp_axis_tvalid_reg <= temp_axis_tvalid_next; + end - if (output_axis_tready_int) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tvalid_reg <= output_axis_tvalid_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else begin - // output is not ready, store input in temp - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tvalid_reg <= output_axis_tvalid_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tvalid_reg <= temp_axis_tvalid_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - temp_axis_tdata_reg <= 0; - temp_axis_tkeep_reg <= 0; - temp_axis_tvalid_reg <= 0; - temp_axis_tlast_reg <= 0; - temp_axis_tuser_reg <= 0; - end + // datapath + if (store_axis_int_to_output) begin + output_axis_tdata_reg <= output_axis_tdata_int; + output_axis_tkeep_reg <= output_axis_tkeep_int; + output_axis_tlast_reg <= output_axis_tlast_int; + output_axis_tuser_reg <= output_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + output_axis_tdata_reg <= temp_axis_tdata_reg; + output_axis_tkeep_reg <= temp_axis_tkeep_reg; + output_axis_tlast_reg <= temp_axis_tlast_reg; + output_axis_tuser_reg <= temp_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_axis_tdata_reg <= output_axis_tdata_int; + temp_axis_tkeep_reg <= output_axis_tkeep_int; + temp_axis_tlast_reg <= output_axis_tlast_int; + temp_axis_tuser_reg <= output_axis_tuser_int; end end