summaryrefslogtreecommitdiff
path: root/rtl/vdc/vdc_io.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-05-26 11:16:04 -0600
committerAlejandro Soto <alejandro@34project.org>2024-05-26 12:51:51 -0600
commit2e12077e682a27a159122b5676301c8c433a58fe (patch)
tree338ee5116fdda32f6d7c988232dfe20c52a643b6 /rtl/vdc/vdc_io.sv
parente11c49cb39fd7957d74a1431e28efc4049d16799 (diff)
rtl/vdc: initial commit of video display controller
Diffstat (limited to 'rtl/vdc/vdc_io.sv')
-rw-r--r--rtl/vdc/vdc_io.sv184
1 files changed, 184 insertions, 0 deletions
diff --git a/rtl/vdc/vdc_io.sv b/rtl/vdc/vdc_io.sv
new file mode 100644
index 0000000..88b19e3
--- /dev/null
+++ b/rtl/vdc/vdc_io.sv
@@ -0,0 +1,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