`timescale 1ns/1ps // Single-clock unsigned stream: y = 3 * (a + b) modulo 256. // Two-entry registered FIFO followed by two elastic register stages. // Transfers occur on rising edges with valid && ready, except during rst. module dp_stream_calculator ( input logic clk, input logic rst, input logic in_valid, output logic in_ready, input logic [7:0] in_a, input logic [7:0] in_b, input logic [7:0] in_tag, output logic out_valid, input logic out_ready, output logic [7:0] out_y, output logic [7:0] out_tag ); logic [7:0] fifo_a [0:1]; logic [7:0] fifo_b [0:1]; logic [7:0] fifo_tag [0:1]; logic read_ptr, write_ptr; logic [1:0] fifo_count; // 0, 1, or 2; pointer equality is ambiguous. logic fifo_pop, fifo_push; logic v1, v2, s1_ready, s2_ready; logic [8:0] s1_sum; logic [7:0] s1_tag; logic [10:0] scaled; assign s2_ready = !v2 || out_ready; assign s1_ready = !v1 || s2_ready; assign fifo_pop = !rst && (fifo_count != 2'd0) && s1_ready; assign in_ready = !rst && ((fifo_count < 2'd2) || fifo_pop); assign fifo_push = in_valid && in_ready; assign out_valid = !rst && v2; assign scaled = {2'b00, s1_sum} * 11'd3; always_ff @(posedge clk) begin if (rst) begin read_ptr <= 1'b0; write_ptr <= 1'b0; fifo_count <= 2'd0; v1 <= 1'b0; v2 <= 1'b0; end else begin // The old FIFO head is sampled before a same-edge replacement write. if (fifo_pop) read_ptr <= !read_ptr; if (fifo_push) begin fifo_a[write_ptr] <= in_a; fifo_b[write_ptr] <= in_b; fifo_tag[write_ptr] <= in_tag; write_ptr <= !write_ptr; end case ({fifo_push, fifo_pop}) 2'b10: fifo_count <= fifo_count + 2'd1; 2'b01: fifo_count <= fifo_count - 2'd1; default: fifo_count <= fifo_count; endcase if (s1_ready) begin v1 <= fifo_pop; if (fifo_pop) begin s1_sum <= {1'b0, fifo_a[read_ptr]} + {1'b0, fifo_b[read_ptr]}; s1_tag <= fifo_tag[read_ptr]; end end if (s2_ready) begin v2 <= v1; if (v1) begin out_y <= scaled[7:0]; out_tag <= s1_tag; end end end end endmodule