// // Copyright (C) 2015-2019 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //`define DEBUG `define PO_RESET_WIDTH 27 //1us module ossc ( input clk27, input ir_rx, inout scl, inout sda, input [1:0] btn, input [7:0] R_in, input [7:0] G_in, input [7:0] B_in, input FID_in, input VSYNC_in, input HSYNC_in, input PCLK_in, output HDMI_TX_PCLK, output reg [7:0] HDMI_TX_RD, output reg [7:0] HDMI_TX_GD, output reg [7:0] HDMI_TX_BD, output reg HDMI_TX_DE, output reg HDMI_TX_HS, output reg HDMI_TX_VS, input HDMI_TX_INT_N, input HDMI_TX_MODE, output hw_reset_n, output LED_G, output LED_R, output LCD_RS, output LCD_CS_N, output LCD_BL, output SD_CLK, inout SD_CMD, inout [3:0] SD_DAT ); wire [15:0] sys_ctrl; wire h_unstable, pll_lock_lost; wire [31:0] h_config, h_config2, v_config, misc_config, sl_config, sl_config2; wire [10:0] vmax, vmax_tvp; wire [1:0] fpga_vsyncgen; wire ilace_flag, vsync_flag; wire [19:0] pcnt_frame; wire [15:0] ir_code; wire [7:0] ir_code_cnt; wire [7:0] R_out_sc, G_out_sc, B_out_sc; wire HSYNC_out_sc; wire VSYNC_out_sc; wire PCLK_out; wire DE_out_sc; wire [7:0] R_out_vg, G_out_vg, B_out_vg; wire HSYNC_out_vg; wire VSYNC_out_vg; wire DE_out_vg; reg [7:0] po_reset_ctr = 0; reg po_reset_n = 1'b0; wire jtagm_reset_req; wire sys_reset_n = (po_reset_n & ~jtagm_reset_req); reg [7:0] R_in_L, G_in_L, B_in_L; reg HSYNC_in_L, VSYNC_in_L, FID_in_L; reg [1:0] btn_L, btn_LL; reg ir_rx_L, ir_rx_LL, HDMI_TX_INT_N_L, HDMI_TX_INT_N_LL, HDMI_TX_MODE_L, HDMI_TX_MODE_LL; wire lt_sensor = btn_LL[1]; wire lt_active = sys_ctrl[15]; wire lt_armed = sys_ctrl[14]; wire lt_trigger = HDMI_TX_DE & HDMI_TX_GD[0]; wire [1:0] lt_mode = sys_ctrl[13:12]; wire [1:0] lt_mode_synced; wire [15:0] lt_lat_result; wire [11:0] lt_stb_result; wire lt_trig_waiting; wire lt_finished; wire remote_event = sys_ctrl[8]; reg remove_event_prev; reg [14:0] to_ctr, to_ctr_ms; wire lcd_bl_timeout; wire [1:0] osd_color; wire osd_enable_pre; wire osd_enable = osd_enable_pre & ~lt_active; wire [10:0] xpos, xpos_sc, xpos_vg; wire [10:0] ypos, ypos_sc, ypos_vg; wire pll_areset, pll_scanclk, pll_scanclkena, pll_configupdate, pll_scandata, pll_scandone, pll_activeclock; // Latch inputs from TVP7002 (synchronized to PCLK_in) always @(posedge PCLK_in or negedge hw_reset_n) begin if (!hw_reset_n) begin R_in_L <= 8'h00; G_in_L <= 8'h00; B_in_L <= 8'h00; HSYNC_in_L <= 1'b0; VSYNC_in_L <= 1'b0; FID_in_L <= 1'b0; end else begin R_in_L <= R_in; G_in_L <= G_in; B_in_L <= B_in; HSYNC_in_L <= HSYNC_in; VSYNC_in_L <= VSYNC_in; FID_in_L <= FID_in; end end // Insert synchronizers to async inputs (synchronize to CPU clock) always @(posedge clk27 or negedge po_reset_n) begin if (!po_reset_n) begin btn_L <= 2'b00; btn_LL <= 2'b00; ir_rx_L <= 1'b0; ir_rx_LL <= 1'b0; HDMI_TX_INT_N_L <= 1'b0; HDMI_TX_INT_N_LL <= 1'b0; HDMI_TX_MODE_L <= 1'b0; HDMI_TX_MODE_LL <= 1'b0; end else begin btn_L <= btn; btn_LL <= btn_L; ir_rx_L <= ir_rx; ir_rx_LL <= ir_rx_L; HDMI_TX_INT_N_L <= HDMI_TX_INT_N; HDMI_TX_INT_N_LL <= HDMI_TX_INT_N_L; HDMI_TX_MODE_L <= HDMI_TX_MODE; HDMI_TX_MODE_LL <= HDMI_TX_MODE_L; end end // Power-on reset pulse generation (not strictly necessary) always @(posedge clk27) begin if (po_reset_ctr == `PO_RESET_WIDTH) po_reset_n <= 1'b1; else po_reset_ctr <= po_reset_ctr + 1'b1; end assign hw_reset_n = sys_ctrl[0]; //HDMI_TX_RST_N in v1.2 PCB `ifdef DEBUG assign LED_R = HSYNC_in_L; assign LED_G = VSYNC_in_L; `else assign LED_R = lt_active ? lt_trig_waiting : (pll_lock_lost|h_unstable); assign LED_G = lt_active ? ~lt_sensor : (ir_code == 0); `endif assign SD_DAT[3] = sys_ctrl[7]; //SD_SPI_SS_N assign LCD_CS_N = sys_ctrl[6]; assign LCD_RS = sys_ctrl[5]; wire lcd_bl_on = sys_ctrl[4]; //hw_reset_n in v1.2 PCB wire [1:0] lcd_bl_time = sys_ctrl[3:2]; assign LCD_BL = lcd_bl_on ? (~lcd_bl_timeout | lt_active) : 1'b0; wire enable_sc = sys_ctrl[1]; assign xpos = enable_sc ? xpos_sc : xpos_vg; assign ypos = enable_sc ? ypos_sc : ypos_vg; assign HDMI_TX_PCLK = PCLK_out; always @(posedge PCLK_out) begin if (osd_enable) begin if (osd_color == 2'h0) begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= 24'h000000; end else if (osd_color == 2'h1) begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= 24'h0000ff; end else if (osd_color == 2'h2) begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= 24'hffff00; end else begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= 24'hffffff; end end else if (enable_sc) begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= {R_out_sc, G_out_sc, B_out_sc}; end else begin {HDMI_TX_RD, HDMI_TX_GD, HDMI_TX_BD} <= {R_out_vg, G_out_vg, B_out_vg}; end HDMI_TX_HS <= enable_sc ? HSYNC_out_sc : HSYNC_out_vg; HDMI_TX_VS <= enable_sc ? VSYNC_out_sc : VSYNC_out_vg; HDMI_TX_DE <= enable_sc ? DE_out_sc : DE_out_vg; end // LCD backlight timeout counters always @(posedge clk27) begin if (remote_event != remove_event_prev) begin to_ctr <= 15'd0; to_ctr_ms <= 15'd0; end else begin if (to_ctr == 27000-1) begin to_ctr <= 0; if (to_ctr_ms < 15'h7fff) to_ctr_ms <= to_ctr_ms + 1'b1; end else begin to_ctr <= to_ctr + 1'b1; end end case (lcd_bl_time) default: lcd_bl_timeout <= 0; //off 2'b01: lcd_bl_timeout <= (to_ctr_ms >= 3000); //3s 2'b10: lcd_bl_timeout <= (to_ctr_ms >= 10000); //10s 2'b11: lcd_bl_timeout <= (to_ctr_ms >= 30000); //30s endcase remove_event_prev <= remote_event; end sys sys_inst( .clk_clk (clk27), .reset_reset_n (sys_reset_n), .pulpino_0_config_testmode_i (1'b0), .pulpino_0_config_fetch_enable_i (1'b1), .pulpino_0_config_clock_gating_i (1'b0), .pulpino_0_config_boot_addr_i (32'h00010000), .master_0_master_reset_reset (jtagm_reset_req), .i2c_opencores_0_export_scl_pad_io (scl), .i2c_opencores_0_export_sda_pad_io (sda), .i2c_opencores_0_export_spi_miso_pad_i (1'b0), .i2c_opencores_1_export_scl_pad_io (SD_CLK), .i2c_opencores_1_export_sda_pad_io (SD_CMD), .i2c_opencores_1_export_spi_miso_pad_i (SD_DAT[0]), .pio_0_sys_ctrl_out_export (sys_ctrl), .pio_1_controls_in_export ({ir_code_cnt, 4'b0000, pll_activeclock, HDMI_TX_MODE_LL, btn_LL, ir_code}), .sc_config_0_sc_if_sc_status_i ({vsync_flag, 2'b00, vmax_tvp, fpga_vsyncgen, 4'h0, ilace_flag, vmax}), .sc_config_0_sc_if_sc_status2_i ({12'h000, pcnt_frame}), .sc_config_0_sc_if_lt_status_i ({lt_finished, 3'h0, lt_stb_result, lt_lat_result}), .sc_config_0_sc_if_h_config_o (h_config), .sc_config_0_sc_if_h_config2_o (h_config2), .sc_config_0_sc_if_v_config_o (v_config), .sc_config_0_sc_if_misc_config_o (misc_config), .sc_config_0_sc_if_sl_config_o (sl_config), .sc_config_0_sc_if_sl_config2_o (sl_config2), .osd_generator_0_osd_if_vclk (PCLK_out), .osd_generator_0_osd_if_xpos (xpos), .osd_generator_0_osd_if_ypos (ypos), .osd_generator_0_osd_if_osd_enable (osd_enable_pre), .osd_generator_0_osd_if_osd_color (osd_color), .pll_reconfig_0_pll_reconfig_if_areset (pll_areset), .pll_reconfig_0_pll_reconfig_if_scanclk (pll_scanclk), .pll_reconfig_0_pll_reconfig_if_scanclkena (pll_scanclkena), .pll_reconfig_0_pll_reconfig_if_configupdate (pll_configupdate), .pll_reconfig_0_pll_reconfig_if_scandata (pll_scandata), .pll_reconfig_0_pll_reconfig_if_scandone (pll_scandone) ); scanconverter scanconverter_inst ( .reset_n (hw_reset_n), .PCLK_in (PCLK_in), .clk27 (clk27), .enable_sc (enable_sc), .HSYNC_in (HSYNC_in_L), .VSYNC_in (VSYNC_in_L), .FID_in (FID_in_L), .R_in (R_in_L), .G_in (G_in_L), .B_in (B_in_L), .h_config (h_config), .h_config2 (h_config2), .v_config (v_config), .misc_config (misc_config), .sl_config (sl_config), .sl_config2 (sl_config2), .R_out (R_out_sc), .G_out (G_out_sc), .B_out (B_out_sc), .PCLK_out (PCLK_out), .HSYNC_out (HSYNC_out_sc), .VSYNC_out (VSYNC_out_sc), .DE_out (DE_out_sc), .h_unstable (h_unstable), .fpga_vsyncgen (fpga_vsyncgen), .pll_lock_lost (pll_lock_lost), .vmax (vmax), .vmax_tvp (vmax_tvp), .pcnt_frame (pcnt_frame), .ilace_flag (ilace_flag), .vsync_flag (vsync_flag), .lt_active (lt_active), .lt_mode (lt_mode_synced), .xpos (xpos_sc), .ypos (ypos_sc), .pll_areset (pll_areset), .pll_scanclk (pll_scanclk), .pll_scanclkena (pll_scanclkena), .pll_configupdate (pll_configupdate), .pll_scandata (pll_scandata), .pll_scandone (pll_scandone), .pll_activeclock (pll_activeclock) ); ir_rcv ir0 ( .clk27 (clk27), .reset_n (po_reset_n), .ir_rx (ir_rx_LL), .ir_code (ir_code), .ir_code_ack (), .ir_code_cnt (ir_code_cnt) ); lat_tester lt0 ( .clk27 (clk27), .pclk (PCLK_out), .active (lt_active), .armed (lt_armed), .sensor (lt_sensor), .trigger (lt_trigger), .VSYNC_in (HDMI_TX_VS), .mode_in (lt_mode), .mode_synced (lt_mode_synced), .lat_result (lt_lat_result), .stb_result (lt_stb_result), .trig_waiting (lt_trig_waiting), .finished (lt_finished) ); videogen vg0 ( .clk27 (PCLK_out), .reset_n (po_reset_n & ~enable_sc), .lt_active (lt_active), .lt_mode (lt_mode_synced), .R_out (R_out_vg), .G_out (G_out_vg), .B_out (B_out_vg), .HSYNC_out (HSYNC_out_vg), .VSYNC_out (VSYNC_out_vg), .DE_out (DE_out_vg), .xpos (xpos_vg), .ypos (ypos_vg) ); endmodule