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