Subversion Repositories pentevo

Rev

Rev 1063 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // ZX-Evo SDLoad Configuration (c) NedoPC 2023
  2. //
  3. // video sync module
  4.  
  5. /*
  6.     This file is part of ZX-Evo Base Configuration firmware.
  7.  
  8.     ZX-Evo Base Configuration firmware is free software:
  9.     you can redistribute it and/or modify it under the terms of
  10.     the GNU General Public License as published by
  11.     the Free Software Foundation, either version 3 of the License, or
  12.     (at your option) any later version.
  13.  
  14.     ZX-Evo Base Configuration firmware is distributed in the hope that
  15.     it will be useful, but WITHOUT ANY WARRANTY; without even
  16.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17.     See the GNU General Public License for more details.
  18.  
  19.     You should have received a copy of the GNU General Public License
  20.     along with ZX-Evo Base Configuration firmware.
  21.     If not, see <http://www.gnu.org/licenses/>.
  22. */
  23.  
  24. module video_sync
  25. (
  26.         input  wire clk,
  27.         input  wire rst_n,
  28.  
  29.         input  wire vga_on,
  30.         input  wire hsync_polarity, // 1 - positive polarity, 0 - negative
  31.         input  wire vsync_polarity, //
  32.  
  33.         // pixel strobe -- everything happens enabled by this signal
  34.         output reg  pix_stb,
  35.  
  36.         // initial sync signals
  37.         output reg  i_hsync,
  38.         output reg  i_vsync,
  39.         output reg  i_hpix,
  40.         output reg  i_vpix,
  41.  
  42.         // fetch synchronizing signals
  43.         output reg  v_init, // prepare fetching whole screen
  44.         output reg  v_step, // step to the next screen line
  45.         output reg  v_char, // step to the next char line
  46.        
  47.         output reg  h_init, // prepare fetching/displaying single line
  48.         output reg  h_char  // strobes 6 pix_stb's before the pix_stb that begins h_pix,
  49.                             // then continues throughout the visible area. Ends also 6 pix_stb's
  50.                             // before the end of h_pix
  51. );
  52.  
  53.         parameter H_PERIOD = 9'd448; // in 7MHz clock
  54.         //
  55.         parameter H_TV_SYNC_END  = 9'd33; // counting starts with HSYNC going active
  56.         parameter H_TV_PIX_START = 9'd78;
  57.         parameter H_TV_PIX_STOP  = 9'd438;
  58.         //
  59.         parameter H_VGA_SYNC_END  = 9'd53;
  60.         parameter H_VGA_PIX_START = 9'd79;
  61.         parameter H_VGA_PIX_STOP  = 9'd439;
  62.  
  63.  
  64.         parameter V_PERIOD = 9'd262; // in 15625Hz clock
  65.         //
  66.         parameter V_SYNC_END = 9'd2; // in TV mode, must be a little longer than exact 2 HSYNC periods. Addition is 78 7MHz clocks
  67.         parameter V_PIX_START = 9'd18;
  68.         parameter V_PIX_STOP  = 9'd258;
  69.  
  70.  
  71.         reg [1:0] pix_divider = 2'b0;
  72.  
  73.  
  74.         reg [8:0] h_counter = 9'd0;
  75.  
  76.  
  77.         reg v_div2 = 1'b0;
  78.  
  79.         reg [8:0] v_counter = 9'd0;
  80.  
  81.        
  82.  
  83.  
  84.         // pixel clock strobes
  85.         always @(posedge clk)
  86.                 pix_divider[1:0] <= { pix_divider[0], ~pix_divider[1] };
  87.         //
  88.         always @(posedge clk)
  89.                 pix_stb <= vga_on ? (~^pix_divider) : (&pix_divider);
  90.  
  91.  
  92.  
  93.         // horizontal counter: counts from 1 to 448
  94.         wire h_count_end = &h_counter[8:6]; // 448 is 0x1C0
  95.         //
  96.         always @(posedge clk)
  97.         if( pix_stb )
  98.         begin
  99.                 if( h_count_end )
  100.                         h_counter <= 9'd1;
  101.                 else
  102.                         h_counter <= h_counter + 9'd1;
  103.         end
  104.  
  105.         // hsync on/off
  106.         wire hsync_on  = h_count_end;
  107.         wire hsync_off = vga_on ? (h_counter==H_VGA_SYNC_END) : (h_counter==H_TV_SYNC_END);
  108.  
  109.         // hpix on/off
  110.         wire hpix_on  = vga_on ? (h_counter==H_VGA_PIX_START) : (h_counter==H_TV_PIX_START);
  111.         wire hpix_off = vga_on ? (h_counter==H_VGA_PIX_STOP) : (h_counter==H_TV_PIX_STOP);
  112.  
  113.  
  114.         // skip every second vertical count in vga mode
  115.         always @(posedge clk)
  116.         if( pix_stb && h_count_end )
  117.                 v_div2 <= vga_on ? (~v_div2) : 1'b1;
  118.  
  119.         // vertical count strobe
  120.         wire v_stb = pix_stb & h_count_end & v_div2;
  121.  
  122.         // vertical counter: from 1 to 262
  123.         wire v_count_end = v_counter[8] & (&v_counter[2:1]); // 262 is 0x106
  124.         //
  125.         always @(posedge clk)
  126.         if( v_stb )
  127.         begin
  128.                 if( v_count_end )
  129.                         v_counter <= 9'd1;
  130.                 else
  131.                         v_counter <= v_counter + 9'd1;
  132.         end
  133.  
  134.         // vsync on/off
  135.         wire vsync_on  = v_count_end;
  136.         wire vsync_off = (v_counter==V_SYNC_END);
  137.  
  138.         // vpix on/off
  139.         wire vpix_on  = (v_counter==V_PIX_START);
  140.         wire vpix_off = (v_counter==V_PIX_STOP);
  141.  
  142.  
  143.         // make initial sync signals
  144.         always @(posedge clk)
  145.         if( pix_stb )
  146.         begin
  147.                 if( hsync_on )
  148.                         i_hsync <= hsync_polarity;
  149.                 else if( hsync_off )
  150.                         i_hsync <= ~hsync_polarity;
  151.  
  152.                 if( hpix_on )
  153.                         i_hpix <= 1'b1;
  154.                 else if( hpix_off )
  155.                         i_hpix <= 1'b0;
  156.         end
  157.         //
  158.         // vsync in tv mode must be 78 pix_stb's longer
  159.         reg [7:0] extra_vsync_count;
  160.         reg       extra_vsync_count_r;
  161.         always @(posedge clk)
  162.         if( v_stb && vsync_off )
  163.                         extra_vsync_count <= 8'd77 + 8'h80;
  164.         else if( pix_stb && extra_vsync_count[7] )
  165.                         extra_vsync_count <= extra_vsync_count - 8'd1;
  166.         //
  167.         always @(posedge clk)
  168.         if( pix_stb )
  169.                 extra_vsync_count_r <= extra_vsync_count[7];
  170.         //
  171.         always @(posedge clk)
  172.         begin
  173.                 if( v_stb && vsync_on )
  174.                         i_vsync <= vsync_polarity;
  175.                 else if( vga_on ? (v_stb && vsync_off) : (pix_stb && extra_vsync_count_r && !extra_vsync_count[7]) )
  176.                         i_vsync <= ~vsync_polarity;
  177.         end
  178.         //
  179.         always @(posedge clk)
  180.         if( v_stb )
  181.         begin
  182.                 if( vpix_on )
  183.                         i_vpix <= 1'b1;
  184.                 else if( vpix_off )
  185.                         i_vpix <= 1'b0;
  186.         end
  187.  
  188.  
  189.  
  190.         // vertical fetch syncs
  191.  
  192.         always @(posedge clk)
  193.         if( pix_stb )
  194.         begin
  195.                 if( v_stb && vsync_off )
  196.                         v_init <= 1'b1;
  197.                 else
  198.                         v_init <= 1'b0;
  199.         end
  200.  
  201.  
  202.         reg [2:0] vctr_6;
  203.         always @(posedge clk)
  204.         if( pix_stb )
  205.         begin
  206.                 if( ?? )
  207.                         vctr_6
  208.                 else if( v_stb )
  209.                         vctr_6 <= (vctr_6[2] & vctr_6[0]) ? 3'd0 : (vctr_6 + 3'd1);
  210.         end
  211.  
  212.  
  213.         always @(posedge clk)
  214.         if( pix_stb )
  215.         begin
  216.                 if( i_vpix && v_stb )
  217.                         v_step <= 1'b1;
  218.                 else
  219.                         v_step <= 1'b0;
  220.         end
  221.        
  222.  
  223.  
  224.  
  225.         // horizontal fetch syncs
  226.  
  227.         always @(posedge clk)
  228.         if( pix_stb )
  229.         begin
  230.                 if( hsync_off )
  231.                         h_init <= 1'b1;
  232.                 else
  233.                         h_init <= 1'b0;
  234.         end
  235.  
  236.        
  237.         wire start_char = vga_on ? (h_counter==(H_VGA_PIX_START-7)) : (h_counter==(H_TV_PIX_START-7));
  238.         wire stop_char  = vga_on ? (h_counter==(H_VGA_PIX_STOP -7)) : (h_counter==(H_TV_PIX_STOP -7));
  239.  
  240.         reg char;
  241.         always @(posedge clk)
  242.         if( pix_stb )
  243.                 if( start_char )
  244.                         char <= 1'b1;
  245.                 else if( stop_char )
  246.                         char <= 1'b0;
  247.  
  248.         // MOD 6 counter
  249.         reg [2:0] char_ctr;
  250.         //
  251.         always @(posedge clk)
  252.         if( pix_stb )
  253.         begin
  254.                 if( start_char )
  255.                         char_ctr <= 3'd0;
  256.                 else
  257.                         char_ctr <= (char_ctr[2] & char_ctr[0]) ? 3'd0 : (char_ctr + 3'd1);
  258.         end
  259.         //
  260.  
  261.         //
  262.         always @(posedge clk)
  263.         if( pix_stb )
  264.         begin
  265.                 if( start_char )
  266.                         h_char <= 1'b1;
  267.                 else if( char && (char_ctr[2] & char_ctr[0]) )
  268.                         h_char <= 1'b1;
  269.                 else
  270.                         h_char <= 1'b0;
  271.         end
  272.  
  273.  
  274.  
  275.  
  276. endmodule
  277.  
  278.