diff --git a/HDMI.alp b/HDMI.alp
index 7a7e8f2..668f553 100644
--- a/HDMI.alp
+++ b/HDMI.alp
@@ -1,25 +1,25 @@
-
-
-
- cclk_detector.luc
- simple_dual_ram.v
- async_fifo.luc
- uart_rx.luc
- fifo_2x_reducer.luc
- tmds_encoder.luc
- spi_slave.luc
- mojo_top.v
- serdes_n_to_1.luc
- uart_tx.luc
- dvi_encoder.luc
- hdmi_encoder.luc
- sram.v
- dvi_globals.luc
- avr_interface.luc
- hdmi.ucf
- mojo.ucf
-
- ..\clk_wiz_v3_6.v
-
-
-
+
+
+
+ hdmi_encoder.luc
+ mojo_top.v
+ uart_rx.luc
+ sram.v
+ fifo_2x_reducer.luc
+ dvi_globals.luc
+ avr_interface.luc
+ dvi_encoder.luc
+ spi_slave.luc
+ uart_tx.luc
+ serdes_n_to_1.luc
+ simple_dual_ram.v
+ async_fifo.luc
+ cclk_detector.luc
+ tmds_encoder.luc
+ mojo.ucf
+ hdmi.ucf
+
+ ..\clk_wiz_v3_6.v
+
+
+
diff --git a/source/hdmi_encoder.luc b/source/hdmi_encoder.luc
new file mode 100644
index 0000000..f8c5ef8
--- /dev/null
+++ b/source/hdmi_encoder.luc
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/source/mojo_top.v b/source/mojo_top.v
index f8e4c1b..0096c2c 100644
--- a/source/mojo_top.v
+++ b/source/mojo_top.v
@@ -27,8 +27,8 @@ module mojo_top(
wire hdmi_clk;
reg[7:0] hdmired, hdmigreen, hdmiblue;
- wire[10:0] hdmix;
- wire[9:0] hdmiy;
+ wire[11:0] hdmix;
+ wire[10:0] hdmiy;
reg[7:0] frame_q, frame_d;
@@ -36,8 +36,18 @@ module mojo_top(
.CLK_IN1(clk),
.CLK_OUT1(hdmi_clk)
);
+
+ 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);
- hdmi_encoder hdmi(
+ // @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),
.rst(rst),
.tmds(hdmi1_tmds),
@@ -147,13 +157,11 @@ module mojo_top(
assign char_data[93] = 30'h610C46; // }
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[9:0] chary;
- localparam SCALE = 2;
-
reg[7:0] tx_data;
reg new_tx_data;
wire tx_busy;
@@ -185,11 +193,11 @@ module mojo_top(
.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 write_enable;
wire[7:0] sram_read_data;
- sram #(.SIZE(8), .DEPTH(3600)) sram(
+ sram #(.SIZE(8), .DEPTH(CHAR_HMAX*CHAR_VMAX)) sram(
.clk(hdmi_clk),
.read_address(char_index_q),
.write_address(addr_q),
@@ -199,23 +207,26 @@ module mojo_top(
);
always @(*) begin
- hdmired = 1'h28;
- hdmigreen = 1'h28;
- hdmiblue = 1'h28;
+ hdmired = 1'b0;
+ hdmigreen = 1'b0;
+ 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;
- if (char_index_q < 3600 && charx > 0 && charx < 6 && chary > 1 && char_data[sram_read_data][29 - (charx - 1) - 5*(chary - 2)] == 1) begin
- hdmired = 8'hEB;
- hdmigreen = 8'hDB;
- hdmiblue = 8'hB2;
+ if (charx > 0 && charx < 6 && chary > 1 && char_data[sram_read_data][29 - (charx - 1) - 5*(chary - 2)] == 1) begin
+ hdmired = 8'hFF;
+ hdmigreen = 8'hFF;
+ hdmiblue = 8'hFF;
end
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;
end
@@ -228,9 +239,8 @@ module mojo_top(
tx_data = rx_data;
if (rx_data == "\r") begin
- addr_d = addr_q - (addr_q % 80);
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
addr_d = addr_q - 1'b1;
end else begin