diff options
Diffstat (limited to 'fpga/hp_lcd_driver')
22 files changed, 844 insertions, 56 deletions
diff --git a/fpga/hp_lcd_driver/.gitignore b/fpga/hp_lcd_driver/.gitignore index d7fb5c6..4284f6d 100644 --- a/fpga/hp_lcd_driver/.gitignore +++ b/fpga/hp_lcd_driver/.gitignore @@ -1,5 +1,9 @@ build_spartan6/ build_smh-ac415/ build_smh-ac415b/ +build_rando_a7/ build_loader/ NOT/ +*.swp +*.lic +*.orig diff --git a/fpga/hp_lcd_driver/Makefile b/fpga/hp_lcd_driver/Makefile index 4e2be26..e9f1df7 100644 --- a/fpga/hp_lcd_driver/Makefile +++ b/fpga/hp_lcd_driver/Makefile @@ -1,22 +1,19 @@ -TARGETS= smh-ac415b #spartan6 #ep4ce6 smh-ac415 +TARGETS= rando_a7 #smh-ac415b #spartan6 #ep4ce6 smh-ac415 #fish:smh-ac415 default: ${TARGETS:%=build_%/hp_lcd_driver.svf} + + smh-ac415: build_smh-ac415/hp_lcd_driver.svf spartan6: build_spartan6/hp_lcd_driver.svf +rando_a7: build_rando_a7/out/hp_lcd_driver.bit + build_%/hp_lcd_driver.svf: dummy ${MAKE} -f ${@:build_%/hp_lcd_driver.svf=%}.mk -build_smh-ac415/hp_lcd_driver.svf: build_flash_loader/output_files/flash_loader.sof - -build_flash_loader/output_files/flash_loader.sof: dummy - ${MAKE} -f ep4ce15f23c8_loader.mk - - - clean: for i in ${TARGETS}; do ${MAKE} -f $$i.mk $@; done diff --git a/fpga/hp_lcd_driver/artix7.mk b/fpga/hp_lcd_driver/artix7.mk new file mode 100644 index 0000000..578468c --- /dev/null +++ b/fpga/hp_lcd_driver/artix7.mk @@ -0,0 +1,51 @@ +BUILD=build_${BOARD} + +IP= \ + artix7_ip/blk_mem_gen_0.tcl \ + artix7_ip/mmcm_0.tcl \ + artix7_ip/mmcm_1.tcl + + +BIT=${BUILD}/out/hp_lcd_driver.bit + +IP_STAMP=${IP:artix7_ip/%.tcl=${BUILD}/ip/%/stamp} +SRCS= ${IP} \ + artix7_config.tcl \ + artix7_hp_lcd_driver.tcl \ + ${BOARD}.tcl \ + ${BOARD}.xdc \ + clkgen_artix7.vhdl \ + debounce.vhdl \ + delay.vhdl \ + edge_det.vhdl \ + hp_lcd_driver.vhdl \ + input_formatter.vhdl \ + input_stage.vhdl \ + output_analog.vhdl \ + output_formatter.vhdl \ + output_stage.vhdl \ + synchronizer.vhdl \ + tmds_encoder.vhdl \ + tmds_encode.vhdl \ + tmds_output_artix7.vhdl \ + tmds_phy_artix7.vhdl \ + vram_artix7.vhdl + + + +OPENOCD=openocd -f openocd/${BOARD}.cfg + +default: ${BUILD}/build.stamp + +${BUILD}/build.stamp:${SRCS} ${IP_STAMP} + mkdir -p ${BUILD} + (cd ${BUILD} && BOARD=${BOARD} ../scripts/vivado -mode batch -source ../artix7_hp_lcd_driver.tcl) + touch $@ + +${BUILD}/ip/%/stamp:artix7_ip/%.tcl + mkdir -p ${BUILD}/ip + /bin/rm -rf $(dir $@) + (cd ${BUILD} && BOARD=${BOARD} ../scripts/vivado -mode batch -source ../$<) && touch $@ + + +${BIT}: ${BUILD}/build.stamp diff --git a/fpga/hp_lcd_driver/artix7_config.tcl b/fpga/hp_lcd_driver/artix7_config.tcl new file mode 100644 index 0000000..d76719c --- /dev/null +++ b/fpga/hp_lcd_driver/artix7_config.tcl @@ -0,0 +1,30 @@ +# +set board $::env(BOARD) +set board_tcl $source_dir/$board.tcl +set build_dir . +set ip_dir $build_dir/ip +set bd_dir $build_dir/bd +set ipl_dir $build_dir/ip_library +set output_dir $build_dir/out +source $board_tcl +create_project -in_memory -part $part_num + +file mkdir $build_dir +file mkdir $bd_dir +file mkdir $ip_dir +file mkdir $ipl_dir +file mkdir $output_dir + +#WARNING: [Vivado 12-13651] The IP file '/home/root/projects/hp_instrument_lcds/fpga/artix7/build-rando_a7/ip/mmcm_0/mmcm_0.xci' has been moved from its original location, as a result the outputs for this IP will now be generated in '/home/root/projects/hp_instrument_lcds/fpga/artix7/build-rando_a7/ip/mmcm_0'. Alternatively a copy of the IP can be imported into the project using one of the 'import_ip' or 'import_files' commands. +set_msg_config -id 12-13651 -suppress + + +#WARNING: [DRC REQP-1839] RAMB36 async control check: The RAMB36E1 vram0/bmg0/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_gen/valid.cstr/ramloop[0].ram.r/prim_noinit.ram/DEVICE_7SERIES.NO_BMM_INFO.SDP.CASCADED_PRIM36.ram_B has an input control pin vram0/bmg0/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_gen/valid.cstr/ramloop[0].ram.r/prim_noinit.ram/DEVICE_7SERIES.NO_BMM_INFO.SDP.CASCADED_PRIM36.ram_B/ADDRBWRADDR[12] (net: vram0/bmg0/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_gen/valid.cstr/ramloop[0].ram.r/prim_noinit.ram/addrb[12]) which is driven by a register (output0/output_formatter/addr_reg[12]) that has an active asychronous set or reset. This may cause corruption of the memory contents and/or read values when the set/reset is asserted and is not analyzed by the default static timing analysis. It is suggested to eliminate the use of a set/reset to registers driving this RAMB pin or else use a synchronous reset in which the assertion of the reset is timed by default. +set_msg_config -id REQP-1839 -suppress + + + +#WARNING: [Synth 8-3848] Net dma_axi_awid in module/entity pcie_tpm_widget does not have driver. [/root/projects/tpm_interposer/logic_analyzer/source/pcie_tpm_widget.vhdl:88] +#set_msg_config -id 8-3848 -new_severity ERROR + + diff --git a/fpga/hp_lcd_driver/artix7_hp_lcd_driver.tcl b/fpga/hp_lcd_driver/artix7_hp_lcd_driver.tcl new file mode 100644 index 0000000..684e493 --- /dev/null +++ b/fpga/hp_lcd_driver/artix7_hp_lcd_driver.tcl @@ -0,0 +1,85 @@ +# +set source_dir [file dirname [file normalize [info script]]] + +source $source_dir/artix7_config.tcl + +file mkdir $output_dir + +set files [glob -nocomplain "$output_dir/*"] +if {[llength $files] != 0} { + # clear folder contents + puts "deleting contents of $output_dir" + file delete -force {*}[glob -directory $output_dir *]; +} else { + puts "$output_dir is empty" +} + +#Reference HDL and constraint source files + +#read_xdc $early_xdc + +#read_verilog [ glob ../source/*.v ] +#read_vhdl -vhdl2008 -library work [ glob ../source/*.vhdl ] +read_vhdl -vhdl2008 -library work { ../clkgen_artix7.vhdl ../debounce.vhdl ../delay.vhdl ../edge_det.vhdl ../hp_lcd_driver.vhdl ../input_formatter.vhdl ../input_stage.vhdl ../output_analog.vhdl ../output_formatter.vhdl ../output_stage.vhdl ../synchronizer.vhdl ../tmds_encoder.vhdl ../tmds_encode.vhdl ../tmds_output_artix7.vhdl ../tmds_phy_artix7.vhdl ../vram_artix7.vhdl } + +set generics {} +append generics { } "video_width=$video_width" +append generics { } "BOARD=\"$board\"" +append generics { } "use_pclk=$use_pclk" + +set_property generic "$generics" [current_fileset] +puts $generics + +read_ip $ip_dir/blk_mem_gen_0/blk_mem_gen_0.xci +read_ip $ip_dir/mmcm_0/mmcm_0.xci +read_ip $ip_dir/mmcm_1/mmcm_1.xci + +read_xdc $normal_xdc + +#Run Synthesis +synth_design -top hp_lcd_driver -part $part_num +write_checkpoint -force $output_dir/post_synth.dcp +report_timing_summary -file $output_dir/post_synth_timing_summary.rpt +report_utilization -file $output_dir/post_synth_util.rpt + +set crdl [get_param tcl.collectionResultDisplayLimit] +set_param tcl.collectionResultDisplayLimit 10000000 + +set f [open "$output_dir/cells.txt" w] +puts $f [get_cells -hierarchical] +close $f + +set f [open "$output_dir/nets.txt" w] +puts $f [get_nets -hierarchical] +close $f +set_param tcl.collectionResultDisplayLimit $crdl + +set f [open "$output_dir/pins.txt" w] +puts $f [get_pins -hierarchical] +close $f +set_param tcl.collectionResultDisplayLimit $crdl + +#run optimization +opt_design +place_design +report_clock_utilization -file $output_dir/clock_util.rpt + +#get timing violations and run optimizations if needed +if {[get_property SLACK [get_timing_paths -max_paths 1 -nworst 1 -setup]] < 0} { + puts "Found setup timing violations => running physical optimization" + phys_opt_design +} +write_checkpoint -force $output_dir/post_place.dcp +report_utilization -file $output_dir/post_place_util.rpt +report_timing_summary -file $output_dir/post_place_timing_summary.rpt + +#Route design and generate bitstream +route_design -directive Explore +write_checkpoint -force $output_dir/post_route.dcp +report_route_status -file $output_dir/post_route_status.rpt +report_timing_summary -file $output_dir/post_route_timing_summary.rpt +report_power -file $output_dir/post_route_power.rpt +report_drc -file $output_dir/post_imp_drc.rpt +report_io -file $output_dir/post_imp_placed.rpt +write_verilog -force $output_dir/cpu_impl_netlist.v -mode timesim -sdf_anno true +write_bitstream -force $output_dir/hp_lcd_driver.bit diff --git a/fpga/hp_lcd_driver/artix7_ip/blk_mem_gen_0.tcl b/fpga/hp_lcd_driver/artix7_ip/blk_mem_gen_0.tcl new file mode 100644 index 0000000..84626aa --- /dev/null +++ b/fpga/hp_lcd_driver/artix7_ip/blk_mem_gen_0.tcl @@ -0,0 +1,33 @@ + + +set source_dir [file dirname [file dirname [file normalize [info script]]]] + +source $source_dir/artix7_config.tcl + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name blk_mem_gen_0 -dir $ip_dir + +set_property -dict [list \ + CONFIG.Memory_Type {Simple_Dual_Port_RAM} \ + CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {false} \ + CONFIG.Byte_Size {9} \ + CONFIG.Write_Width_A {6} \ + CONFIG.Write_Depth_A {245760} \ + CONFIG.Read_Width_A {6} \ + CONFIG.Operating_Mode_A {NO_CHANGE} \ + CONFIG.Write_Width_B {6} \ + CONFIG.Read_Width_B {6} \ + CONFIG.Enable_B {Use_ENB_Pin} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Register_PortB_Output_of_Memory_Primitives {true} \ + CONFIG.Use_RSTB_Pin {false} \ + CONFIG.Port_B_Clock {22} \ + CONFIG.Port_B_Enable_Rate {22} \ + CONFIG.Disable_Collision_Warnings {false} \ + CONFIG.EN_SAFETY_CKT {false} \ + ] [get_ips blk_mem_gen_0] + +generate_target all [get_ips] + +synth_ip [get_ips] + diff --git a/fpga/hp_lcd_driver/artix7_ip/mmcm_0.tcl b/fpga/hp_lcd_driver/artix7_ip/mmcm_0.tcl new file mode 100644 index 0000000..a49c8f2 --- /dev/null +++ b/fpga/hp_lcd_driver/artix7_ip/mmcm_0.tcl @@ -0,0 +1,38 @@ +set source_dir [file dirname [file dirname [file normalize [info script]]]] + +source $source_dir/artix7_config.tcl + +create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name mmcm_0 -dir $ip_dir + +set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {50} \ + CONFIG.CLKOUT2_USED {true} \ + CONFIG.CLKOUT3_USED {true} \ + CONFIG.CLKOUT4_USED {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {240} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {80} \ + CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {48} \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {24} \ + CONFIG.CLKIN1_JITTER_PS {200.0} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {20.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {5.000} \ + CONFIG.MMCM_CLKOUT1_DIVIDE {15} \ + CONFIG.MMCM_CLKOUT2_DIVIDE {25} \ + CONFIG.MMCM_CLKOUT3_DIVIDE {50} \ + CONFIG.NUM_OUT_CLKS {4} \ + CONFIG.CLKOUT1_JITTER {120.627} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678} \ + CONFIG.CLKOUT2_JITTER {146.190} \ + CONFIG.CLKOUT2_PHASE_ERROR {154.678} \ + CONFIG.CLKOUT3_JITTER {165.425} \ + CONFIG.CLKOUT3_PHASE_ERROR {154.678} \ + CONFIG.CLKOUT4_JITTER {202.151} \ + CONFIG.CLKOUT4_PHASE_ERROR {154.678} \ + ] [get_ips mmcm_0] + +generate_target all [get_ips] + +synth_ip [get_ips] + diff --git a/fpga/hp_lcd_driver/artix7_ip/mmcm_1.tcl b/fpga/hp_lcd_driver/artix7_ip/mmcm_1.tcl new file mode 100644 index 0000000..eb2143d --- /dev/null +++ b/fpga/hp_lcd_driver/artix7_ip/mmcm_1.tcl @@ -0,0 +1,35 @@ +set source_dir [file dirname [file dirname [file normalize [info script]]]] + +source $source_dir/artix7_config.tcl + +create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name mmcm_1 -dir $ip_dir + +set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {50} \ + CONFIG.CLKOUT2_USED {true} \ + CONFIG.CLKOUT3_USED {true} \ + CONFIG.CLKOUT4_USED {true} \ + CONFIG.CLKOUT5_USED {false} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {78.571} \ + CONFIG.USE_SAFE_CLOCK_STARTUP {false} \ + CONFIG.CLKIN1_JITTER_PS {100.0} \ + CONFIG.CLKOUT1_DRIVES {BUFG} \ + CONFIG.CLKOUT2_DRIVES {BUFG} \ + CONFIG.CLKOUT3_DRIVES {BUFG} \ + CONFIG.CLKOUT4_DRIVES {BUFG} \ + CONFIG.CLKOUT5_DRIVES {BUFG} \ + CONFIG.CLKOUT6_DRIVES {BUFG} \ + CONFIG.CLKOUT7_DRIVES {BUFG} \ + CONFIG.FEEDBACK_SOURCE {FDBK_AUTO} \ + CONFIG.MMCM_DIVCLK_DIVIDE {1} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {11.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {20.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {20.000} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {7} \ + CONFIG.NUM_OUT_CLKS {1} \ + ] [get_ips mmcm_1] + +generate_target all [get_ips] + +synth_ip [get_ips] + diff --git a/fpga/hp_lcd_driver/clkgen_artix7.vhdl b/fpga/hp_lcd_driver/clkgen_artix7.vhdl new file mode 100644 index 0000000..f7f8971 --- /dev/null +++ b/fpga/hp_lcd_driver/clkgen_artix7.vhdl @@ -0,0 +1,61 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +use work.all; + +library UNISIM; +use UNISIM.vcomponents.all; + +entity clkgen is + port ( + sys_rst_n : in std_logic; + clk_in : in std_logic; + i_clk : out std_logic; + o_clk : out std_logic; + o_clk_x2 : out std_logic; + o_clk_phy : out std_logic; + locked : out std_logic + ); +end clkgen; +architecture Behavioural of clkgen is + + signal clk_240m : std_logic; + signal clk_78_571m : std_logic; + signal clk_80m : std_logic; + signal clk_24m : std_logic; + signal clk_48m : std_logic; + signal clk_50m : std_logic; + + signal reset : std_logic; +begin + + reset <= not sys_rst_n; + + o_clk_buf : BUFG port map ( + I => clk_in, + O => clk_50m); + + + mmcm_0_i : mmcm_0 port map ( + clk_in1 => clk_50m, + clk_out1 => clk_240m, + clk_out2 => clk_80m, + clk_out3 => clk_48m, + clk_out4 => clk_24m, + reset => reset, + locked => locked + ); + + mmcm_1_i : mmcm_1 port map ( + clk_in1 => clk_50m, + clk_out1 => clk_78_571m, + reset => reset + ); + + o_clk_phy <= clk_240m; + o_clk <= clk_24m; + o_clk_x2 <= clk_48m; + i_clk <= clk_78_571m; + + +end Behavioural; diff --git a/fpga/hp_lcd_driver/hp_lcd_driver.vhdl b/fpga/hp_lcd_driver/hp_lcd_driver.vhdl index 087e475..95a38a1 100644 --- a/fpga/hp_lcd_driver/hp_lcd_driver.vhdl +++ b/fpga/hp_lcd_driver/hp_lcd_driver.vhdl @@ -15,12 +15,14 @@ entity hp_lcd_driver is addr_width : natural := 18; phase_slip : natural := 320; i_clk_multiple : natural := 4; - target : string := "spartan6"); + use_pclk : natural := 0; + target : string := "artix7"); port (clk_50m : in std_logic; sys_rst_n : in std_logic; - video : in std_logic_vector(video_width-1 downto 0); + video : in std_logic_vector(video_width -1 downto 0); hsync_in : in std_logic; vsync_in : in std_logic; + pclk_in : in std_logic; r_out : out std_logic; b_out : out std_logic; g_out : out std_logic; @@ -34,7 +36,9 @@ entity hp_lcd_driver is hdmi_g_n : out std_logic; hdmi_b_p : out std_logic; hdmi_b_n : out std_logic; - i_clk_out : out std_logic); + hdmi_vcc : out std_logic; + i_clk_out : out std_logic; + led : out std_logic); end hp_lcd_driver; @@ -70,6 +74,8 @@ architecture Behavioral of hp_lcd_driver is signal v : natural; + signal c : natural; + signal t : std_logic; begin @@ -146,12 +152,14 @@ begin frame_start => 383, h_stride => 384, v_stride => 524287, - phase_slip => phase_slip + phase_slip => phase_slip, + use_pclk => use_pclk ) port map ( sys_rst_n => sys_rst_n, clk => i_clk, video_in => video, + pclk_in => pclk_in, hsync_in => not hsync_in, vsync_in => not vsync_in, @@ -203,14 +211,18 @@ begin rd_data => rd_data ); - - r<=x"00"; - b<=x"00"; - g <= x"ff" when rd_data(1) = '1' else - x"80" when rd_data(0) = '1' else - x"00"; +-- r<=x"00"; +-- b<=x"00"; + + r <= rd_data(1 downto 0) & "000000"; + g <= rd_data(3 downto 2) & "000000"; + b <= rd_data(5 downto 4) & "000000"; + +--"ff" when rd_data(1) = '1' else +-- x"80" when rd_data(0) = '1' else +-- ix"00"; @@ -262,17 +274,20 @@ begin h_stride => 1, v_stride => 384 --- h_active => 800, --- h_sync_start => 832, --- h_sync_end => 912, --- h_total => 1024, --- v_active => 600, --- v_sync_start => 601, --- v_sync_end => 604, --- v_total => 622, --- h_stride => 1, --- v_stride => 384 +-- h_active => 640, +-- h_sync_start=>656, +-- h_sync_end =>752, +-- h_total=>800, +-- +-- v_active =>480, +-- v_sync_start=>490, +-- v_sync_end=>492, +-- v_total=>525, +-- h_stride=>1, +-- v_stride=>384 + ) + port map( clk_locked => clk_locked, clk => o_clk, @@ -299,6 +314,22 @@ begin hdmi_b_n => hdmi_b_n ); + process (clk_50m, c) + begin + if rising_edge(clk_50m) then + + if c < 19999999 then + c <=c+1; + else + c <=0; + t <=not t; + end if; + end if; + end process; + + + led <= t; + end Behavioral; diff --git a/fpga/hp_lcd_driver/input_formatter.vhdl b/fpga/hp_lcd_driver/input_formatter.vhdl index f3bd434..35916f5 100644 --- a/fpga/hp_lcd_driver/input_formatter.vhdl +++ b/fpga/hp_lcd_driver/input_formatter.vhdl @@ -16,13 +16,16 @@ entity input_formatter is frame_start : natural := 0; h_stride : natural := 384; v_stride : natural := 1; - phase_slip : natural := 320); + phase_slip : natural := 320; + use_pclk : natural := 0 + ); port ( sys_rst_n : in std_logic; clk : in std_logic; hsync : in std_logic; vsync : in std_logic; + pclk : in std_logic; addr_out : out std_logic_vector(addr_width-1 downto 0); wren_out : out std_logic; h_grid : out std_logic; @@ -38,6 +41,9 @@ architecture beh of input_formatter is signal addr : std_logic_vector(addr_width-1 downto 0); signal wren : std_logic; + signal pclk_ne : std_logic; + signal pclk_pe : std_logic; + signal hsync_ne : std_logic; signal hsync_pe : std_logic; @@ -45,8 +51,8 @@ architecture beh of input_formatter is signal v_active_counter : natural; signal h_fp_counter : natural; signal h_active_counter : natural; - signal h_div : natural; + signal h_div : natural; signal phase_accum : natural; @@ -62,6 +68,14 @@ begin pe => hsync_pe); + pclk_ed : entity work.edge_det + port map( + clk => clk, + sig => pclk, + e => pclk_ne, + pe => pclk_pe); + + addr_out <= addr; @@ -77,7 +91,7 @@ begin h_fp_counter <= 0; v_active_counter <= 0; v_fp_counter <= 0; - phase_accum <= 0; + phase_accum <= phase_slip; elsif rising_edge(clk) then if hsync_pe = '1' then --if v_active_counter = 0 and v_fp_counter=0 then @@ -102,22 +116,27 @@ begin h_fp_counter <= h_fp_counter -1; elsif h_active_counter /= 0 then - if h_div = 0 then - wren <= '1'; - if phase_accum = 0 then - phase_accum <= phase_slip; - h_div <= clk_multiple; + if use_pclk = 0 then + if h_div = 0 then + wren <= '1'; + if phase_accum = 0 then + phase_accum <= phase_slip; + h_div <= clk_multiple; + else + phase_accum <= phase_accum-1; + h_div <= clk_multiple-1; + end if; else - phase_accum <= phase_accum-1; - h_div <= clk_multiple-1; + h_div <= h_div -1; + wren <= '0'; end if; else - if wren = '1' then - wren <= '0'; - h_active_counter <= h_active_counter -1; - addr <= std_logic_vector(unsigned(addr)+h_stride); - end if; - h_div <= h_div -1; + wren <= pclk_pe; + end if; + + if wren = '1' then + h_active_counter <= h_active_counter -1; + addr <= std_logic_vector(unsigned(addr)+h_stride); end if; end if; end if; diff --git a/fpga/hp_lcd_driver/input_stage.vhdl b/fpga/hp_lcd_driver/input_stage.vhdl index 9355a93..c124a59 100644 --- a/fpga/hp_lcd_driver/input_stage.vhdl +++ b/fpga/hp_lcd_driver/input_stage.vhdl @@ -16,7 +16,8 @@ entity input_stage is frame_start : natural := 0; h_stride : natural := 384; v_stride : natural := 1; - phase_slip : natural := 320); + phase_slip : natural := 320; + use_pclk : natural := 0); port ( clk : in std_logic; @@ -24,6 +25,7 @@ entity input_stage is video_in : in std_logic_vector(video_width -1 downto 0); + pclk_in : in std_logic; hsync_in : in std_logic; vsync_in : in std_logic; @@ -36,6 +38,9 @@ end input_stage; architecture beh of input_stage is + signal s_pclk : std_logic; + signal d_pclk : std_logic; + signal s_hsync : std_logic; signal d_hsync : std_logic; @@ -65,6 +70,13 @@ begin end generate; + pclk_sync : entity work.synchronizer + generic map(stages => sync_stages) + port map ( + clk => clk, + i => pclk_in, + o => s_pclk + ); hsync_sync : entity work.synchronizer generic map(stages => sync_stages) @@ -82,6 +94,14 @@ begin o => s_vsync ); + + pclk_debounce : entity work.debounce + generic map(stages => debounce_stages) + port map( + clk => clk, + i => s_pclk, + o => d_pclk); + hsync_debounce : entity work.debounce generic map(stages => debounce_stages) port map( @@ -89,8 +109,6 @@ begin i => s_hsync, o => d_hsync); - - vsync_debounce : entity work.debounce generic map(stages => debounce_stages) port map( @@ -112,10 +130,12 @@ begin frame_start => frame_start, h_stride => h_stride, v_stride => v_stride, - phase_slip => phase_slip) + phase_slip => phase_slip, + use_pclk => use_pclk) port map ( sys_rst_n => sys_rst_n, clk => clk, + pclk => d_pclk, hsync => d_hsync, vsync => d_vsync, addr_out => addr, diff --git a/fpga/hp_lcd_driver/output_formatter.vhdl b/fpga/hp_lcd_driver/output_formatter.vhdl index 3e26515..558c222 100644 --- a/fpga/hp_lcd_driver/output_formatter.vhdl +++ b/fpga/hp_lcd_driver/output_formatter.vhdl @@ -124,11 +124,11 @@ begin h_grid <= '1' when (h mod 32) = 0 -- h_grid <= '1' when (h = 0) or (h = (h_active-1)) - else '0'; +else '0'; v_grid <= '1' when (v mod 32) = 0 -- v_grid <= '1' when (v = 0) or (v = (v_active-1)) - else '0'; +else '0'; addr_out <= addr; diff --git a/fpga/hp_lcd_driver/output_stage.vhdl b/fpga/hp_lcd_driver/output_stage.vhdl index e02d8ce..56f4ae4 100644 --- a/fpga/hp_lcd_driver/output_stage.vhdl +++ b/fpga/hp_lcd_driver/output_stage.vhdl @@ -140,15 +140,17 @@ begin -- o => grid_d -- ); --- r <= r_in; + r <= r_in; g <= g_in; --- b <= b_in; + b <= b_in; - b<=x"00" when v_grid='0' - else x"ff"; - r<=x"00" when h_grid='0' - else x"ff"; + +-- b<=x"00" when v_grid='0' +-- else x"ff"; + +-- r<=x"00" when h_grid='0' +-- else x"ff"; -- b<=x"00" when v_grid='0' and h_grid='0' -- else x"ff"; diff --git a/fpga/hp_lcd_driver/prog_a7 b/fpga/hp_lcd_driver/prog_a7 new file mode 100755 index 0000000..c10ee8f --- /dev/null +++ b/fpga/hp_lcd_driver/prog_a7 @@ -0,0 +1,4 @@ +#!/bin/bash +BIT=./build-rando_a7/out/hp_lcd_driver.bit +../../openocd/prefix/bin/openocd -f interface/altera-usb-blaster.cfg -f cpld/xilinx-xc7.cfg -c init -c "pld load xc7.pld $BIT" -c shutdown + diff --git a/fpga/hp_lcd_driver/rando_a7.mk b/fpga/hp_lcd_driver/rando_a7.mk new file mode 100644 index 0000000..87a2ef4 --- /dev/null +++ b/fpga/hp_lcd_driver/rando_a7.mk @@ -0,0 +1,2 @@ +BOARD=rando_a7 +include artix7.mk diff --git a/fpga/hp_lcd_driver/rando_a7.tcl b/fpga/hp_lcd_driver/rando_a7.tcl new file mode 100644 index 0000000..cfaa74d --- /dev/null +++ b/fpga/hp_lcd_driver/rando_a7.tcl @@ -0,0 +1,5 @@ +# +set part_num "xc7a35tfgg484-2" +set normal_xdc "../rando_a7.xdc" +set use_pclk 1 +set video_width 6 diff --git a/fpga/hp_lcd_driver/rando_a7.xdc b/fpga/hp_lcd_driver/rando_a7.xdc new file mode 100644 index 0000000..04b2cac --- /dev/null +++ b/fpga/hp_lcd_driver/rando_a7.xdc @@ -0,0 +1,117 @@ +# "Normal" constraints file- not early not late + + +set_property IOSTANDARD LVCMOS33 [get_ports clk_50m] +set_property PACKAGE_PIN R4 [get_ports clk_50m] + +set_property PACKAGE_PIN U1 [get_ports {led}] +set_property IOSTANDARD LVCMOS33 [get_ports {led}] +#set_property PACKAGE_PIN T1 [get_ports {led_1}] +#set_property IOSTANDARD LVCMOS33 [get_ports {led_1}] + +set_property PACKAGE_PIN R3 [get_ports {hdmi_r_p}] +set_property PACKAGE_PIN R2 [get_ports {hdmi_r_n}] +set_property PACKAGE_PIN R6 [get_ports {hdmi_g_p}] +set_property PACKAGE_PIN T6 [get_ports {hdmi_g_n}] +set_property PACKAGE_PIN U3 [get_ports {hdmi_b_p}] +set_property PACKAGE_PIN V3 [get_ports {hdmi_b_n}] +set_property PACKAGE_PIN Y3 [get_ports {hdmi_c_p}] +set_property PACKAGE_PIN AA3 [get_ports {hdmi_c_n}] + +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_c_p}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_c_n}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_r_p}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_r_n}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_g_p}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_g_n}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_b_p}] +set_property IOSTANDARD TMDS_33 [get_ports {hdmi_b_n}] + +#set_property DRIVE 16 [get_ports {hdmi_c_p}] +#set_property DRIVE 16 [get_ports {hdmi_c_n}] +#set_property DRIVE 16 [get_ports {hdmi_r_p}] +#set_property DRIVE 16 [get_ports {hdmi_r_n}] +#set_property DRIVE 16 [get_ports {hdmi_g_p}] +#set_property DRIVE 16 [get_ports {hdmi_g_n}] +#set_property DRIVE 16 [get_ports {hdmi_b_p}] + +set_property PACKAGE_PIN W1 [get_ports {hdmi_vcc}] +set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_vcc}] + + +#set_property PACKAGE_PIN P20 [get_ports rxd] +#set_property PACKAGE_PIN T20 [get_ports txd] +#set_property IOSTANDARD LVCMOS33 [get_ports rxd] +#set_property IOSTANDARD LVCMOS33 [get_ports txd] + +#set_property PACKAGE_PIN T3 [get_ports key] +#set_property IOSTANDARD LVCMOS33 [get_ports key] + +set_property PACKAGE_PIN N22 [get_ports {video[0]}] +set_property PACKAGE_PIN N20 [get_ports {video[1]}] +set_property PACKAGE_PIN N18 [get_ports {video[2]}] +set_property PACKAGE_PIN K18 [get_ports {video[3]}] +set_property PACKAGE_PIN M18 [get_ports {video[4]}] +set_property PACKAGE_PIN M15 [get_ports {video[5]}] +#set_property PACKAGE_PIN U20 [get_ports {video[6]}] +#set_property PACKAGE_PIN T21 [get_ports {video[7]}] + +set_property IOSTANDARD LVCMOS33 [get_ports {video[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {video[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {video[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {video[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {video[4]}] +set_property IOSTANDARD LVCMOS33 [get_ports {video[5]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {video[6]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {video[7]}] + +set_property PACKAGE_PIN W19 [get_ports {pclk_in}] +set_property PACKAGE_PIN R18 [get_ports {vsync_in}] +set_property PACKAGE_PIN Y18 [get_ports {hsync_in}] +set_property PACKAGE_PIN P16 [get_ports {r_out}] +set_property PACKAGE_PIN V18 [get_ports {g_out}] +set_property PACKAGE_PIN P15 [get_ports {b_out}] +set_property PACKAGE_PIN P14 [get_ports {i_clk_out}] +set_property PACKAGE_PIN V17 [get_ports {hsync_out}] +set_property PACKAGE_PIN N13 [get_ports {vsync_out}] +set_property PACKAGE_PIN N13 [get_ports {vsync_out}] + + +set_property IOSTANDARD LVCMOS33 [get_ports {pclk_in}] +set_property IOSTANDARD LVCMOS33 [get_ports {vsync_in}] +set_property IOSTANDARD LVCMOS33 [get_ports {hsync_in}] +set_property IOSTANDARD LVCMOS33 [get_ports {r_out}] +set_property IOSTANDARD LVCMOS33 [get_ports {g_out}] +set_property IOSTANDARD LVCMOS33 [get_ports {b_out}] +set_property IOSTANDARD LVCMOS33 [get_ports {i_clk_out}] +set_property IOSTANDARD LVCMOS33 [get_ports {hsync_out}] +set_property IOSTANDARD LVCMOS33 [get_ports {vsync_out}] + +set_property PACKAGE_PIN AA18 [get_ports {sys_rst_n}] +set_property IOSTANDARD LVCMOS33 [get_ports {sys_rst_n}] +set_property PULLTYPE PULLUP [get_ports {sys_rst_n}] + +create_clock -period 20.000 -name pcie_clkin [get_ports clk_50m] +#set_false_path -from [get_ports pci_exp_rst_n] + + +############################################################################### +# Additional design / project settings +############################################################################### + +# Power down on overtemp +set_property BITSTREAM.CONFIG.OVERTEMPPOWERDOWN ENABLE [current_design] + +# High-speed configuration so FPGA is up in time to negotiate with PCIe root complex +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN Div-1 [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property CONFIG_MODE SPIx4 [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] + +set_property CONFIG_VOLTAGE 3.3 [current_design] +set_property CFGBVS VCCO [current_design] + + + + diff --git a/fpga/hp_lcd_driver/scripts/vivado b/fpga/hp_lcd_driver/scripts/vivado new file mode 100755 index 0000000..0dbf03c --- /dev/null +++ b/fpga/hp_lcd_driver/scripts/vivado @@ -0,0 +1,16 @@ +#!/bin/bash +HS3_BIN=/home/DISTRIB/Xilinx/Digilent-HS3/foo +HS3_LIB=/home/DISTRIB/Xilinx/Digilent-HS3/foo +VIVADO=/software/apps/xilinx/Vivado/2022.1/ +VIVADO_BIN=${VIVADO}/bin +VIVADO_LIB=${VIVADO}/lib64 + +XILINXD_LICENSE_FILE=${PWD}/xilinx_ise_vivado_license.lic +export XILINXD_LICENSE_FILE + +export LD_LIBRARY_PATH + +PATH="${VIVADO_BIN}:${HS3_BIN}:$PATH" +LD_LIBRAY_PATH="${LD_LIBRARY_PATH}:/usr/lib64:/usr/lib:/lib64:/lib:${VIVADO_LIB}:${HS3_LIB}" + +exec ${VIVADO_BIN}/vivado $@ diff --git a/fpga/hp_lcd_driver/tmds_output_artix7.vhdl b/fpga/hp_lcd_driver/tmds_output_artix7.vhdl new file mode 100644 index 0000000..7370bb7 --- /dev/null +++ b/fpga/hp_lcd_driver/tmds_output_artix7.vhdl @@ -0,0 +1,115 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; + +library UNISIM; +use UNISIM.vcomponents.all; + + +entity tmds_output is + port ( + sys_rst_n : in std_logic; + pclk_locked : in std_logic; + pclk : in std_logic; + pclk_x2 : in std_logic; + pclk_phy : in std_logic; + + r_p10 : in std_logic_vector(9 downto 0); + g_p10 : in std_logic_vector(9 downto 0); + b_p10 : in std_logic_vector(9 downto 0); + c_p10 : in std_logic_vector(9 downto 0); + + + tmds_c_out_p : out std_logic; + tmds_c_out_n : out std_logic; + tmds_r_out_p : out std_logic; + tmds_r_out_n : out std_logic; + tmds_g_out_p : out std_logic; + tmds_g_out_n : out std_logic; + tmds_b_out_p : out std_logic; + tmds_b_out_n : out std_logic + ); +end tmds_output; + + +architecture beh of tmds_output is + + signal phy_reset : std_logic; + signal b : natural := 0; + + +begin + phy_reset <= not sys_rst_n; -- or not pll_locked; + + process (pclk_phy, b, sys_rst_n) + begin + if sys_rst_n = '0' then + b <= 0; + elsif rising_edge(pclk_phy) then + if b = 9 then + b <= 0; + else + b <= b+1; + end if; + end if; + end process; + + + phy_c : entity work.tmds_phy_artix7 + port map ( + reset => phy_reset, + pix_clk => pclk, + phy_clk => pclk_phy, + b =>b, + din => c_p10, + tmds_out_p => tmds_c_out_p, + tmds_out_n => tmds_c_out_n + ); + + phy_r : entity work.tmds_phy_artix7 + port map ( + reset => phy_reset, + pix_clk => pclk, + phy_clk => pclk_phy, + b =>b, + din => r_p10, + tmds_out_p => tmds_r_out_p, + tmds_out_n => tmds_r_out_n + ); + + + phy_g : entity work.tmds_phy_artix7 + port map ( + reset => phy_reset, + pix_clk => pclk, + phy_clk => pclk_phy, + b =>b, + din => g_p10, + tmds_out_p => tmds_g_out_p, + tmds_out_n => tmds_g_out_n + ); + + + phy_b : entity work.tmds_phy_artix7 + port map ( + reset => phy_reset, + pix_clk => pclk, + phy_clk => pclk_phy, + b =>b, + din => b_p10, + tmds_out_p => tmds_b_out_p, + tmds_out_n => tmds_b_out_n + ); + + +-- tmds_c_out_p <= '0'; +-- tmds_c_out_n <= '0'; +-- tmds_r_out_p <= '0'; +-- tmds_r_out_n <= '0'; +-- tmds_g_out_p <= '0'; +-- tmds_g_out_n <= '0'; +-- tmds_b_out_p <= '0'; +-- tmds_b_out_n <= '0'; +-- + +end beh; diff --git a/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl b/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl new file mode 100644 index 0000000..8c8106e --- /dev/null +++ b/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl @@ -0,0 +1,85 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; + +library UNISIM; +use UNISIM.vcomponents.all; + + +entity tmds_phy_artix7 is + port ( + reset : in std_logic; + pix_clk : in std_logic; + phy_clk : in std_logic; + din : in std_logic_vector(9 downto 0); + b : in natural; + tmds_out_p : out std_logic; + tmds_out_n : out std_logic + ); +end tmds_phy_artix7; + + +architecture beh of tmds_phy_artix7 is + + signal ld : std_logic_vector(9 downto 0); + signal sr : std_logic_vector(9 downto 0); + + signal s : std_logic; + +begin + + + process(pix_clk) + begin + if rising_edge(pix_clk) then + ld <= din; + end if; + end process; + + +-- Using ODDR +-- process(phy_clk) +-- begin +-- if rising_edge(phy_clk) then +-- if b=0 then +-- sr<= ld; +-- else +-- sr(7 downto 0) <= sr (9 downto 2); +-- end if; +-- end if; +-- end process; +-- +--ODDR_inst : ODDR +--generic map( +-- DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" +-- INIT => '0', -- Initial value for Q port ('1' or '0') +-- SRTYPE => "ASYNC") -- Reset Type ("ASYNC" or "SYNC") +--port map ( +-- Q => s, -- 1-bit DDR output +-- C => phy_clk, -- 1-bit clock input +-- CE => '1', -- 1-bit clock enable input +-- D1 => sr(0), -- 1-bit data input (positive edge) +-- D2 => sr(1), -- 1-bit data input (negative edge) +-- R => '0', -- 1-bit reset input +-- S => '0' -- 1-bit set input +--); + + +-- Using a shift register + process(phy_clk) + begin + if rising_edge(phy_clk) then + if b = 0 then + sr <= ld; + else + sr(8 downto 0) <= sr (9 downto 1); + s <=sr(0); + end if; + end if; + end process; + + + + od : OBUFDS port map (O => tmds_out_p, OB => tmds_out_n, I => s); + +end beh; diff --git a/fpga/hp_lcd_driver/vram_artix7.vhdl b/fpga/hp_lcd_driver/vram_artix7.vhdl new file mode 100644 index 0000000..82186e1 --- /dev/null +++ b/fpga/hp_lcd_driver/vram_artix7.vhdl @@ -0,0 +1,38 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity vram is + generic ( + addr_width : natural := 18; + video_width : natural := 6 + ); + port ( + wr_clk : in std_logic; + wr_en : in std_logic; + wr_addr : in std_logic_vector(addr_width-1 downto 0); + wr_data : in std_logic_vector(video_width-1 downto 0); + rd_clk : in std_logic; + rd_addr : in std_logic_vector(addr_width-1 downto 0); + rd_data : out std_logic_vector(video_width-1 downto 0) + ); +end vram; + +architecture beh of vram is + signal wr_en_v : std_logic_vector(0 downto 0); +begin + + wr_en_v(0) <= wr_en; + + bmg0 : entity work.blk_mem_gen_0 + port map ( + ena => '1', + enb => '1', + clka => wr_clk, + wea => wr_en_v, + addra => wr_addr, + dina => wr_data, + clkb => rd_clk, + doutb => rd_data, + addrb => rd_addr + ); +end beh; |