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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
module vdc_io
import vdc_pkg::*;
(
input logic clk,
rst_n,
input logic frame_start,
input ptr front_base,
input geom_dim lines,
stride,
line_len,
output logic frame_done,
if_axib.m stream,
vdc_dac.tx dac
);
localparam int BURST_BITS = 4;
enum int unsigned
{
ORDER_B_RGB,
ORDER_GB_RG,
ORDER_RGB_R,
ORDER_BUBBLE
} word_order;
ptr araddr, stride_jump, stride_save;
logic bubble, burst_ar_last, first_pix, last_pix, next_bubble, word_r_last;
geom_dim line_ar_count, line_r_count, word_r_count;
pix_rgb24 dac_pix, next_pix;
logic[3:0][7:0] in_cur, in_prev;
logic[$bits(geom_dim) - BURST_BITS - 1:0] burst_ar_count, bursts_per_line;
assign stream.arid = '0;
assign stream.arlen = ($bits(stream.arlen))'((1 << BURST_BITS) - 1);
assign stream.arsize = 3'b010; // 4 bytes/beat
assign stream.araddr = {araddr, 2'b00};
assign stream.arburst = 2'b01; // Incremental mode
assign stream.rready = (~dac.valid | dac.ready) & ~bubble;
assign stream.awid = 'x;
assign stream.awlen = 'x;
assign stream.awsize = 'x;
assign stream.awaddr = 'x;
assign stream.awburst = 'x;
assign stream.awvalid = 0;
assign stream.wdata = 'x;
assign stream.wlast = 'x;
assign stream.wstrb = 'x;
assign stream.wvalid = 0;
assign stream.bready = 0;
assign dac.pix.b = rgb8to10(dac_pix.b);
assign dac.pix.g = rgb8to10(dac_pix.g);
assign dac.pix.r = rgb8to10(dac_pix.r);
assign in_cur = stream.rdata;
assign last_pix = bubble & word_r_last & (line_r_count == '0);
assign stride_jump = stride_save + {{($bits(araddr) - $bits(stride)){1'b0}}, stride};
assign word_r_last = word_r_count == '0;
assign burst_ar_last = burst_ar_count == '0;
assign bursts_per_line = line_len[$bits(line_len) - 1:BURST_BITS];
always_comb begin
unique case (word_order)
ORDER_RGB_R: next_bubble = 1;
default: next_bubble = 0;
endcase
unique case (word_order)
ORDER_BUBBLE: bubble = 1;
default: bubble = 0;
endcase
unique case (word_order)
ORDER_B_RGB: begin
next_pix.b = in_cur[0];
next_pix.g = in_cur[1];
next_pix.r = in_cur[2];
end
ORDER_GB_RG: begin
next_pix.b = in_prev[3];
next_pix.g = in_cur[0];
next_pix.r = in_cur[1];
end
ORDER_RGB_R: begin
next_pix.b = in_prev[2];
next_pix.g = in_prev[3];
next_pix.r = in_cur[0];
end
ORDER_BUBBLE: begin
next_pix.b = in_prev[1];
next_pix.g = in_prev[2];
next_pix.r = in_prev[3];
end
endcase
end
always_ff @(posedge clk) begin
if (stream.arvalid & stream.arready) begin
araddr <= araddr + ($bits(araddr))'(1 << BURST_BITS);
burst_ar_count <= burst_ar_count - 1;
if (burst_ar_last) begin
araddr <= stride_jump;
stride_save <= stride_jump;
burst_ar_count <= bursts_per_line;
line_ar_count <= line_ar_count - 1;
end
end
if (stream.rvalid & stream.rready)
in_prev <= in_cur;
if (~dac.valid | dac.ready) begin
dac_pix <= next_pix;
dac.last <= last_pix;
dac.first <= first_pix;
end
if (dac.valid & dac.ready) begin
first_pix <= 0;
unique case (word_order)
ORDER_B_RGB: word_order <= ORDER_GB_RG;
ORDER_GB_RG: word_order <= ORDER_RGB_R;
ORDER_RGB_R: word_order <= ORDER_BUBBLE;
ORDER_BUBBLE: word_order <= ORDER_B_RGB;
endcase
if (~next_bubble) begin
word_r_count <= word_r_count - 1;
if (word_r_last) begin
line_r_count <= line_r_count - 1;
word_r_count <= line_len;
end
end
end
if (frame_start) begin
araddr <= front_base;
stride_save <= front_base;
line_ar_count <= lines;
burst_ar_count <= bursts_per_line;
first_pix <= 1;
word_order <= ORDER_B_RGB;
line_r_count <= lines;
word_r_count <= line_len;
end
end
always_ff @(posedge clk or negedge rst_n)
if (~rst_n) begin
dac.valid <= 0;
frame_done <= 0;
stream.arvalid <= 0;
end else begin
dac.valid <= (dac.valid & ~dac.ready) | bubble | stream.rvalid;
unique case (1'b1)
frame_start:
stream.arvalid <= 1;
stream.arvalid & stream.arready & burst_ar_last & (line_ar_count == '0):
stream.arvalid <= 0;
default: ;
endcase
frame_done <= dac.valid & dac.ready & last_pix;
end
endmodule
|