diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..47bff27525d618ed1ec81cf26999a69d22f61973 Binary files /dev/null and b/.DS_Store differ diff --git a/hdl/src/message_build.sv b/hdl/src/message_build.sv new file mode 100644 index 0000000000000000000000000000000000000000..5ef3d373ebf0ce6648ed10f4db31f7d4bcd805fc --- /dev/null +++ b/hdl/src/message_build.sv @@ -0,0 +1,185 @@ +module message_build ( + input logic clk, + input logic nrst, + input logic en, + + // Synchronous, localised reset + input logic sync_rst, + + // Data In data and Handshaking + input logic [511:0] data_in, + input logic data_in_last, + input logic data_in_valid, + output logic data_in_ready, + + // Config data and Handshaking + input logic [63:0] cfg_size, + input logic [1:0] cfg_scheme, + input logic cfg_valid, + output logic cfg_ready, + + // Data Out data and Handshaking + output logic [511:0] data_out, + output logic data_out_last, + output logic data_out_valid, + input logic data_out_ready +); + + logic [9:0] data_word_rem, next_data_word_rem; // Remainder number of bits after 512 division + logic [63:0] cfg_size_reg, next_cfg_size; + logic [2:0] state, next_state; // State Machine State + logic [53:0] data_word_count, next_data_word_count; + + logic [511:0] last_word_mask; + logic [511:0] end_marker; + logic [511:0] last_data_word; + + // Create Mask for last Data Word + // - If Muliple of 512, then no mask needed, else mask off valid data + assign last_word_mask = |data_word_rem ? ((512'd1 << 512) - 1) << (512 - data_word_rem) : ((512'd1 << 512) - 1); + + // Create Position Marker to show end of data message (place a "1") + // - only if not a multiple of 512 + assign end_marker = |data_word_rem ? 1 << (512 - data_word_rem - 1) : 512'd0; + + // Combine Last Data (after being masked) with end marker and size + assign last_data_word = (data_in & last_word_mask) | end_marker; + + always_ff @(posedge clk, negedge nrst) begin + if ((!nrst) | sync_rst) begin + state <= 3'd0; + data_in_ready <= 1'b0; + cfg_ready <= 1'b1; + cfg_size_reg <= 64'd0; + data_word_rem <= 9'd0; + data_out_valid <= 1'b0; + data_out <= 512'd0; + data_word_count <= 54'd0; + end else begin + state <= next_state; + data_in_ready <= next_data_in_ready; + cfg_ready <= next_cfg_ready; + cfg_size_reg <= next_cfg_size; + data_word_rem <= next_data_word_rem; + data_out_valid <= next_data_out_valid; + data_out <= next_data_out; + data_word_count <= next_data_word_count; + end + end + + always_comb begin + // Default + next_state = state; + next_data_in_ready = data_in_ready; + next_cfg_ready = cfg_ready; + next_cfg_size = cfg_size_reg; + next_data_word_rem = data_word_rem; + next_data_out_valid = data_out_valid; + next_data_out = data_out; + next_data_word_count = data_word_count; + + // Override + case (state) + 3'd0: begin // First time State + next_cfg_ready = 1'b1; + end + + 3'd1: begin // Initial Config Read + if (cfg_valid == 1'b1) begin + // Handshake to Acknowledge Config Has been Read + next_cfg_size = cfg_size; + next_cfg_ready = 1'b0; + next_data_in_ready = 1'b1; + next_data_word_count = (cfg_size >> 9) + |cfg_size[8:0]; // Divide by 512 and round up + next_data_word_rem = cfg_size[8:0]; + if (next_data_word_count > 1) begin + next_state = 3'd2; + end else begin + next_state = 3'd3; + end + end + end + + 3'd2: begin // Pass through Data Blocks + // Check outputs can be written to + if (data_out_valid && !data_out_ready) begin + // If data out is valid and ready is low, there is already data waiting to be transferred + next_data_in_ready = 1'b0; + // If there is no Valid data at the output or there is a valid transfer happening on this clock cycle + end else begin + // These can be overloaded later if data is written to the outputs + next_data_out_valid = 1'b0; + next_data_in_ready = 1'b1; + // Check Inputs have data + if (data_in_valid && data_in_ready) begin + // Valid Handshake and data can be processed + // Data Processing Algorithm + next_data_word_count = data_word_count - 1; + // Write Input Data to Output + next_data_out = data_in; + next_data_out_valid = 1'b1; + if (data_word_count == 1) begin + // Last Input Data Word + next_state = 3'd3; + end + end + end + end + + 3'd3: begin // Process Last Read Word + // Check outputs can be written to + if (data_out_valid && !data_out_ready) begin + // If data out is valid and ready is low, there is already data waiting to be transferred + next_data_in_ready = 1'b0; + // If there is no Valid data at the output or there is a valid transfer happening on this clock cycle + end else begin + // These can be overloaded later if data is written to the outputs + next_data_out_valid = 1'b0; + next_data_in_ready = 1'b1; + // Check Inputs have data + if (data_in_valid && data_in_ready) begin + // Valid Handshake and data can be processed + if ((data_word_rem - 1) > 9'd446) begin + // If can't fit size in last word + next_data_out = last_data_word; + next_data_out_valid = 1'b1; + // NEXT STATE: Generate Additional Word + next_state = 3'd4; + next_data_in_ready = 1'b0; + else + // Size can fit in last data word + next_data_out = last_data_word | cfg_size_reg; + next_data_out_valid = 1'b1; + // NEXT STATE: Read Next Config + next_state = 3'd1; + next_data_in_ready = 1'b0; + next_cfg_ready = 1'b1; + end + end + end + end + + 3'd4: begin // Generate Extra Word + // Check outputs can be written to + if (data_out_valid && !data_out_ready) begin + // If data out is valid and ready is low, there is already data waiting to be transferred + next_data_in_ready = 1'b0; + // If there is no Valid data at the output or there is a valid transfer happening on this clock cycle + end else begin + // Size can fit in last data word + next_data_out = {~|data_word_rem, 447'd0, cfg_size_reg}; + next_data_out_valid = 1'b1; + // NEXT STATE: Read Next Config + next_state = 3'd1; + next_data_in_ready = 1'b0; + next_cfg_ready = 1'b1; + end + end + + default: begin + next_state = 3'd0; + end + endcase + end + +endmodule \ No newline at end of file