⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga_controller.pm

📁 altera的ip核
💻 PM
📖 第 1 页 / 共 3 页
字号:
  });
  e_register->add({
    out => {name => "fifo_has_data", export => 0,},
    in => "fifo_has_data_reg1",
    clock => "vga_clk",
    enable => 1,
  });

	
  ################################################################
  #               THIS IS THE DMA ADDRESS COUNTER                #
  ################################################################

  e_blind_instance->add({
     tag            => 'normal',
     use_sim_models => 1,
     name           => 'dma_address_counter',
     module         => 'lpm_counter',
     in_port_map    => {clock => "clk",
                        aclr => "!reset_n",
                        cnt_en => "address_counter_incr",
                        sload => "address_counter_sload",
                        data => "dma_source_reg[31:2]",},
     out_port_map   => {"q", "address_counter_temp"},
     parameter_map  => {LPM_WIDTH => "30"},
  });

  e_signal->add({name => "address_counter_temp", width => 30,});
  e_signal->add({name => "address_counter", width => 32,});
  e_assign->add (["address_counter_incr", "(master_read == 1) && (master_waitrequest == 0) && (go_bit == 1)"]);
  e_assign->add (["address_counter_sload", "(go_bit == 0) ||(address_counter_incr && (address_counter == last_dma_addr_reg))"]);
  e_assign->add (["address_counter", "{address_counter_temp, 2'b00}"]);

  # Register the DMA end address too, since the sw driver can change the 
  # dma_source_reg register on which it depends during a buffer flip.
  e_register->add({
    out => {name => "last_dma_addr_reg", width => $SBI_slave->{Data_Width}, export => 0,},
    in => "(dma_source_reg + dma_modulus_reg - 4)",
    enable => "address_counter_sload",
  });


  ################################################################
  #                THIS IS THE VGA COLUMN COUNTER                #
  ################################################################
  
  my $column_counter_width = ceil(log2($HSCAN_WIDTH));

  e_blind_instance->add({
     tag            => 'normal',
     use_sim_models => 1,
     name           => 'vga_column_counter',
     module         => 'lpm_counter',
     in_port_map    => {clock => "vga_clk",
                        aclr => "!reset_n",
                        cnt_en => "vga_start",
                        sclr => "!vga_start"},
     out_port_map   => {"q", "column_counter",},
     parameter_map  => {LPM_WIDTH => "$column_counter_width",
                        LPM_MODULUS => "$HSCAN_WIDTH"},
  });

  e_signal->add({name => "column_counter", width => "$column_counter_width",});

  # Temporary for debug
  #e_port->add({name => "column_counter", width => 10, direction => "output", });


  ################################################################
  #               THIS IS THE VGA ROW COUNTER                    #
  ################################################################

  my $row_counter_width = ceil(log2($VSCAN_DEPTH));

  e_blind_instance->add({
     tag            => 'normal',
     use_sim_models => 1,
     name           => 'vga_row_counter',
     module         => 'lpm_counter',
     in_port_map    => {clock => "vga_clk",
                        aclr => "!reset_n",
                        cnt_en => "vga_start && (column_counter == ($HSCAN_WIDTH - 1))",
                        sclr => "!vga_start",},
     out_port_map   => {"q", "row_counter",},
     parameter_map  => {LPM_WIDTH => "$row_counter_width",
                        LPM_MODULUS => "$VSCAN_DEPTH"},
  });

  e_signal->add({name => "row_counter", width => "$row_counter_width",});

  # Temporary for debug
  #e_port->add({name => "row_counter", width => 10, direction => "output", });


  ################################################################
  #                  THIS IS THE VGA INIT LOGIC                  #
  ################################################################

  # We need to wait until everything's set up before we release
  # the fury of the go bit. Also, if the fifo loses sync during normal
  # operation, we drive the go_bit low again.
  e_register->add({
    out => {name => "go_bit", export => 0,},
    in => "ctrl_reg_go_bit & stop_config_counter & fifo_emptied",
    enable => 1,
  });

  # This is a config counter that we decode below for the VGA init sequence
  e_signal->add({name => "config_counter", width => 3,});
  e_assign->add (["stop_config_counter", "config_counter == 3'b101"]);
  e_blind_instance->add({
     tag            => 'normal',
     use_sim_models => 1,
     name           => 'vga_config_counter',
     module         => 'lpm_counter',
     in_port_map    => {clock => "vga_clk",
                        aclr => "!reset_n",
                        cnt_en => "!stop_config_counter",},
     out_port_map   => {"q", "config_counter"},
     parameter_map  => {LPM_WIDTH => "3"},
  });

  # This gives us a config sequence for the VGA DAC. The sequence is as follows:
  # sync_n -> 0-1-0-0-1-1
  # sync_t -> 0-0-0-0-0-0
  # M1     -> 0-0-0-0-0-0
  # M2     -> 0-0-1-1-0-0
  e_register->add({
    out => {name => "sync_n_init", export => 0,},
    in => "(config_counter[2] | (config_counter[0] & !config_counter[1]))",
    clock => "vga_clk",
    enable => 1,
  });
  e_register->add({
    out => {name => "M2", export => 1,},
    in => "config_counter[1]",
    clock => "vga_clk",
    enable => 1,
  });

  e_assign->add (["M1", 0]);

  # This holds the fifo read_req signal high until the thing's empty.  Used for bring-up
  # and disaster recovery.
  e_register->add({
    out => {name => "fifo_emptied", export => 0,},
    in => "(ctrl_reg_go_bit & (fifo_emptied | fifo_rdempty))",
    clock => "vga_clk",
    enable => 1,
  });
  e_assign->add (["empty_the_fifo", "!fifo_emptied"]);


  ################################################################
  #              THIS IS THE VGA CONTROL LOGIC                   #
  ################################################################

  # This is a version of the go bit in the control register, but here, it's
  # double-registered on the 25MHz clock to sync it up.  We'll use it in our
  # logic that determines when we're all set to start the VGA sequencer
  e_register->add({
    out => {name => "go_bit_vga_reg1", export => 0,},
    in => "go_bit",
    clock => "vga_clk",
    enable => 1,
  });
  e_register->add({
    out => {name => "go_bit_vga", export => 0,},
    in => "go_bit_vga_reg1",
    clock => "vga_clk",
    enable => 1,
  });

  # This signals when we're okay to start the VGA sequencer
  e_register->add({
    out => {name => "vga_start", export => 0,},
    in => "(vga_start & go_bit_vga) | (fifo_has_data & go_bit_vga)",
    clock => "vga_clk",
    enable => 1,
  });
  
	# If the color depth is 16-bits, we just use a mux to pull 16 bits at a 
	#time out of the fifo's 32 bit output
	if($WSA->{color_depth} eq "16")
	{
	  # This is the data splitter mux.  We get data out of the fifo as 32-bit
  	# words.  Only we need 16-bit words.  So we time-div-mux it with a toggling flip flop
  	# and only do a real read of the fifo every other cycle.
  	e_signal->add({name => "vga_16bit_out", width => 16,});
  	e_assign->add (["vga_16bit_out", "mux_toggle ? fifo_data_out[31:16] : fifo_data_out[15:0]"]);


  	# And the mux toggler flip flop
  	e_register->add({
  	  out => {name => "mux_toggle", export => 0,},
  	  in => "(!mux_toggle) & (read_16b)",
  	  clock => "vga_clk",
  	  enable => 1,
  	  async_value => 0,
  	});

  	# The read request that actually goes to the fifo is essentially the output
  	# of the mux toggler.  We also or-in a read signal that empties the fifo during
  	# the init sequence.
  	e_assign->add (["fifo_read_req", "((mux_toggle & read_16b) | empty_the_fifo)"]);
  	
		# Here, we issue a 16-bit read whenever we're not blanking the VGA.
	 	# We already have logic that holds off the VGA sequencer until we
	 	# know there is data in the fifo.  And since hblank and vblank are
	 	# created by the sequencer, they wont go high until the fifo's got
	 	# data to read
	 	e_assign->add (["read_16b", "hblank & vblank"]);

	  # The read signal is also our active signal, so we'll give it a
	  # descriptive name.
	  e_assign->add (["display_active", "read_16b"]);


	  # This splits up the 16-bit data into RGB.
	  e_port->add({name => "R", width => 8, direction => "output", });
	  e_register->add({
	    out => {name => "R", export => 1,},
	    in => "display_active ? ({vga_16bit_out[15:11], 3'b111}) : 8'b00000000",
	    clock => "vga_clk",
	    enable => 1,
	  });
	  e_port->add({name => "G", width => 8, direction => "output", });
	  e_register->add({
	    out => {name => "G", export => 1,},
	    in => "display_active ? ({vga_16bit_out[10:5], 2'b11}) : 8'b00000000",
	    clock => "vga_clk",
	    enable => 1,
	  });
	  e_port->add({name => "B", width => 8, direction => "output", });
	  e_register->add({
	    out => {name => "B", export => 1,},
	    in => "display_active ? ({vga_16bit_out[4:0], 3'b111}) : 8'b00000000",
	    clock => "vga_clk",
	    enable => 1,
	  });
  	
	}
	
	# If the color depth is 24 bits packed, our muxing is a little more complicated.
	# Every set of 3 32-bit words contains 4 24-bit pixels
	if($WSA->{color_depth} eq "24")
	{
		# This stores the fifo output for one extra cycle because sometimes pieces of 
		# our 24-bit pixels need to be picked out of the previous 32-bit word.
	  e_register->add({
	    out => {name => "prev_fifo_data_out", width => "32", export => 0,},
	    in => "fifo_data_out",
   	  clock => "vga_clk",
	    enable => "fifo_read_req",
	  });

  	# This is the mux counter.  Every time we pull out 24-bits, our byte offset changes.
  	# This counter is here to keep track of what that byte-offset is so we always get 
  	# the proper 24-bits
  	e_signal->add({name => "pixel_mux_counter", width => 2,});
  	e_blind_instance->add({
  	   tag            => 'normal',
  	   use_sim_models => 1,
  	   name           => 'vga_pixel_mux_counter',
  	   module         => 'lpm_counter',
  	   in_port_map    => {clock => "vga_clk",
  	                      aclr => "!reset_n",
  	                      cnt_en => "read_24b",
	                        sclr => "!go_bit_vga",},  	                      
  	   out_port_map   => {"q", "pixel_mux_counter"},
  	   parameter_map  => {LPM_WIDTH => "2"},
  	});

		# Here, we issue a 24-bit read whenever we're not blanking the VGA.
	 	# We already have logic that holds off the VGA sequencer until we
	 	# know there is data in the fifo.  And since hblank and vblank are
	 	# created by the sequencer, they wont go high until the fifo's got
	 	# data to read
	 	e_assign->add (["read_24b", "hblank & vblank"]);

	  # The read signal is also our active signal, so we'll give it a
	  # descriptive name.
	  e_assign->add (["display_active", "read_24b"]);

  	# The fifo skips a read once every 3 words (4 pixels)
  	e_assign->add (["fifo_read_req", "(((pixel_mux_counter != 3) & read_24b) | empty_the_fifo)"]);

	  # This is the data splitter mux.  We get data out of the fifo as 32-bit
  	# words.  Only we need 24-bit pixels.  So we do a fancy little mux dance.
  	e_signal->add({name => "vga_24bit_out", width => 24,});

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -