Merge pull request #77 from antonblanchard/timing

A number of timing fixes
jtag-port
Anton Blanchard 5 years ago committed by GitHub
commit 4174cd8e93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -222,7 +222,6 @@ begin
begin begin
if jtag_reset = '1' then if jtag_reset = '1' then
shiftr <= (others => '0'); shiftr <= (others => '0');
request <= (others => '0');
jtag_req <= '0'; jtag_req <= '0';
elsif rising_edge(jtag_clk) then elsif rising_edge(jtag_clk) then



@ -6,7 +6,9 @@ use UNISIM.vcomponents.all;


entity clock_generator is entity clock_generator is
generic ( generic (
clk_period_hz : positive := 12000000); CLK_INPUT_HZ : positive := 12000000;
CLK_OUTPUT_HZ : positive := 50000000
);
port ( port (
ext_clk : in std_logic; ext_clk : in std_logic;
pll_rst_in : in std_logic; pll_rst_in : in std_logic;
@ -22,28 +24,66 @@ architecture rtl of clock_generator is
clkfbout_mult : real range 2.0 to 64.0; clkfbout_mult : real range 2.0 to 64.0;
clkout_divide : real range 1.0 to 128.0; clkout_divide : real range 1.0 to 128.0;
divclk_divide : integer range 1 to 106; divclk_divide : integer range 1 to 106;
force_rst : std_ulogic;
end record; end record;


function gen_pll_settings ( function gen_pll_settings (
constant freq_hz : positive) constant input_hz : positive;
constant output_hz : positive)
return pll_settings_t is return pll_settings_t is

constant bad_settings : pll_settings_t :=
(clkin_period => 0.0,
clkfbout_mult => 2.0,
clkout_divide => 1.0,
divclk_divide => 1,
force_rst => '1');
begin begin
if freq_hz = 100000000 then case input_hz is
return (clkin_period => 10.0, when 100000000 =>
clkfbout_mult => 16.0, case output_hz is
clkout_divide => 32.0, when 100000000 =>
divclk_divide => 1); return (clkin_period => 10.0,
elsif freq_hz = 12000000 then clkfbout_mult => 16.0,
return (clkin_period => 83.33, clkout_divide => 16.0,
clkfbout_mult => 50.0, divclk_divide => 1,
clkout_divide => 12.0, force_rst => '0');
divclk_divide => 1); when 50000000 =>
else return (clkin_period => 10.0,
report "Unsupported input frequency" severity failure; clkfbout_mult => 16.0,
end if; clkout_divide => 32.0,
divclk_divide => 1,
force_rst => '0');
when others =>
report "Unsupported output frequency" severity failure;
return bad_settings;
end case;
when 12000000 =>
case output_hz is
when 100000000 =>
return (clkin_period => 83.33,
clkfbout_mult => 50.0,
clkout_divide => 6.0,
divclk_divide => 1,
force_rst => '0');
when 50000000 =>
return (clkin_period => 83.33,
clkfbout_mult => 50.0,
clkout_divide => 12.0,
divclk_divide => 1,
force_rst => '0');
when others =>
report "Unsupported output frequency" severity failure;
return bad_settings;
end case;
when others =>
report "Unsupported input frequency" severity failure;
return bad_settings;
end case;
end function gen_pll_settings; end function gen_pll_settings;


constant pll_settings : pll_settings_t := gen_pll_settings(clk_period_hz); constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz);
begin begin
pll : MMCME2_BASE pll : MMCME2_BASE
generic map ( generic map (
@ -71,6 +111,6 @@ begin
CLKFBIN => clkfb, CLKFBIN => clkfb,
CLKIN1 => ext_clk, CLKIN1 => ext_clk,
PWRDWN => '0', PWRDWN => '0',
RST => pll_rst_in RST => pll_rst_in or pll_settings.force_rst
); );
end architecture rtl; end architecture rtl;

@ -5,67 +5,89 @@ Library UNISIM;
use UNISIM.vcomponents.all; use UNISIM.vcomponents.all;


entity clock_generator is entity clock_generator is
generic ( generic (
clk_period_hz : positive := 100000000); CLK_INPUT_HZ : positive := 100000000;
port ( CLK_OUTPUT_HZ : positive := 100000000
ext_clk : in std_logic; );
pll_rst_in : in std_logic; port (
pll_clk_out : out std_logic; ext_clk : in std_logic;
pll_locked_out : out std_logic); pll_rst_in : in std_logic;
pll_clk_out : out std_logic;
pll_locked_out : out std_logic);
end entity clock_generator; end entity clock_generator;


architecture rtl of clock_generator is architecture rtl of clock_generator is
signal clkfb : std_ulogic;


signal clkfb : std_ulogic; type pll_settings_t is record
clkin_period : real range 0.000 to 52.631;
clkfbout_mult : integer range 2 to 64;
clkout_divide : integer range 1 to 128;
divclk_divide : integer range 1 to 56;
force_rst : std_ulogic;
end record;


type pll_settings_t is record function gen_pll_settings (
clkin_period : real range 0.000 to 52.631; constant input_hz : positive;
clkfbout_mult : integer range 2 to 64; constant output_hz : positive)
clkout_divide : integer range 1 to 128; return pll_settings_t is
divclk_divide : integer range 1 to 56;
end record;


function gen_pll_settings ( constant bad_settings : pll_settings_t :=
constant freq_hz : positive) (clkin_period => 0.0,
return pll_settings_t is clkfbout_mult => 2,
begin clkout_divide => 1,
if freq_hz = 100000000 then divclk_divide => 1,
return (clkin_period => 10.0, force_rst => '1');
clkfbout_mult => 16, begin
clkout_divide => 32, case input_hz is
divclk_divide => 1); when 100000000 =>
else case output_hz is
report "Unsupported input frequency" severity failure; when 100000000 =>
-- return (clkin_period => 0.0, return (clkin_period => 10.0,
-- clkfbout_mult => 0, clkfbout_mult => 16,
-- clkout_divide => 0, clkout_divide => 16,
-- divclk_divide => 0); divclk_divide => 1,
end if; force_rst => '0');
end function gen_pll_settings; when 50000000 =>
return (clkin_period => 10.0,
clkfbout_mult => 16,
clkout_divide => 32,
divclk_divide => 1,
force_rst => '0');
when others =>
report "Unsupported output frequency" severity failure;
return bad_settings;
end case;
when others =>
report "Unsupported input frequency" severity failure;
return bad_settings;
end case;
end function gen_pll_settings;


constant pll_settings : pll_settings_t := gen_pll_settings(clk_period_hz); constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz);
begin begin


