Moved hardcoded numbers to parameters, improved newline behaviour, tried to get 1080p60 to work

This commit is contained in:
Dreaded_X 2020-03-03 01:51:40 +01:00
parent 5d5fef95df
commit 9b5fd29244
3 changed files with 170 additions and 45 deletions

View File

@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project name="HDMI" board="Mojo" language="Verilog" version="2"> <project name="HDMI" board="Mojo" language="Verilog" version="2">
<files> <files>
<component>cclk_detector.luc</component> <src>hdmi_encoder.luc</src>
<component>simple_dual_ram.v</component>
<component>async_fifo.luc</component>
<component>uart_rx.luc</component>
<component>fifo_2x_reducer.luc</component>
<component>tmds_encoder.luc</component>
<component>spi_slave.luc</component>
<src top="true">mojo_top.v</src> <src top="true">mojo_top.v</src>
<component>serdes_n_to_1.luc</component> <component>uart_rx.luc</component>
<component>uart_tx.luc</component>
<component>dvi_encoder.luc</component>
<component>hdmi_encoder.luc</component>
<src>sram.v</src> <src>sram.v</src>
<component>fifo_2x_reducer.luc</component>
<component>dvi_globals.luc</component> <component>dvi_globals.luc</component>
<component>avr_interface.luc</component> <component>avr_interface.luc</component>
<constraint lib="true">hdmi.ucf</constraint> <component>dvi_encoder.luc</component>
<component>spi_slave.luc</component>
<component>uart_tx.luc</component>
<component>serdes_n_to_1.luc</component>
<component>simple_dual_ram.v</component>
<component>async_fifo.luc</component>
<component>cclk_detector.luc</component>
<component>tmds_encoder.luc</component>
<constraint lib="true">mojo.ucf</constraint> <constraint lib="true">mojo.ucf</constraint>
<constraint lib="true">hdmi.ucf</constraint>
<core name="clk_wiz_v3_6"> <core name="clk_wiz_v3_6">
<src>..\clk_wiz_v3_6.v</src> <src>..\clk_wiz_v3_6.v</src>
</core> </core>

115
source/hdmi_encoder.luc Normal file
View File

@ -0,0 +1,115 @@
/******************************************************************************
The MIT License (MIT)
Copyright (c) 2019 Alchitry
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*****************************************************************************/
module hdmi_encoder #(
PCLK_DIV = 1 : PCLK_DIV >= 1 && PCLK_DIV < 12,
Y_RES = 720 : Y_RES > 0,
X_RES = 1280 : X_RES > 0,
Y_FRAME = 750 : Y_FRAME >= Y_RES + 15,
X_FRAME = 1667 : X_FRAME >= X_RES + 30
)(
input clk, // clock
input rst, // reset
output pclk,
output tmds[4],
output tmdsb[4],
output active,
output x[12],
output y[11],
input red[8],
input green[8],
input blue[8]
) {
sig clkfbin;
xil_PLL_BASE pll_oserdes (
#CLKIN_PERIOD(10),
#CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN
#CLKOUT0_DIVIDE(1 * PCLK_DIV),
#CLKOUT1_DIVIDE(10 * PCLK_DIV),
#CLKOUT2_DIVIDE(5 * PCLK_DIV),
#COMPENSATION("SOURCE_SYNCHRONOUS"),
.CLKFBIN(clkfbin),
.CLKIN(clk),
.RST(0)
);
xil_BUFG clkfb_buf (.I(pll_oserdes.CLKFBOUT));
always clkfbin = clkfb_buf.O;
xil_BUFG pclkx2_buf (.I(pll_oserdes.CLKOUT2));
xil_BUFG pclk_buf(.I(pll_oserdes.CLKOUT1));
xil_BUFPLL ioclk_buf (
#DIVIDE(5),
.PLLIN(pll_oserdes.CLKOUT0),
.GCLK(pclkx2_buf.O),
.LOCKED(pll_oserdes.LOCKED)
);
.clk(pclk_buf.O) {
.rst(rst) {
dff ctrX[12];
dff ctrY[11];
}
}
sig hSync, vSync, drawArea;
dvi_encoder dvi (
.pclk(pclk_buf.O),
.pclkx2(pclkx2_buf.O),
.pclkx10(ioclk_buf.IOCLK),
.strobe(ioclk_buf.SERDESSTROBE),
.rst(~ioclk_buf.LOCK),
.blue(blue),
.green(green),
.red(red),
.hsync(hSync),
.vsync(vSync),
.de(drawArea)
);
always {
ctrX.d = (ctrX.q == X_FRAME-1) ? 0 : ctrX.q + 1;
if (ctrX.q == X_FRAME-1)
ctrY.d = (ctrY.q == Y_FRAME-1) ? 0 : ctrY.q + 1;
pclk = pclk_buf.O;
hSync = (ctrX.q >= X_RES + 10) && (ctrX.q < X_RES + 20);
vSync = (ctrY.q >= Y_RES + 10) && (ctrY.q < Y_RES + 12);
drawArea = (ctrX.q < X_RES) && (ctrY.q < Y_RES);
active = drawArea;
x = ctrX.q;
y = ctrY.q;
tmds = dvi.tmds;
tmdsb = dvi.tmdsb;
}
}

