From 5ef1470360a255df2aea5cab9744938f9209bbac Mon Sep 17 00:00:00 2001
From: dam1n19 <d.a.mapstone@soton.ac.uk>
Date: Wed, 4 Jan 2023 12:51:40 +0000
Subject: [PATCH] Added Message Builder

---
 .DS_Store                | Bin 0 -> 6148 bytes
 hdl/src/message_build.sv | 185 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 .DS_Store
 create mode 100644 hdl/src/message_build.sv

diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..47bff27525d618ed1ec81cf26999a69d22f61973
GIT binary patch
literal 6148
zcmZQzU|@7AO)+F(5MW?n;9!8zOq>i@0Z1N%F(jFwB5WY@KxTO6<R>TP<R?K5gi4Q6
zgE$00amT`t#*o91&rpsQe~t_c40`{;0PF*1h75)jh8#3i>#?g!Dlaa8riC3z1v#0;
zB?bo97@3$^SlQS)*g3d4VuLgC%Y#c2OG=BK5{sfiypa6-oFo`KF)1uFwLD%x#5q5&
zBr!8DwFsmnI5Q<RDX}OfJTosPzuYOmG%uwXtQRW5!O6iHFCbA}ZDL@eqhM-aQmdm-
zZE0knqhMleR$I%-A*!rz9TcCPlbe^{1@;vKBO`=n;DypKs+)m<0qW<n;G(>o{JeBX
zN@w6?2x4$$aAa^{@MUmi&|}DDNI?x1Mp?8_;b16c$Y&^JC}K!vNM*=nNJUc*vI{w^
zVQv_uM?+vV1V%%E79jvF_c*v|Vfd(-qaiRF0z*0kK;?r1w8i59r5hkLNQ!}xfdSkF
zU}Rumfq9e>)DM8D0ci!P0ci!%Agv6HAQo62td)Tgs+AGk4Pjtl1b0b5G*~+WBLi4F
z10w@iJG`;R2+_{K2(_6J+CyOk^=LrmL$ot6LbSu2H%gC&z-S0SLx34V3xMi>R|W=L
z{eOt6QF1f{Mnhm&h5#drOR$R*sM5sYJy2Z>s!tQ3@}SxuR2?&d>S=@+xGH9X3@A!K
fg+bLlNGpg2SH+ABkeYn7Api@ZQF=54=pO<ACBAsQ

literal 0
HcmV?d00001

diff --git a/hdl/src/message_build.sv b/hdl/src/message_build.sv
new file mode 100644
index 0000000..5ef3d37
--- /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
-- 
GitLab