URL
https://opencores.org/ocsvn/p9813_rgb_led_string_driver/p9813_rgb_led_string_driver/trunk
Subversion Repositories p9813_rgb_led_string_driver
[/] [p9813_rgb_led_string_driver/] [trunk/] [rtl/] [VHDL/] [fpga.vhd] - Rev 2
Compare with Previous | Blame | View Log
-------------------------------------- -- Test FPGA -------------------------------------- -- -------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; -- synopsys translate_off library xp2; use xp2.components.all; -- synopsys translate_on library work; use work.function_pack.all; entity fpga is port ( -- System Clock & Reset_n sys_clk_ref : in std_logic; sys_rst_n_i : in std_logic; -- Standardized Board Inputs / Outputs switch : in unsigned(7 downto 0); led : out unsigned(7 downto 0); exp_io : inout unsigned(39 downto 1); -- TTL serial interface uart_0_tx_o : out std_logic; uart_0_rx_i : in std_logic ); end fpga; architecture beh of fpga is -- Constants constant SYS_CLK_RATE : real := 50000000.0; -- The clock rate at which the FPGA runs constant FPGA_VERSION : unsigned(31 downto 0) := "11110000111100001111111111110001"; constant ALEX_K_BITS : natural := 32; constant ALEX_K_FRAC : natural := 8; constant ALEX_GAIN_ADJ : natural := 2; constant DERAND_BITS : natural := 16; ---------------------------------------------------------------------------- --Internal signal declarations ---------------------------------------------------------------------------- signal sys_rst_l : std_logic; -- Board Input & Output related signal led_reg : unsigned(7 downto 0); signal led_disp : unsigned(7 downto 0); signal switch_l : unsigned(7 downto 0); signal sys_rst : std_logic; signal sys_rst_n : std_logic; -- Clock and oscillator related signal sys_clk : std_logic; signal sys_clk_en : std_logic; -- Signals for system controller signal syscon_baud_clk : std_logic; signal syscon_baud_lock : std_logic; -- System Bus interface signal syscon_ack : std_logic; signal syscon_err : std_logic; signal syscon_dat_rd : unsigned(31 downto 0); signal syscon_dat_wr : unsigned(31 downto 0); signal syscon_rst : std_logic; signal syscon_cyc : std_logic; signal syscon_adr : unsigned(31 downto 0); signal syscon_we : std_logic; signal sel_reg : std_logic; signal reg_dat_rd : unsigned(31 downto 0); signal reg_ack : std_logic; signal reg_err : std_logic; signal sel_bram : std_logic; signal bram_dat_rd : unsigned(31 downto 0); signal bram_ack : std_logic; signal bram_err : std_logic; signal bram_wait : unsigned(1 downto 0); -- Signals for system registers signal sel_sysregs : std_logic; signal sysregs_ack : std_logic; signal sysregs_err : std_logic; signal sysregs_dat_rd : unsigned(31 downto 0); signal center_f1 : unsigned(31 downto 0); signal center_f2 : unsigned(31 downto 0); signal center_f : unsigned(31 downto 0); signal rgb_1 : unsigned(23 downto 0); signal rgb_2 : unsigned(23 downto 0); signal p9813_rgb : unsigned(23 downto 0); signal rnrzl_enable : std_logic; -- Signals for bit synchronizer units signal speed_bit : std_logic; signal alex_kp : unsigned(31 downto 0); signal alex_ki : unsigned(31 downto 0); signal sync_0_idle : std_logic; signal sync_0_lock : std_logic; signal sync_0_dat : std_logic; signal sync_0_clk : std_logic; signal clk_in_r1 : std_logic; signal clk_in_r2 : std_logic; signal clk_out : std_logic; signal dat_out : std_logic; signal dat_in : std_logic; signal dat_rnrzl : std_logic; -- Signals for derandomizer signal derand_sr : unsigned(DERAND_BITS-1 downto 0); signal pcm_dr_taps : unsigned(DERAND_BITS-1 downto 0); -- Fun related signal larson_pulse_1 : std_logic; signal larson_pulse_2 : std_logic; signal c1 : unsigned(7 downto 0); signal c1_dir : std_logic; signal c2 : unsigned(7 downto 0); signal c2_dir : std_logic; -- Test related -- Signals for the randomizer and PN sequence generator signal pn_freq : unsigned(32 downto 0); signal pn_clk_pulse : std_logic; signal pn_seq : std_logic; signal rand_sr : unsigned(15 downto 0); signal rand_bit : std_logic; signal ber_bit : std_logic; signal ber_errors : unsigned(31 downto 0); signal ber_bits : unsigned(31 downto 0); signal ber_center_f1 : unsigned(31 downto 0); signal ber_center_f2 : unsigned(31 downto 0); signal ber_center_f : unsigned(31 downto 0); signal ber_rnrzl_enable : std_logic; ------------------------------------------------- begin -- instantiate an internal reset -- intrst : internal_reset -- PORT MAP ( -- nReset_o => sys_rst_l -- ); sys_rst_l <= '1'; -- Reset is not complicated sys_rst_n <= '0' when sys_rst_l='0' or sys_rst_n_i='0' else '1'; sys_rst <= '1' when sys_rst_l='0' or sys_rst_n_i='0' else '0'; -- This design uses a 50 MHz clock sys_clk <= sys_clk_ref; -- System clock enable currently not used. sys_clk_en <= '1'; ------------------------------ -- Assign LED outputs led_disp <= led_reg xor (c1 or c2); led <= not led_disp; ------------------------------ -- Invert switch inputs. On this board, active or "on" is low... switch_l <= not switch; ------------------------------ -- Provide a default of "high impedance" for all the potentially -- unused pins exp_io <= (others=>'Z'); ------------------------- -- A clock enable pulse c1_clkgen: entity work.dds_constant_squarewave generic map( OUTPUT_FREQ => 32.0, -- Desired output frequency SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate ACC_BITS => 32 -- Bit width of DDS phase accumulator ) port map( sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => sys_clk_en, -- Output pulse_o => larson_pulse_1, squarewave_o => open ); ------------------------- -- A clock enable pulse c2_clkgen: entity work.dds_constant_squarewave generic map( OUTPUT_FREQ => 16.2, -- Desired output frequency SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate ACC_BITS => 32 -- Bit width of DDS phase accumulator ) port map( sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => sys_clk_en, -- Output pulse_o => larson_pulse_2, squarewave_o => open ); -- Larson scanner #1 process (sys_clk,sys_rst_n) begin if (sys_rst_n='0') then c1 <= (0=>'1', others=>'0'); c1_dir <= '0'; elsif (sys_clk'event and sys_clk='1') then if (sys_clk_en='1') then if (larson_pulse_1='1') then if (c1_dir='0') then c1 <= c1(c1'length-2 downto 0) & '0'; if (c1="01000000") then c1_dir <= '1'; end if; else c1 <= '0' & c1(c1'length-1 downto 1); if (c1="00000010") then c1_dir <= '0'; end if; end if; end if; end if; end if; end process; -- Larson scanner #2 process (sys_clk,sys_rst_n) begin if (sys_rst_n='0') then c2 <= (0=>'1', others=>'0'); c2_dir <= '0'; elsif (sys_clk'event and sys_clk='1') then if (sys_clk_en='1') then if (larson_pulse_2='1') then if (c2_dir='0') then c2 <= c2(c2'length-2 downto 0) & '0'; if (c2="01000000") then c2_dir <= '1'; end if; else c2 <= '0' & c2(c2'length-1 downto 1); if (c2="00000010") then c2_dir <= '0'; end if; end if; end if; end if; end if; end process; ------------------------------ -- This module generates a serial BAUD clock automatically. -- The unit synchronizes on the carriage return character, so the user -- only needs to press the "enter" key for serial communications to start -- working, no matter what BAUD rate and clk_i frequency are used, within -- reason, of course. auto_baud1 : entity work.auto_baud_with_tracking generic map( CLOCK_FACTOR => 1, -- Output is this factor times the baud rate FPGA_CLKRATE => SYS_CLK_RATE, -- FPGA system clock rate MIN_BAUDRATE => 19200.0, -- Minimum expected incoming Baud rate DELTA_THRESHOLD => 200 -- Measurement filter constraint. Smaller = tougher. ) port map( sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => sys_clk_en, -- rate and parity rx_parity_i => "00", -- 0=none, 1=even, 2=odd -- serial input rx_stream_i => uart_0_rx_i, -- Output baud_lock_o => syscon_baud_lock, baud_clk_o => syscon_baud_clk ); -- ascii_syscon mounted with a UART interface syscon_1 : entity work.async_syscon generic map( ECHO_COMMANDS => 1, -- set nonzero to echo back command characters ADR_DIGITS => 8, -- # of hex digits for address DAT_DIGITS => 8, -- # of hex digits for data QTY_DIGITS => 4, -- # of hex digits for quantity CMD_BUFFER_SIZE => 64, -- # of chars in the command buffer WATCHDOG_VALUE => 20, -- # of sys_clks before ack is expected DISPLAY_FIELDS => 4 -- # of fields/line ) port map( sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => sys_clk_en, -- rate and parity parity_i => "00", -- 0=none, 1=even, 2=odd baud_clk_i => syscon_baud_clk, -- At 1x the desired baud rate, can be squarewave or pulses. baud_lock_i => syscon_baud_lock, -- '1' Indicates baud clock is stable and ready. -- Serial IO cmd_i => uart_0_rx_i, resp_o => uart_0_tx_o, cmd_done_o => open, -- Master Bus IO master_bg_i => '1', master_ack_o => open, master_adr_i => to_unsigned(0,32), master_dat_i => to_unsigned(0,32), master_dat_o => open, master_stb_i => '0', master_we_i => '0', master_br_o => open, -- System Bus IO ack_i => syscon_ack, err_i => syscon_err, dat_i => syscon_dat_rd, dat_o => syscon_dat_wr, rst_o => syscon_rst, stb_o => open, cyc_o => syscon_cyc, adr_o => syscon_adr, we_o => syscon_we ); -------------------------- -- syscon bus selection -- -------------------------- with to_integer(syscon_adr(31 downto 24)) select syscon_dat_rd <= bram_dat_rd when 2, reg_dat_rd when 3, str2u("01234567",32) when others; with to_integer(syscon_adr(31 downto 24)) select syscon_ack <= bram_ack when 2, reg_ack when 3, '1' when others; with to_integer(syscon_adr(31 downto 24)) select syscon_err <= bram_err when 2, reg_err when 3, syscon_cyc when others; sel_bram <= '1' when syscon_cyc='1' and to_integer(syscon_adr(31 downto 24))=2 else '0'; sel_reg <= '1' when syscon_cyc='1' and to_integer(syscon_adr(31 downto 24))=3 else '0'; ---------------------------- -- register bus selection -- ---------------------------- with to_integer(syscon_adr(23 downto 8)) select reg_dat_rd <= sysregs_dat_rd when 16#00FF#, str2u("11112222",32) when others; with to_integer(syscon_adr(23 downto 8)) select reg_ack <= sysregs_ack when 16#00FF#, '1' when others; with to_integer(syscon_adr(23 downto 8)) select reg_err <= sysregs_err when 16#00FF#, sel_reg when others; sel_sysregs <= '1' when sel_reg='1' and to_integer(syscon_adr(23 downto 8))=16#00FF# else '0'; ----------------------------- -- System Registers -- ----------------------------- with to_integer(syscon_adr(7 downto 0)) select sysregs_dat_rd <= center_f1 when 0, ber_center_f1 when 1, center_f2 when 2, ber_center_f2 when 3, to_unsigned(0,27) & speed_bit & "00" & ber_rnrzl_enable & rnrzl_enable when 4, resize(rgb_1,32) when 240, resize(rgb_2,32) when 241, ber_errors when 250, ber_bits when 251, to_unsigned(0,30) & sync_0_lock & sync_0_idle when 252, resize(switch_l,32) when 253, FPGA_VERSION when 254, resize(led_reg,32) when 255, syscon_adr(7 downto 0) & syscon_adr(7 downto 0) & syscon_adr(7 downto 0) & syscon_adr(7 downto 0) when others; with to_integer(syscon_adr(7 downto 0)) select sysregs_ack <= sel_sysregs when others; with to_integer(syscon_adr(7 downto 0)) select sysregs_err <= '0' when others; -------------------------- -- Bit Error Rate Counts proc_bert: Process(sys_rst_n,sys_clk) begin if (sys_rst_n = '0') then elsif (sys_clk'event AND sys_clk='1') then end if; end process; -- Handle writes to system registers process (sys_clk,sys_rst_n) begin if (sys_rst_n='0') then ber_errors <= (others=>'0'); ber_bits <= (others=>'0'); led_reg <= (others=>'0'); center_f1 <= to_unsigned(integer(128095.0*(2.0**10.0)/SYS_CLK_RATE*(2.0**23.0)),center_f1'length); ber_center_f1 <= to_unsigned(integer(128095.0*(2.0**10.0)/SYS_CLK_RATE*(2.0**23.0)),ber_center_f1'length); center_f2 <= to_unsigned(integer(2000000.0*(2.0**10.0)/SYS_CLK_RATE*(2.0**23.0)),center_f2'length); ber_center_f2 <= to_unsigned(integer(2000000.0*(2.0**10.0)/SYS_CLK_RATE*(2.0**23.0)),ber_center_f2'length); ber_rnrzl_enable <= '0'; rnrzl_enable <= '0'; rgb_1 <= str2u("802020",rgb_1'length); rgb_2 <= str2u("200080",rgb_2'length); elsif (sys_clk'event and sys_clk='1') then if (sys_clk_en='1') then if (sysregs_ack='1' and syscon_we='1') then case to_integer(syscon_adr(7 downto 0)) is when 0 => center_f1 <= syscon_dat_wr; when 1 => ber_center_f1 <= syscon_dat_wr; when 2 => center_f2 <= syscon_dat_wr; when 3 => ber_center_f2 <= syscon_dat_wr; when 4 => rnrzl_enable <= syscon_dat_wr(0); ber_rnrzl_enable <= syscon_dat_wr(1); when 240 => rgb_1 <= syscon_dat_wr(rgb_1'length-1 downto 0); when 241 => rgb_2 <= syscon_dat_wr(rgb_2'length-1 downto 0); when 250 => ber_errors <= (others=>'0'); when 251 => ber_bits <= (others=>'0'); when 255 => led_reg <= syscon_dat_wr(led_reg'length-1 downto 0); when others => null; end case; end if; -- Increment the counters if there are data mismatches if (pn_clk_pulse='1') then ber_bits <= ber_bits+1; if (dat_out/=pn_seq) then ber_errors <= ber_errors+1; end if; end if; end if; -- sys_clk_en end if; -- sys_clk end process; --------------------------------------------------------- -- Acknowledge Signal for BRAM process (sys_clk,sys_rst_n) begin if (sys_rst_n='0') then bram_wait <= (others=>'0'); elsif (sys_clk'event and sys_clk='1') then if (sys_clk_en='1') then if sel_bram='1' and bram_ack='0' then bram_wait <= bram_wait+1; else bram_wait <= (others=>'0'); end if; end if; end if; end process; bram_ack <= '1' when (bram_wait=1 and sel_bram='1') else '0'; ---------------------------- -- RAM block selection -- ---------------------------- bram_dat_rd <= to_unsigned(16#1234#,bram_dat_rd'length); bram_err <= syscon_cyc; -------------------------------- -- Digital Bit synchronizers -- -------------------------------- alex_kp <= to_unsigned(16#00094F59#,alex_kp'length); -- Alex DPLL kp factor alex_ki <= to_unsigned(16#00000793#,alex_ki'length); -- Alex DPLL ki factor bit_sync_0 : entity work.bit_sync_digital generic map( ALEX_K_BITS => ALEX_K_BITS, -- Number of bits in Alexander DPLL coefficients ALEX_K_FRAC => ALEX_K_FRAC, -- How many of the ALEX_K_BITS are used for fractional representation ALEX_GAIN_ADJ => ALEX_GAIN_ADJ, -- How many bits to reduce KP_i and KI_i during lock FSTEP_FINE => 1, -- Frequency increment during phase track PHASE_WIDTH => 33, -- Bits in the phase accumulator LOCK_VAL => 4, -- Period mismatch to obtain lock DROP_LOCK_VAL => 12, -- Period mismatch to drop lock PERIOD_I_WIDTH => 16, -- Integer width of period measurements PERIOD_F_WIDTH => 2, -- Fractional width of period measurements IDLE_CLOCKS => 2**16, -- sys_clk periods before signal is called idle BAUD_READS => 127, -- Period baud interval read attempts INTERVAL_READS => 64, -- Period interval read attempts WINDOW_SIZE => 3 -- Period variation window, in sys_clks ) port map( -- System Clock and Clock Enable sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => sys_clk_en, -- Frequency calibration clk enable cal_clk_en => '1', -- Calibration in Hz removed. Units are now (Fsys_clk/2^33) Hz. -- Settings freq_i => center_f, freq_seek_i => '0', use_alex_i => '0', alex_kp_i => alex_kp(ALEX_K_BITS-ALEX_K_FRAC-1 downto 0), alex_ki_i => alex_ki(ALEX_K_BITS-ALEX_K_FRAC-1 downto 0), -- Reference data input dat_i => dat_in, -- indicators and outputs idle_o => sync_0_idle, lock_o => sync_0_lock, dat_o => sync_0_dat, clk_o => sync_0_clk ); -------------------------- -- Derandomizer shift register pcm_dr_taps <= to_unsigned(16#6000#,pcm_dr_taps'length); proc_derand_sr: Process(sys_rst_n,sys_clk) begin if (sys_rst_n = '0') then derand_sr <= (others=>'0'); clk_in_r1 <= '0'; clk_in_r2 <= '0'; dat_rnrzl <= '0'; elsif (sys_clk'event AND sys_clk='1') then clk_in_r1 <= sync_0_clk; clk_in_r2 <= clk_in_r1; if (clk_in_r1='0' and clk_in_r2='1') then -- falling edge derand_sr <= derand_sr(derand_sr'length-2 downto 0) & sync_0_dat; -- Latch outputs in synchronism with clock edge dat_rnrzl <= sync_0_dat xor u_recursive_parity(derand_sr and pcm_dr_taps); end if; end if; end process; clk_out <= clk_in_r2; -- Obtain data input from desired pins dat_in <= exp_io(32); -- Select which data goes out dat_out <= dat_rnrzl when rnrzl_enable='1' else sync_0_dat; -- Map outputs to desired pins exp_io(35) <= dat_out; exp_io(34) <= clk_out; exp_io(36) <= dat_out; exp_io(37) <= not dat_out; exp_io(38) <= clk_out; exp_io(39) <= not clk_out; -------------------------- -- For test purposes, generate a PN sequence and randomize it. -- Send it out on a pin, for use in testing the bit synchronizer. -- Check the bit synchronized data against the generated data, -- and count the total bits and the errors, if any. ------------------------- -- A clock enable pulse for use with PN sequence and randomizer pn_freq <= '0' & ber_center_f; pn_clkgen : entity work.dds_squarewave generic map( ACC_BITS => 33 -- Bit width of DDS phase accumulator ) port map( sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => '1', -- Frequency setting freq_i => pn_freq, -- Output pulse_o => pn_clk_pulse, squarewave_o => open ); ------------------------------------------------------------------------ -- Instantiate a maximum-cycle linear feedback shift register -- which generates a pseudo-noise sequence pn_0 : entity work.mlfsr generic map( POLY_A => 32, -- Polynomial tap, also number of bits in shift register POLY_B => 30, -- Polynomial tap, less than POLY_A POLY_C => 26, -- Polynomial tap, less than POLY_B POLY_D => 25 -- Polynomial tap, less than POLY_C ) port map( -- System Clock and Clock Enable sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => pn_clk_pulse, -- Sequence Output pn_seq_o => pn_seq ); -------------------------- -- Randomizer shift register proc_rand_sr: Process(sys_rst_n,sys_clk) begin if (sys_rst_n = '0') then rand_sr <= (others=>'0'); elsif (sys_clk'event AND sys_clk='1') then if (pn_clk_pulse='1') then rand_sr <= rand_sr(rand_sr'length-2 downto 0) & rand_bit; end if; end if; end process; rand_bit <= pn_seq xor u_recursive_parity(rand_sr and to_unsigned(16#6000#,16)); ber_bit <= rand_bit when ber_rnrzl_enable='1' else pn_seq; -- Provide outputs for testing exp_io(1) <= ber_bit; exp_io(2) <= not ber_bit; -- Create a colorful LED indicator -- Use it to indicate at what speed the bit synchronizer center frequency -- is set. The speed is set by a rocker switch. indicator : entity work.p9813_LED_chain_driver generic map( SCLK_FREQ => 2000000.0, -- Desired lpd8806 serial clock frequency UPDATE_FREQ => 200.0, -- Desired LED chain update frequency SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate N_LEDS => 1 -- Number of LEDs in chain ) port map( -- System Clock, Reset and Clock Enable sys_rst_n => sys_rst_n, sys_clk => sys_clk, sys_clk_en => '1', -- Selection of color information c_adr_o => open, red_i => p9813_rgb(23 downto 16), grn_i => p9813_rgb(15 downto 8), blu_i => p9813_rgb(7 downto 0), -- Output sclk_o => exp_io(5), sdat_o => exp_io(6) ); -- Obtain switch position speed_bit <= exp_io(11); -- Select settings based on the switch position p9813_rgb <= rgb_1 when speed_bit='0' else rgb_2; center_f <= center_f1 when speed_bit='0' else center_f2; ber_center_f <= ber_center_f1 when speed_bit='0' else ber_center_f2; end beh;