📄 vga_controller.pm
字号:
my $pixel_mux;
$pixel_mux = e_mux->add ({
out => "vga_24bit_out",
table =>
[
"(pixel_mux_counter == 0)" => "fifo_data_out[23:0]",
"(pixel_mux_counter == 1)" => "{fifo_data_out[15:0], prev_fifo_data_out[31:24]}",
"(pixel_mux_counter == 2)" => "{fifo_data_out[7:0], prev_fifo_data_out[31:16]}",
"(pixel_mux_counter == 3)" => "prev_fifo_data_out[31:8]",
],
default => "fifo_data_out[23:0]",
});
# This splits up the 24-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_24bit_out[7:0]) : 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_24bit_out[15:8]) : 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_24bit_out[23:16]) : 8'b00000000",
clock => "vga_clk",
enable => 1,
});
}
# Here we generate the sync signals to the DAC
e_signal->add({name => "sync_n", width => 1,});
# e_assign->add (["sync_n", "vga_start ? (vsync_temp ~^ hsync_temp) : sync_n_init"]);
# e_assign->add (["sync_n", "vga_start ? 1'b1 : sync_n_init"]);
e_register->add({
out => {name => "sync_n", export => 1,},
in => ("vga_start ? (vsync_temp ~^ hsync_temp) : sync_n_init"),
clock => "vga_clk",
enable => 1,
});
e_signal->add({name => "sync_t", width => 1,});
# e_assign->add (["sync_t", "vga_start ? $SYNC_POLARITY : 0"]);
e_register->add({
out => {name => "sync_t", export => 1,},
in => ("vga_start ? $SYNC_POLARITY : 0"),
clock => "vga_clk",
enable => 1,
});
e_register->add({
out => {name => "blank_n", export => 1,},
in => "display_active",
clock => "vga_clk",
enable => 1,
});
# These are our other VGA output signals, vblank, vsync, hblank, and hsync
e_register->add({
out => {name => "vblank", export => 0,},
in => "(row_counter >= ($VBLANK_HIGH)) && (row_counter < ($VBLANK_LOW))",
clock => "vga_clk",
enable => 1,
});
# e_register->add({
# out => {name => "vsync_temp", export => 0,},
# in => "(row_counter >= ($VSYNC_HIGH)) && (row_counter < ($VSYNC_LOW2))",
# clock => "vga_clk",
# enable => 1,
# });
e_assign->add (["vsync_temp", "(row_counter >= ($VSYNC_HIGH)) && (row_counter < ($VSYNC_LOW2))"]);
# This delays the vsync signal to account for the latency
# in the VGA DAC. This is needed because vsync bypasses
# the DAC.
e_blind_instance->add({
tag => 'normal',
use_sim_models => 1,
name => 'vsync_delay',
module => 'lpm_shiftreg',
in_port_map => {clock => "vga_clk",
aclr => "!reset_n",
shiftin => "vsync_temp",},
out_port_map => {shiftout => "vsync"},
parameter_map => {LPM_WIDTH => "$VGA_DAC_LATENCY"},
});
e_register->add({
out => {name => "hblank", export => 0,},
in => "(column_counter >= ($HBLANK_HIGH)) && (column_counter < ($HBLANK_LOW))",
clock => "vga_clk",
enable => 1,
});
# e_register->add({
# out => {name => "hsync_temp", export => 0,},
# in => "(column_counter >= ($HSYNC_HIGH)) && (column_counter < ($HSYNC_LOW2))",
# clock => "vga_clk",
# enable => 1,
# });
e_assign->add (["hsync_temp", "(column_counter >= ($HSYNC_HIGH)) && (column_counter < ($HSYNC_LOW2))"]);
# This delays the hsync signal 7 clock cycles to account for the latency
# in the VGA DAC. This is needed because hsync is a TTL signal that bypasses
# the DAC.
e_blind_instance->add({
tag => 'normal',
use_sim_models => 1,
name => 'hsync_delay',
module => 'lpm_shiftreg',
in_port_map => {clock => "vga_clk",
aclr => "!reset_n",
shiftin => "hsync_temp",},
out_port_map => {shiftout => "hsync"},
parameter_map => {LPM_WIDTH => "$VGA_DAC_LATENCY"},
});
# Temp counter for debug
# e_blind_instance->add({
# tag => 'normal',
# use_sim_models => 1,
# name => 'num_fifo_writes',
# module => 'lpm_counter',
# in_port_map => {clock => "clk",
# aclr => "!reset_n",
# cnt_en => "fifo_write_req",
# sclr => "!go_bit",},
# out_port_map => {"q", "fifo_writes",},
# parameter_map => {LPM_WIDTH => "32",
# LPM_MODULUS => "153600",},
# });
# e_port->add({name => "fifo_writes", width => 32, direction => "output", });
# Temp counter for debug
# e_blind_instance->add({
# tag => 'normal',
# use_sim_models => 1,
# name => 'vga_frame_counter',
# module => 'lpm_counter',
# in_port_map => {clock => "vga_clk",
# aclr => "!reset_n",
# cnt_en => "(column_counter == ($HSCAN_WIDTH - 1)) && (row_counter == ($VSCAN_DEPTH - 1))",
# sclr => "!vga_start",},
# out_port_map => {"q", "frame_counter",},
# parameter_map => {LPM_WIDTH => "10",},
# });
# e_port->add({name => "frame_counter", width => 10, direction => "output", });
################################################################
# THIS IS THE SLAVE INTERFACE #
################################################################
# Declare slave_writedata explicitly (its width isn't stated implicitly anywhere).
e_port->add({name => "slave_writedata", width => $SBI_slave->{Data_Width}, direction => "input", });
# Declare slave_readdata explicitly (its width isn't stated implicitly anywhere).
e_port->add({name => "slave_readdata", width => $SBI_slave->{Data_Width}, direction => "output", });
# The address input isn't currently used - declare it.
e_port->add({name => "slave_address", width => 2, direction => "input", });
# Declare the chipselect
e_port->add({name => "slave_chipselect", width => 1, direction => "input", });
my $read_mux;
$read_mux = e_mux->add ({
out => "slave_readdata",
table =>
[
"(slave_address == 0)" => "slave_control_reg",
"(slave_address == 1)" => "dma_source_reg",
"(slave_address == 2)" => "dma_modulus_reg",
"(slave_address == 3)" => "current_dma",
],
default => "slave_control_reg",
});
################################################################
# THESE ARE THE SLAVE REGISTERS #
################################################################
# This is the control/status register (bit0 = go)
# 31 0
# ------------------------------------------------------
# | | G |
# ------------------------------------------------------
#
# G - Go Bit, Enables initialization and operation of controller
#
e_register->add({
out => {name => "slave_control_reg", width => $SBI_slave->{Data_Width}, export => 0,},
in => "slave_writedata",
enable => "slave_write && slave_chipselect && (slave_address == 0)",
});
e_assign->add (["ctrl_reg_go_bit", "slave_control_reg[0]"]);
# e_assign->add (["read_fifo_if_not_empty", "slave_control_reg[1]"]);
# This is the DMA address counter reload value for the next frame
e_register->add({
out => {name => "dma_source_reg", width => $SBI_slave->{Data_Width}, export => 0,},
in => "slave_writedata",
enable => "slave_write && slave_chipselect && (slave_address == 1)",
});
# This is the end value of the DMA address counter.
# (reload counter with dma_source_reg when count = dma_source_reg + dma_modulus_reg - 4)
e_register->add({
out => {name => "dma_modulus_reg", width => $SBI_slave->{Data_Width}, export => 0,},
in => "slave_writedata",
enable => "slave_write && slave_chipselect && (slave_address == 2)",
});
# This reg is the start address the DMA is currenlty transfering from.
e_register->add({
out => {name => "current_dma", width => $SBI_slave->{Data_Width}, export => 0,},
in => "dma_source_reg",
enable => "address_counter_sload",
});
################################################################
# THIS IS THE DMA READ MASTER #
################################################################
e_port->add({name => "master_readdata", width => $SBI_master->{Data_Width}, direction => "input", });
e_port->add({name => "master_address", width => 32, direction => "output", });
e_port->add({name => "master_waitrequest", width => 1, direction => "input", });
e_port->add({name => "master_data_valid", width => 1, direction => "input", });
e_port->add({name => "master_read", width => 1, direction => "output", });
e_assign->add (["master_address", "address_counter"]);
# Perform pipelined reads whenever the go bit in the control register is set.
e_assign->add (["master_read", "fifo_has_room & go_bit"]);
# Write to the fifo whenever read data is valid on the read master and the go bit is set
e_assign->add (["fifo_write_req", "master_data_valid & go_bit"]);
################################################################
# THESE ARE THE AVALON PORTS #
################################################################
my @avalon_slave_signals = qw(
slave_address
clk
reset_n
slave_write
slave_writedata
slave_readdata
slave_chipselect
);
my @avalon_master_signals = qw(
master_address
clk
master_readdata
master_read
master_waitrequest
master_data_valid
);
make_slave_interface(@avalon_slave_signals);
make_master_interface(@avalon_master_signals);
}
1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -