diff options
Diffstat (limited to 'rtl/vdc/vdc_io.sv')
| -rw-r--r-- | rtl/vdc/vdc_io.sv | 184 |
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 |
