mwb
Junior Member level 2
Im taping out a chip that requires a robust serial-to-parallel converter. What is posted below seems to synthesize correctly but I have the following questions:
I use asynchronous resets because there are two clocks, p_clk and clk. clk shifts in the serial data, p_clk latches it out.
Async. resets obviously gives better timing and since I control the data-in, reset, p_clk and clk from off-chip, I don't think I will have problems with reset-recovery timing. I have to admit, reset-recovery time is a new concept to me, I mainly work on FPGA's and this is never an issue since the tools take that worry away. In this case, Im on my own synthesizing with standard cells and DC-shell.
Lastly, the shift-reg input:
looks like it might function more reliably if I reversed the order so that the output register vec_mod_slow_in is always defined since the synthesis tool does not support initial values:
The circuit synthesizes and functions perfectly. There is a two clk period lag before I can latch the data into the slow_registers but this is fine. It seems to improve timing, not exactly sure why.
I'd just like some opinions on this if anyone has any.
Thanks.
I use asynchronous resets because there are two clocks, p_clk and clk. clk shifts in the serial data, p_clk latches it out.
Async. resets obviously gives better timing and since I control the data-in, reset, p_clk and clk from off-chip, I don't think I will have problems with reset-recovery timing. I have to admit, reset-recovery time is a new concept to me, I mainly work on FPGA's and this is never an issue since the tools take that worry away. In this case, Im on my own synthesizing with standard cells and DC-shell.
Lastly, the shift-reg input:
Code:
sr(data_width - 1 downto 0) <= sr(data_width - 2 downto 0) & serial_data_in;
vec_mod_slow_in <= sr;
looks like it might function more reliably if I reversed the order so that the output register vec_mod_slow_in is always defined since the synthesis tool does not support initial values:
Code:
vec_mod_slow_in <= sr;
sr(data_width - 1 downto 0) <= sr(data_width - 2 downto 0) & serial_data_in;
The circuit synthesizes and functions perfectly. There is a two clk period lag before I can latch the data into the slow_registers but this is fine. It seems to improve timing, not exactly sure why.
I'd just like some opinions on this if anyone has any.
Thanks.
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use work.mwb.all;
entity WVFRM_GEN is
generic (
data_width : integer := 68;
bank_width : integer := 17;
num_banks : integer := 4
);
port (
clk : in std_logic;
p_clk : in std_logic;
serial_data_in : in std_logic;
reset : in std_logic;
serial_data_out : out std_logic;
vm_a_en : out std_logic_vector(11 downto 0);
vm_a_en_bar : out std_logic_vector(11 downto 0);
vm_b_en : out std_logic_vector(11 downto 0);
vm_b_en_bar : out std_logic_vector(11 downto 0);
vm_c_en : out std_logic_vector(11 downto 0);
vm_c_en_bar : out std_logic_vector(11 downto 0);
vm_d_en : out std_logic_vector(11 downto 0);
vm_d_en_bar : out std_logic_vector(11 downto 0);
vm_a_s_i : out std_logic;
vm_a_s_i_bar : out std_logic;
vm_b_s_i : out std_logic;
vm_b_s_i_bar : out std_logic;
vm_c_s_i : out std_logic;
vm_c_s_i_bar : out std_logic;
vm_d_s_i : out std_logic;
vm_d_s_i_bar : out std_logic;
vm_a_sign_i_lsb : out std_logic;
vm_a_sign_i_lsb_bar : out std_logic;
vm_b_sign_i_lsb : out std_logic;
vm_b_sign_i_lsb_bar : out std_logic;
vm_c_sign_i_lsb : out std_logic;
vm_c_sign_i_lsb_bar : out std_logic;
vm_d_sign_i_lsb : out std_logic;
vm_d_sign_i_lsb_bar : out std_logic;
vm_a_s_q : out std_logic;
vm_a_s_q_bar : out std_logic;
vm_b_s_q : out std_logic;
vm_b_s_q_bar : out std_logic;
vm_c_s_q : out std_logic;
vm_c_s_q_bar : out std_logic;
vm_d_s_q : out std_logic;
vm_d_s_q_bar : out std_logic;
vm_a_sign_q_lsb : out std_logic;
vm_a_sign_q_lsb_bar : out std_logic;
vm_b_sign_q_lsb : out std_logic;
vm_b_sign_q_lsb_bar : out std_logic;
vm_c_sign_q_lsb : out std_logic;
vm_c_sign_q_lsb_bar : out std_logic;
vm_d_sign_q_lsb : out std_logic;
vm_d_sign_q_lsb_bar : out std_logic;
vm_a_sign_msb : out std_logic;
vm_a_sign_msb_bar : out std_logic;
vm_b_sign_msb : out std_logic;
vm_b_sign_msb_bar : out std_logic;
vm_c_sign_msb : out std_logic;
vm_c_sign_msb_bar : out std_logic;
vm_d_sign_msb : out std_logic;
vm_d_sign_msb_bar : out std_logic
);
end entity WVFRM_GEN;
architecture behavioral of WVFRM_GEN is
signal sr : std_logic_vector(data_width - 1 downto 0) := (others => '0');
signal serial_out : std_logic := '0';
-----------------------------------------------------------------------------
signal vec_mod_slow_in : std_logic_vector(data_width - 1 downto 0) := (others => '0');
signal parallel_out : std_logic_vector(data_width - 1 downto 0) := (others => '0');
signal vec_mod_out_reclk_1 : std_logic_vector(data_width - 1 downto 0) := (others => '0');
signal vec_mod_out_reclk_2 : std_logic_vector(data_width - 1 downto 0) := (others => '0');
signal vec_mod_out_reclk_post_mux : std_logic_vector(data_width - 1 downto 0) := (others => '0'); -- <[comment]>
-- signal test_pattern : std_logic_vector(data_width - 1 downto 0) := "11110000101000001011000011000000011101100101010000110010000100001001"; -- test pattern
begin -- behavioral
--- vec_mod_out_reclk_post_mux <= vec_mod_out_reclk_2 when output_enable = '1' else test_pattern;
vm_a_en <= vec_mod_out_reclk_2(67 downto 56);
vm_a_en_bar <= not vec_mod_out_reclk_2(67 downto 56);
vm_b_en <= vec_mod_out_reclk_2(50 downto 39);
vm_b_en_bar <= not vec_mod_out_reclk_2(50 downto 39);
vm_c_en <= vec_mod_out_reclk_2(33 downto 22);
vm_c_en_bar <= not vec_mod_out_reclk_2(33 downto 22);
vm_d_en <= vec_mod_out_reclk_2(16 downto 5);
vm_d_en_bar <= not vec_mod_out_reclk_2(16 downto 5);
vm_a_s_i <= vec_mod_out_reclk_2(55);
vm_a_s_i_bar <= not vec_mod_out_reclk_2(55);
vm_b_s_i <= vec_mod_out_reclk_2(38);
vm_b_s_i_bar <= not vec_mod_out_reclk_2(38);
vm_c_s_i <= vec_mod_out_reclk_2(21);
vm_c_s_i_bar <= not vec_mod_out_reclk_2(21);
vm_d_s_i <= vec_mod_out_reclk_2(4);
vm_d_s_i_bar <= not vec_mod_out_reclk_2(4);
vm_a_sign_i_lsb <= vec_mod_out_reclk_2(54);
vm_a_sign_i_lsb_bar <= not vec_mod_out_reclk_2(54);
vm_b_sign_i_lsb <= vec_mod_out_reclk_2(37);
vm_b_sign_i_lsb_bar <= not vec_mod_out_reclk_2(37);
vm_c_sign_i_lsb <= vec_mod_out_reclk_2(20);
vm_c_sign_i_lsb_bar <= not vec_mod_out_reclk_2(20);
vm_d_sign_i_lsb <= vec_mod_out_reclk_2(3);
vm_d_sign_i_lsb_bar <= not vec_mod_out_reclk_2(3);
vm_a_s_q <= vec_mod_out_reclk_2(53);
vm_a_s_q_bar <= not vec_mod_out_reclk_2(53);
vm_b_s_q <= vec_mod_out_reclk_2(36);
vm_b_s_q_bar <= not vec_mod_out_reclk_2(36);
vm_c_s_q <= vec_mod_out_reclk_2(19);
vm_c_s_q_bar <= not vec_mod_out_reclk_2(19);
vm_d_s_q <= vec_mod_out_reclk_2(2);
vm_d_s_q_bar <= not vec_mod_out_reclk_2(2);
vm_a_sign_q_lsb <= vec_mod_out_reclk_2(52);
vm_a_sign_q_lsb_bar <= not vec_mod_out_reclk_2(52);
vm_b_sign_q_lsb <= vec_mod_out_reclk_2(35);
vm_b_sign_q_lsb_bar <= not vec_mod_out_reclk_2(35);
vm_c_sign_q_lsb <= vec_mod_out_reclk_2(18);
vm_c_sign_q_lsb_bar <= not vec_mod_out_reclk_2(18);
vm_d_sign_q_lsb <= vec_mod_out_reclk_2(1);
vm_d_sign_q_lsb_bar <= not vec_mod_out_reclk_2(1);
vm_a_sign_msb <= vec_mod_out_reclk_2(51);
vm_a_sign_msb_bar <= not vec_mod_out_reclk_2(51);
vm_b_sign_msb <= vec_mod_out_reclk_2(34);
vm_b_sign_msb_bar <= not vec_mod_out_reclk_2(34);
vm_c_sign_msb <= vec_mod_out_reclk_2(17);
vm_c_sign_msb_bar <= not vec_mod_out_reclk_2(17);
vm_d_sign_msb <= vec_mod_out_reclk_2(0);
vm_d_sign_msb_bar <= not vec_mod_out_reclk_2(0);
dff_1 : process(p_clk, reset)
begin
if reset = '0' then
if rising_edge(p_clk) then
vec_mod_out_reclk_1 <= vec_mod_slow_in;
end if;
else
vec_mod_out_reclk_1 <= (others => '0');
end if;
end process dff_1;
dff_2 : process(p_clk, reset)
begin
if reset = '0' then
if rising_edge(p_clk) then
vec_mod_out_reclk_2 <= vec_mod_out_reclk_1;
end if;
else
vec_mod_out_reclk_2 <= (others => '0');
end if;
end process dff_2;
--vec_mod_out <= vec_mod_out_reclk_2;
--vec_mod_out_bar <= not vec_mod_out_reclk_2;
--fast_latch : process(clk, reset)
--begin
-- if reset = '0' then
-- -- need to double check these states and possible double-dff for the crossing clock domains.
-- if rising_edge(clk) then
-- vec_mod_slow_in <=
-- end if;
-- else
-- vec_mod_slow_in <= (others => '0');
-- end if;
--end process fast_latch;
serial_data_out <= serial_out;
serial_out <= sr(data_width - 1);
process(clk, reset)
begin
if reset = '0' then
if rising_edge(clk) then
sr(data_width - 1 downto 0) <= sr(data_width - 2 downto 0) & serial_data_in;
vec_mod_slow_in <= sr;
end if;
else
sr(data_width - 1 downto 0) <= (others => '0');
end if;
end process;
end behavioral;
Last edited by a moderator: