gateware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit b8e750af8434a0880e8b64c878b75586213c45ee
parent 76056d1ce0d78e2b809674e57450beac991483fc
Author: Brian Swetland <swetland@frotz.net>
Date:   Thu,  6 Feb 2020 15:08:17 -0800

display: dvi/hdmi backend processing

- tidied up from some xilinx projects in 2014
- but without the benefit of 10x gearing w/ xilinx OSERDES

Diffstat:
Ahdl/display/dvi-backend.sv | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/display/dvi-encoder.sv | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 200 insertions(+), 0 deletions(-)

diff --git a/hdl/display/dvi-backend.sv b/hdl/display/dvi-backend.sv @@ -0,0 +1,120 @@ +// Copyright 2014, Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0. + +`default_nettype none + +module dvi_backend ( + input pixclk, + input pixclk5x, + + // TMDS33 outputs at pixclk5x DDR + output wire [3:0]pin_dvi_dp, + output wire [3:0]pin_dvi_dn, + + // RGB data input at pixclk + input wire hsync, + input wire vsync, + input wire active, + input wire [7:0]red, + input wire [7:0]grn, + input wire [7:0]blu + ); + +wire [3:0]dvi_dp; +wire [3:0]dvi_dn; + +wire [9:0] ch0, ch1, ch2; + +reg [9:0]ch3 = 10'b0000011111; + +dvi_encoder enc2( + .clk(pixclk), + .din(red), + .ctrl(0), + .active(active), + .dout(ch2)); + +dvi_encoder enc1( + .clk(pixclk), + .active(active), + .din(grn), + .ctrl(0), + .dout(ch1)); + +dvi_encoder enc0( + .clk(pixclk), + .active(active), + .din(blu), + .ctrl({vsync,hsync}), + .dout(ch0)); + +// shift registers +reg [9:0]ch0s; +reg [9:0]ch1s; +reg [9:0]ch2s; +reg [9:0]ch3s; + +reg [4:0]cycle = 5'b00001; + +// TODO ideally cycle[0] would occur on the 4th +// pixclk5x tick within every pixclk +// +always_ff @(posedge pixclk5x) begin + cycle <= { cycle[0], cycle[4:1] }; + ch0s <= cycle[0] ? ch0 : { 2'b0, ch0s[9:2] }; + ch1s <= cycle[0] ? ch1 : { 2'b0, ch1s[9:2] }; + ch2s <= cycle[0] ? ch2 : { 2'b0, ch2s[9:2] }; + ch3s <= cycle[0] ? ch3 : { 2'b0, ch3s[9:2] }; +end + +dvi_ddr_out ddo0 ( + .clk(pixclk5x), + .din(ch0s[1:0]), + .pin_dp(pin_dvi_dp[0]), + .pin_dn(pin_dvi_dn[0])); + +dvi_ddr_out ddo1 ( + .clk(pixclk5x), + .din(ch1s[1:0]), + .pin_dp(pin_dvi_dp[1]), + .pin_dn(pin_dvi_dn[1])); + +dvi_ddr_out ddo2 ( + .clk(pixclk5x), + .din(ch2s[1:0]), + .pin_dp(pin_dvi_dp[2]), + .pin_dn(pin_dvi_dn[2])); + +dvi_ddr_out ddo3 ( + .clk(pixclk5x), + .din(ch3s[1:0]), + .pin_dp(pin_dvi_dp[3]), + .pin_dn(pin_dvi_dn[3])); + +endmodule + +module dvi_ddr_out( + input wire clk, + input wire [1:0]din, + output wire pin_dp, + output wire pin_dn +); + +`ifndef verilator +ODDRX1F dp( + .D0(din[0]), + .D1(din[1]), + .Q(pin_dp), + .SCLK(clk), + .RST(0)); + +ODDRX1F dn( + .D0(~din[0]), + .D1(~din[1]), + .Q(pin_dn), + .SCLK(clk), + .RST(0)); +`endif + +endmodule + diff --git a/hdl/display/dvi-encoder.sv b/hdl/display/dvi-encoder.sv @@ -0,0 +1,80 @@ +// Copyright 2014, Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0. + +`default_nettype none + +module dvi_encoder( + input wire clk, + input wire active, + input wire [7:0]din, + input wire [1:0]ctrl, + output reg [9:0]dout + ); + +reg [3:0]acc = 0; + +wire [8:0]xo; +wire [8:0]xn; + +assign xn[0] = din[0]; +assign xn[1] = din[1] ~^ xn[0]; +assign xn[2] = din[2] ~^ xn[1]; +assign xn[3] = din[3] ~^ xn[2]; +assign xn[4] = din[4] ~^ xn[3]; +assign xn[5] = din[5] ~^ xn[4]; +assign xn[6] = din[6] ~^ xn[5]; +assign xn[7] = din[7] ~^ xn[6]; +assign xn[8] = 0; + +assign xo[0] = din[0]; +assign xo[1] = din[1] ^ xo[0]; +assign xo[2] = din[2] ^ xo[1]; +assign xo[3] = din[3] ^ xo[2]; +assign xo[4] = din[4] ^ xo[3]; +assign xo[5] = din[5] ^ xo[4]; +assign xo[6] = din[6] ^ xo[5]; +assign xo[7] = din[7] ^ xo[6]; +assign xo[8] = 1; + +localparam Z3 = 3'd0; + +wire [3:0]ones = + {Z3,din[0]} + {Z3,din[1]} + {Z3,din[2]} + + {Z3,din[3]} + {Z3,din[4]} + {Z3,din[5]} + + {Z3,din[6]} + {Z3,din[7]}; + +wire use_xn = ((ones > 4) | ((ones == 4) & (din[0] == 0))); + +wire [8:0]tmp = use_xn ? xn : xo; +wire [3:0]tmp_ones = + {Z3,tmp[0]} + {Z3,tmp[1]} + {Z3,tmp[2]} + + {Z3,tmp[3]} + {Z3,tmp[4]} + {Z3,tmp[5]} + + {Z3,tmp[6]} + {Z3,tmp[7]}; + +wire no_bias = (acc == 0) | (tmp_ones == 4); + +wire same_sign = (acc[3] == tmp_ones[3]); + +wire inv = no_bias ? (~tmp[8]) : same_sign; + +wire [9:0]enc = { inv, tmp[8], inv ? ~tmp[7:0] : tmp[7:0] }; + +always @(posedge clk) begin + if (active) begin + dout <= enc; + acc <= acc - 5 + {Z3,enc[0]} + {Z3,enc[1]} + + {Z3,enc[2]} + {Z3,enc[3]} + {Z3,enc[4]} + + {Z3,enc[5]} + {Z3,enc[6]} + {Z3,enc[7]} + + {Z3,enc[8]} + {Z3,enc[9]}; + end else begin + case (ctrl) + 2'b00: dout <= 10'b1101010100; + 2'b01: dout <= 10'b0010101011; + 2'b10: dout <= 10'b0101010100; + 2'b11: dout <= 10'b1010101011; + endcase + acc <= 0; + end +end + +endmodule