pll : PLLE2_BASE pll : PLLE2_BASE
generic map ( generic map (
BANDWIDTH => "OPTIMIZED", BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => pll_settings.clkfbout_mult, CLKFBOUT_MULT => pll_settings.clkfbout_mult,
CLKIN1_PERIOD => pll_settings.clkin_period, CLKIN1_PERIOD => pll_settings.clkin_period,
CLKOUT0_DIVIDE => pll_settings.clkout_divide, CLKOUT0_DIVIDE => pll_settings.clkout_divide,
DIVCLK_DIVIDE => pll_settings.divclk_divide, DIVCLK_DIVIDE => pll_settings.divclk_divide,
STARTUP_WAIT => "FALSE") STARTUP_WAIT => "FALSE")
port map ( port map (
CLKOUT0 => pll_clk_out, CLKOUT0 => pll_clk_out,
CLKOUT1 => open, CLKOUT1 => open,
CLKOUT2 => open, CLKOUT2 => open,
CLKOUT3 => open, CLKOUT3 => open,
CLKOUT4 => open, CLKOUT4 => open,
CLKOUT5 => open, CLKOUT5 => open,
CLKFBOUT => clkfb, CLKFBOUT => clkfb,
LOCKED => pll_locked_out, LOCKED => pll_locked_out,
CLKIN1 => ext_clk, CLKIN1 => ext_clk,
PWRDWN => '0', PWRDWN => '0',
RST => pll_rst_in, RST => pll_rst_in or pll_settings.force_rst,
CLKFBIN => clkfb); CLKFBIN => clkfb);


end architecture rtl; end architecture rtl;

@ -5,7 +5,9 @@ entity toplevel is
generic ( generic (
MEMORY_SIZE : positive := 524288; MEMORY_SIZE : positive := 524288;
RAM_INIT_FILE : string := "firmware.hex"; RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true RESET_LOW : boolean := true;
CLK_INPUT : positive := 100000000;
CLK_FREQUENCY : positive := 100000000
); );
port( port(
ext_clk : in std_ulogic; ext_clk : in std_ulogic;
@ -43,6 +45,10 @@ begin
); );


