-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpacket_assembler.sv
More file actions
86 lines (76 loc) · 3.14 KB
/
packet_assembler.sv
File metadata and controls
86 lines (76 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Implementation of HDMI packet ECC calculation.
// By Sameer Puri https://github.com/sameer
module packet_assembler (
input logic clk_pixel,
input logic reset,
input logic data_island_period,
input logic [23:0] header, // See Table 5-8 Packet Types
input logic [55:0] sub [3:0],
output logic [8:0] packet_data, // See Figure 5-4 Data Island Packet and ECC Structure
output logic [4:0] counter = 5'd0
);
// 32 pixel wrap-around counter. See Section 5.2.3.4 for further information.
always_ff @(posedge clk_pixel)
begin
if (reset)
counter <= 5'd0;
else if (data_island_period)
counter <= counter + 5'd1;
end
// BCH packets 0 to 3 are transferred two bits at a time, see Section 5.2.3.4 for further information.
wire [5:0] counter_t2 = {counter, 1'b0};
wire [5:0] counter_t2_p1 = {counter, 1'b1};
// Initialize parity bits to 0
logic [7:0] parity [4:0] = '{8'd0, 8'd0, 8'd0, 8'd0, 8'd0};
wire [63:0] bch [3:0];
assign bch[0] = {parity[0], sub[0]};
assign bch[1] = {parity[1], sub[1]};
assign bch[2] = {parity[2], sub[2]};
assign bch[3] = {parity[3], sub[3]};
wire [31:0] bch4 = {parity[4], header};
assign packet_data = {bch[3][counter_t2_p1], bch[2][counter_t2_p1], bch[1][counter_t2_p1], bch[0][counter_t2_p1], bch[3][counter_t2], bch[2][counter_t2], bch[1][counter_t2], bch[0][counter_t2], bch4[counter]};
// See Figure 5-5 Error Correction Code generator. Generalization of a CRC with binary BCH.
// See https://web.archive.org/web/20190520020602/http://hamsterworks.co.nz/mediawiki/index.php/Minimal_HDMI#Computing_the_ECC for an explanation of the implementation.
// See https://en.wikipedia.org/wiki/BCH_code#Systematic_encoding:_The_message_as_a_prefix for further information.
function automatic [7:0] next_ecc;
input [7:0] ecc, next_bch_bit;
begin
next_ecc = (ecc >> 1) ^ ((ecc[0] ^ next_bch_bit) ? 8'b10000011 : 8'd0);
end
endfunction
logic [7:0] parity_next [4:0];
// The parity needs to be calculated 2 bits at a time for blocks 0 to 3.
// There's 56 bits being sent 2 bits at a time over TMDS channels 1 & 2, so the parity bits wouldn't be ready in time otherwise.
logic [7:0] parity_next_next [3:0];
genvar i;
generate
for(i = 0; i < 5; i++)
begin: parity_calc
if (i == 4)
assign parity_next[i] = next_ecc(parity[i], header[counter]);
else
begin
assign parity_next[i] = next_ecc(parity[i], sub[i][counter_t2]);
assign parity_next_next[i] = next_ecc(parity_next[i], sub[i][counter_t2_p1]);
end
end
endgenerate
always_ff @(posedge clk_pixel)
begin
if (reset)
parity <= '{8'd0, 8'd0, 8'd0, 8'd0, 8'd0};
else if (data_island_period)
begin
if (counter < 5'd28) // Compute ECC only on subpacket data, not on itself
begin
parity[3:0] <= parity_next_next;
if (counter < 5'd24) // Header only has 24 bits, whereas subpackets have 56 and 56 / 2 = 28.
parity[4] <= parity_next[4];
end
else if (counter == 5'd31)
parity <= '{8'd0, 8'd0, 8'd0, 8'd0, 8'd0}; // Reset ECC for next packet
end
else
parity <= '{8'd0, 8'd0, 8'd0, 8'd0, 8'd0};
end
endmodule