View File

@ -27,8 +27,8 @@ module mojo_top(
wire hdmi_clk; wire hdmi_clk;
reg[7:0] hdmired, hdmigreen, hdmiblue; reg[7:0] hdmired, hdmigreen, hdmiblue;
wire[10:0] hdmix; wire[11:0] hdmix;
wire[9:0] hdmiy; wire[10:0] hdmiy;
reg[7:0] frame_q, frame_d; reg[7:0] frame_q, frame_d;
@ -37,7 +37,17 @@ module mojo_top(
.CLK_OUT1(hdmi_clk) .CLK_OUT1(hdmi_clk)
); );
hdmi_encoder hdmi( localparam SCALE = 2;
localparam WIDTH = 1280;
localparam HEIGHT = 720;
// localparam WIDTH = 1920;
// localparam HEIGHT = 1080;
localparam CHAR_HMAX = WIDTH / (SCALE*8);
localparam CHAR_VMAX = HEIGHT / (SCALE*8);
// @todo 1080p30 does not work for some reason (already extended number of bits)
hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+30), .X_FRAME(WIDTH+387)) hdmi(
// hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+45), .X_FRAME(WIDTH+303)) hdmi(
.clk(hdmi_clk), .clk(hdmi_clk),
.rst(rst), .rst(rst),
.tmds(hdmi1_tmds), .tmds(hdmi1_tmds),
@ -147,13 +157,11 @@ module mojo_top(
assign char_data[93] = 30'h610C46; // } assign char_data[93] = 30'h610C46; // }
assign char_data[94] = 30'hAA0000; // ~ assign char_data[94] = 30'hAA0000; // ~
reg[11:0] char_index_q, char_index_d; reg[13:0] char_index_q, char_index_d;
reg[10:0] charx; reg[10:0] charx;
reg[9:0] chary; reg[9:0] chary;
localparam SCALE = 2;
reg[7:0] tx_data; reg[7:0] tx_data;
reg new_tx_data; reg new_tx_data;
wire tx_busy; wire tx_busy;
@ -185,11 +193,11 @@ module mojo_top(
.new_rx_data(new_rx_data) .new_rx_data(new_rx_data)
); );
reg [11:0] addr_q, addr_d; reg [13:0] addr_q, addr_d;
reg[7:0] write_data; reg[7:0] write_data;
reg write_enable; reg write_enable;
wire[7:0] sram_read_data; wire[7:0] sram_read_data;
sram #(.SIZE(8), .DEPTH(3600)) sram( sram #(.SIZE(8), .DEPTH(CHAR_HMAX*CHAR_VMAX)) sram(
.clk(hdmi_clk), .clk(hdmi_clk),
.read_address(char_index_q), .read_address(char_index_q),
.write_address(addr_q), .write_address(addr_q),
@ -199,23 +207,26 @@ module mojo_top(
); );
always @(*) begin always @(*) begin
hdmired = 1'h28; hdmired = 1'b0;
hdmigreen = 1'h28; hdmigreen = 1'b0;
hdmiblue = 1'h28; hdmiblue = 1'b0;
charx = (hdmix >> (SCALE-1)) % 8; // @todo For some reason we need a -1 here, otherwise it looks weird with
// SCALE = 1
// Need to figure that out, something to do with wrap around
charx = ((hdmix >> (SCALE-1)) - 1) % 8;
chary = (hdmiy >> (SCALE-1)) % 8; chary = (hdmiy >> (SCALE-1)) % 8;
if (char_index_q < 3600 && charx > 0 && charx < 6 && chary > 1 && char_data[sram_read_data][29 - (charx - 1) - 5*(chary - 2)] == 1) begin if (charx > 0 && charx < 6 && chary > 1 && char_data[sram_read_data][29 - (charx - 1) - 5*(chary - 2)] == 1) begin
hdmired = 8'hEB; hdmired = 8'hFF;
hdmigreen = 8'hDB; hdmigreen = 8'hFF;
hdmiblue = 8'hB2; hdmiblue = 8'hFF;
end end
frame_d = frame_q; frame_d = frame_q;
char_index_d = ((hdmix >> (SCALE+2)) + 80*(hdmiy >> (SCALE+2))); char_index_d = ((hdmix >> (SCALE+2)) + CHAR_HMAX*(hdmiy >> (SCALE+2)));
if (hdmix == 1279 && hdmiy == 719) begin if (hdmix == WIDTH-1 && hdmiy == HEIGHT-1) begin
frame_d = frame_q + 1'b1; frame_d = frame_q + 1'b1;
end end
@ -228,9 +239,8 @@ module mojo_top(
tx_data = rx_data; tx_data = rx_data;
if (rx_data == "\r") begin if (rx_data == "\r") begin
addr_d = addr_q - (addr_q % 80);
end else if (rx_data == "\n") begin end else if (rx_data == "\n") begin
addr_d = addr_q + 80; addr_d = addr_q - (addr_q % CHAR_HMAX) + CHAR_HMAX;
end else if (rx_data == 8) begin end else if (rx_data == 8) begin
addr_d = addr_q - 1'b1; addr_d = addr_q - 1'b1;
end else begin end else begin