clkgen: entity work.clock_generator clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => CLK_INPUT,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map( port map(
ext_clk => ext_clk, ext_clk => ext_clk,
pll_rst_in => pll_rst, pll_rst_in => pll_rst,

@ -26,6 +26,10 @@ architecture behave of loadstore2 is
signal l_saved : Loadstore1ToLoadstore2Type; signal l_saved : Loadstore1ToLoadstore2Type;
signal w_tmp : Loadstore2ToWritebackType; signal w_tmp : Loadstore2ToWritebackType;
signal m_tmp : wishbone_master_out; signal m_tmp : wishbone_master_out;
signal read_data : std_ulogic_vector(63 downto 0);
signal read_data_shift : std_ulogic_vector(2 downto 0);
signal sign_extend_byte_reverse: std_ulogic_vector(1 downto 0);
signal dlength : std_ulogic_vector(3 downto 0);


type state_t is (IDLE, WAITING_FOR_READ_ACK, WAITING_FOR_WRITE_ACK); type state_t is (IDLE, WAITING_FOR_READ_ACK, WAITING_FOR_WRITE_ACK);
signal state : state_t := IDLE; signal state : state_t := IDLE;
@ -56,21 +60,53 @@ architecture behave of loadstore2 is
return std_ulogic_vector(shift_left(unsigned(length_to_sel(size)), to_integer(unsigned(address(2 downto 0))))); return std_ulogic_vector(shift_left(unsigned(length_to_sel(size)), to_integer(unsigned(address(2 downto 0)))));
end function wishbone_data_sel; end function wishbone_data_sel;
begin begin

loadstore2_1: process(all)
variable tmp : std_ulogic_vector(63 downto 0);
variable data : std_ulogic_vector(63 downto 0);
begin
tmp := std_logic_vector(shift_right(unsigned(read_data), to_integer(unsigned(read_data_shift)) * 8));
data := (others => '0');
case to_integer(unsigned(dlength)) is
when 0 =>
when 1 =>
data(7 downto 0) := tmp(7 downto 0);
when 2 =>
data(15 downto 0) := tmp(15 downto 0);
when 4 =>
data(31 downto 0) := tmp(31 downto 0);
when 8 =>
data(63 downto 0) := tmp(63 downto 0);
when others =>
assert false report "invalid length" severity failure;
data(63 downto 0) := tmp(63 downto 0);
end case;

case sign_extend_byte_reverse is
when "10" =>
w_tmp.write_data <= sign_extend(data, to_integer(unsigned(l_saved.length)));
when "01" =>
w_tmp.write_data <= byte_reverse(data, to_integer(unsigned(l_saved.length)));
when others =>
w_tmp.write_data <= data;
end case;
end process;

w_out <= w_tmp; w_out <= w_tmp;
m_out <= m_tmp; m_out <= m_tmp;


loadstore2_0: process(clk) loadstore2_0: process(clk)
variable tmp : std_ulogic_vector(63 downto 0);
variable data : std_ulogic_vector(63 downto 0);
variable sign_extend_byte_reverse : std_ulogic_vector(1 downto 0);
begin begin
if rising_edge(clk) then if rising_edge(clk) then
tmp := (others => '0');
data := (others => '0');


w_tmp <= Loadstore2ToWritebackInit; w_tmp.valid <= '0';
w_tmp.write_enable <= '0';
w_tmp.write_reg <= (others => '0');


l_saved <= l_saved; l_saved <= l_saved;
read_data_shift <= "000";
sign_extend_byte_reverse <= "00";
dlength <= "1000";


case_0: case state is case_0: case state is
when IDLE => when IDLE =>
@ -95,15 +131,14 @@ begin
if l_in.update = '1' then if l_in.update = '1' then
w_tmp.write_enable <= '1'; w_tmp.write_enable <= '1';
w_tmp.write_reg <= l_in.update_reg; w_tmp.write_reg <= l_in.update_reg;
w_tmp.write_data <= l_in.addr; read_data <= l_in.addr;
end if; end if;


state <= WAITING_FOR_READ_ACK; state <= WAITING_FOR_READ_ACK;
else else
m_tmp.we <= '1'; m_tmp.we <= '1';


data := l_in.data; m_tmp.dat <= std_logic_vector(shift_left(unsigned(l_in.data), wishbone_data_shift(l_in.addr)));
m_tmp.dat <= std_logic_vector(shift_left(unsigned(data), wishbone_data_shift(l_in.addr)));


assert l_in.sign_extend = '0' report "sign extension doesn't make sense for stores" severity failure; assert l_in.sign_extend = '0' report "sign extension doesn't make sense for stores" severity failure;


@ -113,32 +148,10 @@ begin


when WAITING_FOR_READ_ACK => when WAITING_FOR_READ_ACK =>
if m_in.ack = '1' then if m_in.ack = '1' then
tmp := std_logic_vector(shift_right(unsigned(m_in.dat), wishbone_data_shift(l_saved.addr))); read_data <= m_in.dat;
case to_integer(unsigned(l_saved.length)) is read_data_shift <= l_saved.addr(2 downto 0);
when 0 => dlength <= l_saved.length;
when 1 => sign_extend_byte_reverse <= l_saved.sign_extend & l_saved.byte_reverse;
data(7 downto 0) := tmp(7 downto 0);
when 2 =>
data(15 downto 0) := tmp(15 downto 0);
when 4 =>
data(31 downto 0) := tmp(31 downto 0);
when 8 =>
data(63 downto 0) := tmp(63 downto 0);
when others =>
assert false report "invalid length" severity failure;
end case;

sign_extend_byte_reverse := l_saved.sign_extend & l_saved.byte_reverse;

case sign_extend_byte_reverse is
when "10" =>
data := sign_extend(data, to_integer(unsigned(l_saved.length)));
when "01" =>
data := byte_reverse(data, to_integer(unsigned(l_saved.length)));
when others =>
end case;

w_tmp.write_data <= data;


-- write data to register file -- write data to register file
w_tmp.valid <= '1'; w_tmp.valid <= '1';
@ -155,7 +168,7 @@ begin
if l_saved.update = '1' then if l_saved.update = '1' then
w_tmp.write_enable <= '1'; w_tmp.write_enable <= '1';
w_tmp.write_reg <= l_saved.update_reg; w_tmp.write_reg <= l_saved.update_reg;
w_tmp.write_data <= l_saved.addr; read_data <= l_saved.addr;
end if; end if;


m_tmp <= wishbone_master_out_init; m_tmp <= wishbone_master_out_init;

@ -81,7 +81,11 @@ targets:
nexys_a7: nexys_a7:
default_tool: vivado default_tool: vivado
filesets: [core, nexys_a7, soc, fpga, debug_xilinx] filesets: [core, nexys_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file] parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools: tools:
vivado: {part : xc7a100tcsg324-1} vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel toplevel : toplevel
@ -89,7 +93,11 @@ targets:
nexys_video: nexys_video:
default_tool: vivado default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx] filesets: [core, nexys_video, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file] parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools: tools:
vivado: {part : xc7a200tsbg484-1} vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel toplevel : toplevel
@ -97,7 +105,11 @@ targets:
arty_a7-35: arty_a7-35:
default_tool: vivado default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx] filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file] parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools: tools:
vivado: {part : xc7a35ticsg324-1L} vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel toplevel : toplevel
@ -105,7 +117,11 @@ targets:
arty_a7-100: arty_a7-100:
default_tool: vivado default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx] filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file] parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools: tools:
vivado: {part : xc7a100ticsg324-1L} vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel toplevel : toplevel
@ -113,7 +129,11 @@ targets:
cmod_a7-35: cmod_a7-35:
default_tool: vivado default_tool: vivado
filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx] filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file, reset_low=false] parameters :
- memory_size
- ram_init_file
- reset_low=false
- clk_input=12000000
tools: tools:
vivado: {part : xc7a35tcpg236-1} vivado: {part : xc7a35tcpg236-1}
toplevel : toplevel toplevel : toplevel
@ -139,3 +159,15 @@ parameters:
datatype : bool datatype : bool
description : External reset button polarity description : External reset button polarity
paramtype : generic paramtype : generic

clk_input:
datatype : int
description : Clock input frequency in HZ (for top-generic based boards)
paramtype : generic
default : 100000000

clk_frequency:
datatype : int
description : Generated system clock frequency in HZ (for top-generic based boards)
paramtype : generic
default : 50000000

@ -10,7 +10,7 @@ use work.crhelpers.all;


entity multiply is entity multiply is
generic ( generic (
PIPELINE_DEPTH : natural := 2 PIPELINE_DEPTH : natural := 16
); );
port ( port (
clk : in std_logic; clk : in std_logic;

Loading…
Cancel
Save