|
| 1 | +/* |
| 2 | + * Authored by: Robert Metchev / Chips & Scripts (rmetchev@ieee.org) |
| 3 | + * |
| 4 | + * CERN Open Hardware Licence Version 2 - Permissive |
| 5 | + * |
| 6 | + * Copyright (C) 2024 Robert Metchev |
| 7 | + */ |
| 8 | +module bit_pack ( |
| 9 | + //packed code+coeff |
| 10 | + input logic [63:0] in_data, |
| 11 | + input logic [6:0] in_nbits, |
| 12 | + input logic in_tlast, |
| 13 | + input logic in_valid, |
| 14 | + output logic in_hold, |
| 15 | + |
| 16 | + output logic [31:0] out_data, |
| 17 | + output logic [2:0] out_nbytes, |
| 18 | + output logic out_tlast, |
| 19 | + output logic out_valid, |
| 20 | + input logic out_hold, |
| 21 | + |
| 22 | + input logic clk, |
| 23 | + input logic resetn |
| 24 | +); |
| 25 | + |
| 26 | +// 1.) 64-bit to 32-bit align: There will be extremely rarely more than 32 bits. |
| 27 | +// Stall during 1st 32 bits. |
| 28 | +logic [31:0] in32_data; |
| 29 | +logic [5:0] in32_nbits; |
| 30 | +logic in32_tlast; |
| 31 | +logic in32_valid; |
| 32 | +logic in32_hold; |
| 33 | +logic long_in; |
| 34 | + |
| 35 | +always @(posedge clk) |
| 36 | +if (!resetn) begin |
| 37 | + in32_valid <= 0; |
| 38 | + long_in <= 0; |
| 39 | +end |
| 40 | +else if (~(in32_hold & in32_valid)) begin |
| 41 | + in32_valid <= in_valid; |
| 42 | + |
| 43 | + if (long_in) |
| 44 | + long_in <= 0; |
| 45 | + else if (in_valid & in_nbits > 32) |
| 46 | + long_in <= 1; |
| 47 | +end |
| 48 | + |
| 49 | +always @(posedge clk) |
| 50 | +if (~(in32_hold & in32_valid)) |
| 51 | + if (long_in) begin |
| 52 | + in32_nbits <= in_nbits - 32; |
| 53 | + in32_data <= in_data; |
| 54 | + in32_tlast <= in_tlast; |
| 55 | + end |
| 56 | + else if (in_valid) |
| 57 | + if (in_nbits > 32) begin |
| 58 | + in32_nbits <= 32; |
| 59 | + in32_data <= in_data >> 32; |
| 60 | + in32_tlast <= 0; |
| 61 | + end |
| 62 | + else begin |
| 63 | + in32_nbits <= in_nbits; |
| 64 | + in32_data <= in_data >> 32; |
| 65 | + in32_tlast <= in_tlast; |
| 66 | + end |
| 67 | + |
| 68 | +// Stall to split 32+ into 32 + remainder |
| 69 | +always_comb in_hold = (in32_hold & in32_valid) | (~long_in & in_nbits > 32); // goes out |
| 70 | + |
| 71 | + |
| 72 | +// 2.) incoming: 32 bits max = 4 bytes |
| 73 | +// send data when more than 31 bits in storage |
| 74 | +logic [5:0] bit_count, next_bit_count, next_bit_count_incr, next_bit_count_decr; |
| 75 | +logic [63:0] bit_packer, next_bit_packer, next_bit_packer_load; |
| 76 | +logic [5:0] next_bit_packer_shift; |
| 77 | +logic tlast_cycle, next_tlast_cycle; |
| 78 | +logic next_out_tlast; |
| 79 | + |
| 80 | +always_comb out_data = (bit_packer >> 32) | (out_tlast ? (32'hffffffff >> bit_count) : 0); |
| 81 | +always_comb next_bit_count = bit_count + next_bit_count_incr - next_bit_count_decr; |
| 82 | +always_comb next_bit_packer = (bit_packer << next_bit_packer_shift) | (next_bit_packer_load << (32 + next_bit_count_decr - bit_count)); |
| 83 | + |
| 84 | +always_comb begin |
| 85 | + if (out_tlast) begin |
| 86 | + next_bit_count_decr = bit_count; |
| 87 | + next_bit_packer_shift = 32; |
| 88 | + end |
| 89 | + else if (bit_count >= 32) begin |
| 90 | + next_bit_count_decr = 32; |
| 91 | + next_bit_packer_shift = 32; |
| 92 | + end |
| 93 | + else begin |
| 94 | + next_bit_count_decr = 0; |
| 95 | + next_bit_packer_shift = 0; |
| 96 | + end |
| 97 | + |
| 98 | + if (in32_valid & ~in32_hold) begin |
| 99 | + next_bit_count_incr = in32_nbits; |
| 100 | + next_bit_packer_load = in32_data; |
| 101 | + end |
| 102 | + else begin |
| 103 | + next_bit_count_incr = 0; |
| 104 | + next_bit_packer_load = 0; |
| 105 | + end |
| 106 | + |
| 107 | + if (tlast_cycle) |
| 108 | + next_tlast_cycle = ~out_tlast; |
| 109 | + else if (in32_valid) |
| 110 | + next_tlast_cycle = in32_tlast; |
| 111 | + else |
| 112 | + next_tlast_cycle = tlast_cycle; |
| 113 | +end |
| 114 | + |
| 115 | +always @(posedge clk) |
| 116 | +if (!resetn) begin |
| 117 | + bit_count <= 0; |
| 118 | + tlast_cycle <= 0; |
| 119 | + out_tlast <= 0; |
| 120 | + out_valid <= 0; |
| 121 | + bit_packer <= 0; |
| 122 | +end |
| 123 | +else if (~(out_hold & out_valid)) begin |
| 124 | + bit_count <= next_bit_count; |
| 125 | + tlast_cycle <= next_tlast_cycle; |
| 126 | + |
| 127 | + out_tlast <= next_tlast_cycle & next_bit_count <= 32; |
| 128 | + out_valid <= (next_tlast_cycle & next_bit_count <= 32) | next_bit_count >= 32; //always_comb out_valid = out_tlast | bit_count >= 32; |
| 129 | + |
| 130 | + bit_packer <= next_bit_packer; |
| 131 | +end |
| 132 | + |
| 133 | +always @(posedge clk) |
| 134 | +if (~(out_hold & out_valid)) |
| 135 | + out_nbytes <= (next_tlast_cycle & next_bit_count <= 32) ? (next_bit_count + 7) >> 3 : 4; // always_comb out_nbytes = out_tlast ? (bit_count + 7) >> 3 : 4; |
| 136 | + |
| 137 | +always_comb in32_hold = (out_hold & out_valid) | (tlast_cycle & ~out_tlast); |
| 138 | + |
| 139 | +endmodule |
0 commit comments