After purchasing a new FPGA board I was left wondering how to obtain video output. Actually it was a factor in my decision to purchase the board. I wanted to learn something about the new digital standard TV signals. Learning the NTSC standard well enough to obtain colour output was quite a feat for me, not being the brightest guy around. And I've fretted over learning about the newest digital standards.
I've got several VGA standard cores and wondered what would be required to convert them to the new standard ? Well it turns out I didn't have to do very much to obtain HDMI output. How to get HDMI output from the Atlys FPGA board ? Simple - use the dvi_encoder core available for free from Xilinx. The DVI encoder core outputs a digital stream compatible with the HDMI standard. I learned that the DVI and HDMI standards are related. HDMI has a different physical connector than DVI but transmits the same digital codes.
In order to convert from VGA to HDMI it's relatively simple. Take the regular VGA output and feed it into the DVI encoder core instead of to the pins on the FPGA. That's all there is to it. The one other thing that has to be done is to implement a clock generator for the DVI encoder core. It requires a pixel clock, 2x pixel clock, and 10 x pixel clock. This is easily accomplished using the DCM's in the FPGA.
After studying the core for a while, I decided to add my own tweak. In the encode.v module there's a sideways adder, that could also be considered to be a population counter. An alternate approach that's more code but marginally better performance, is to use lookup tables.
// Use a simple lookup table rather
than adders
function [2:0] popcnt4;
input [3:0] a;
begin
case(a)
4'd0: popcnt4 = 3'd0;
4'd1: popcnt4 = 3'd1;
4'd2: popcnt4 = 3'd1;
4'd3: popcnt4 = 3'd2;
4'd4: popcnt4 = 3'd1;
4'd5: popcnt4 = 3'd2;
4'd6: popcnt4 = 3'd2;
4'd7: popcnt4 = 3'd3;
4'd8: popcnt4 = 3'd1;
4'd9: popcnt4 = 3'd2;
4'd10: popcnt4 = 3'd2;
4'd11: popcnt4 = 3'd3;
4'd12: popcnt4 = 3'd2;
4'd13: popcnt4 = 3'd3;
4'd14: popcnt4 = 3'd3;
4'd15: popcnt4 = 3'd4;
endcase
end
endfunction
function [3:0] popcnt8;
input [7:0] a;
begin
popcnt8 = {1'b0,popcnt4(a[7:4])} + {1'b0,popcnt4(a[3:0])};
end
endfunction
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tweaked the following adder into
lookup tables.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clkin) begin
n1d <=#1 popcnt8(din); //din[0] + din[1] + din[2] + din[3] +
din[4] + din[5] + din[6] + din[7];
din_q <=#1 din;
end