diff --git a/.DS_Store b/.DS_Store
index ed5a1627a0488f9e875d5407c85d5a08a9c4e8bb..53434f8e2b2503b1a35cc9227a6ff3c6ae8b9051 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/hdl/src/sha256_id_validator.sv b/hdl/src/sha256_id_validator.sv
new file mode 100644
index 0000000000000000000000000000000000000000..a40d1a5d9bd94e1d1facd787d8a5bd1322509ca7
--- /dev/null
+++ b/hdl/src/sha256_id_validator.sv
@@ -0,0 +1,182 @@
+//-----------------------------------------------------------------------------
+// SoC Labs Basic SHA-256 ID Validator
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+//
+// Copyright  2023, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+module sha256_id_validator (
+    input logic clk,
+    input logic nrst,
+    input logic en,
+    
+    // Synchronous, localised reset
+    input logic sync_rst,
+    
+    // ID Buffer IN
+    input  logic [5:0] id_in_buf,
+    input  logic id_in_buf_last,
+    input  logic id_in_buf_valid,
+    output logic id_in_buf_ready,
+
+    // Hash IN
+    input  logic [255:0] hash_in,
+    input  logic [5:0]   hash_in_id,
+    input  logic hash_in_last,
+    input  logic hash_in_valid,
+    output logic hash_in_ready,
+
+    // Hash Out
+    output logic [255:0] hash_out,
+    output logic hash_out_err,
+    output logic hash_out_last,
+    output logic hash_out_valid,
+    input  logic hash_out_ready,
+
+    // Status Out - Gets updated after every hash
+    output logic [1:0] status_err,
+    output logic [9:0] status_packet_count,
+    input  logic status_clear
+
+);
+    
+    logic [1:0]   state, next_state;
+        
+    logic [255:0] next_hash_out;
+    logic next_hash_out_err;
+    logic next_hash_out_last, next_hash_out_valid;
+    logic next_hash_in_ready, next_id_in_buf_ready;
+
+    logic [255:0] hash_buf;
+    logic [255:0] next_hash_buf;
+
+    logic [5:0]   hash_buf_id, id_buf;
+    logic [5:0]   next_hash_buf_id, next_id_buf;
+
+    // Status
+    logic [1:0]   next_status_err;
+    logic [9:0]   next_status_packet_count;
+    // Status Error
+    // bit 1 high - ID Buffer Error - Buffer has skipped and ID
+    // bit 0 high - Hash ID Error   - Packet has been dropped
+    
+    // State Machine Sequential Logic    
+    always_ff @(posedge clk, negedge nrst) begin
+        if ((!nrst) | sync_rst) begin
+            state            <=   1'd0;
+            hash_out         <= 256'd0;
+            hash_out_err     <=   1'b0;
+            hash_out_last    <=   1'b0;
+            hash_out_valid   <=   1'b0;
+            hash_in_ready    <=   1'b0;
+            id_in_buf_ready  <=   1'b0;
+            hash_buf         <= 256'd0;
+            hash_buf_id      <=   6'd0;
+            id_buf           <=   6'd0;
+        end else if (en == 1'b1) begin
+            state            <= next_state;
+            hash_out         <= next_hash_out;
+            hash_out_err     <= next_hash_out_err;
+            hash_out_last    <= next_hash_out_last;
+            hash_out_valid   <= next_hash_out_valid;
+            hash_in_ready    <= next_hash_in_ready;
+            id_in_buf_ready  <= next_id_in_buf_ready;
+            hash_buf         <= next_hash_buf;
+            hash_buf_id      <= next_hash_buf_id;
+            id_buf           <= id_buf;
+        end else begin
+            hash_out_valid   <= 1'b0;
+            hash_in_ready    <= 1'b0;
+            id_in_buf_ready  <= 1'b0;
+        end
+    end
+    
+    always_comb begin
+        // Default
+        next_state              = state;
+        next_hash_out           = hash_out;
+        next_hash_out_err       = hash_out_err;
+        next_hash_out_last      = hash_out_last;
+        next_hash_out_valid     = hash_out_valid;
+        next_hash_in_ready      = hash_in_ready;
+        next_id_in_buf_ready    = id_in_buf_ready;     
+        next_hash_buf           = hash_buf;
+        next_hash_buf_id        = hash_buf_id;
+        next_id_buf             = id_buf;
+        
+        // Override
+        case (state)
+            2'd0: begin
+                    next_hash_in_ready    = 1'b1;
+                    next_id_in_buf_ready  = 1'b1;
+                    next_state            = 2'd1;
+                end
+                
+            2'd1: begin // Set Packet ID from Seed or Increment Value
+                    if (status_clear) begin
+                        next_status_out_err = 2'b0;
+                    end
+                    if (hash_out_valid && !hash_out_ready) begin
+                        // If data out handshake has not been seen, drop ready
+                        next_hash_in_ready   = 1'b0;
+                        next_id_in_buf_ready = 1'b0;
+                    end else begin
+                        // Check Hash Input Handshaked
+                        if (hash_in_ready && hash_in_ready) begin
+                            next_hash_in_ready = 1'b0;
+                            next_hash_buf      = hash_in;
+                            next_hash_buf_id   = hash_in_id;
+                            // Wait for ID Buffer State
+                            next_state         = 2'd2;
+                        end
+                        // Check ID Buffer Input Handshaked
+                        if (id_in_buf_ready && id_in_buf_valid) begin
+                            next_id_in_buf_ready = 1'b0;
+                            next_id_buf          = id_buf;
+                            // Wait for Hash Input State
+                            next_state           = 2'd3;
+                        end
+                        // Check if Both Input Handshaked
+                        if (hash_in_ready && hash_in_ready) && (id_in_buf_ready && id_in_buf_valid) begin
+                            // Do ID's match?
+                            next_hash_out       = hash_in;
+                            next_hash_out_valid = 1'b0;
+                            if (!cfg_out_valid && cfg_out_ready) begin 
+                                // In case where no valid data and ready is waiting for valid data 
+                                // - (will be asserted next cc), guaranteed handshake next cycle
+                                next_id_in_buf_ready = 1'b1;
+                                next_hash_in_ready   = 1'b1;
+                            end else begin
+                                next_id_in_buf_ready = 1'b0;
+                                next_hash_in_ready   = 1'b0;
+                            end
+                            // ID's don't match
+                            if ((id_in_buf > hash_in_id)||(~id_in_buf[5] & hash_in_id[5])) begin
+                                // If ID Buffer ID > Hash ID - ID Buffer Error
+                                // Pop an additional hash
+                                next_state         = 2'd3;
+                                next_hash_out_err  = 1'b1;
+                                next_status_err[1] = 1'b1; 
+                            end else if ((id_in_buf < hash_in_id)||(id_in_buf[5] & ~hash_in_id[5])) begin
+                                // If ID Buffer ID < Hash ID - Lost Packet Error
+                                // Pop an additional value from the Buffer FIFO
+                                next_state         = 2'd2;
+                                next_hash_out_err  = 1'b1;
+                                next_status_err[0] = 1'b1;
+                            end else begin
+                                next_hash_out_err = 1'b0;
+                                next_state        = 2'd1;
+                            end
+                        end
+                    end
+                end
+            
+            default: begin
+                    next_state = 2'd0;
+                end
+        endcase
+    end
+endmodule
\ No newline at end of file