Commit 39c86c8e authored by Tristan Gingold's avatar Tristan Gingold

Add gc_sync_word_wr module.

parent 47861ac6
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync_word_wr
--
-- description: Synchronizer for writing a word with an ack.
-- Used to transfer a word from the input clock domain to the output clock
-- domain. User provides the data and a pulse write signal to transfer the
-- data. When the data are transfered, a write pulse is generated on the
-- output side along with the data, and an acknowledge is geenrated on the
-- input side. Once the user request a transfer, no new data should be
-- requested for a transfer until the ack was received.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2019
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity gc_sync_word_wr is
generic (
width : positive := 8);
port (
-- Input clock and reset
clk_in_i : in std_logic;
rst_in_n_i : in std_logic;
-- Output clock.
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input data
data_i : in std_logic_vector (width - 1 downto 0);
-- Input wr
wr_i : in std_logic;
ack_o : out std_logic;
-- Output data
data_o : out std_logic_vector (width - 1 downto 0);
wr_o : out std_logic);
end entity;
architecture behav of gc_sync_word_wr is
signal data : std_logic_vector (width - 1 downto 0);
signal in_busy : std_logic;
signal in_progress : std_logic;
signal ack_start, ack_done : std_logic;
-- Synchronized extended wr_i signal.
signal wr_out : std_logic;
-- Internal pulse for wr_o, active one cycle before wr_o.
signal wr_out_p : std_logic;
begin
-- Handle incoming request.
process(clk_in_i)
begin
if rising_edge(clk_in_i) then
if rst_in_n_i = '0' then
in_progress <= '0';
in_busy <= '0';
data <= (others => '0');
ack_o <= '0';
else
ack_o <= '0';
if in_busy = '0' then
if wr_i = '1' then
in_progress <= '1';
in_busy <= '1';
data <= data_i;
end if;
else
assert wr_i = '0' report "request while previous one not completed"
severity error;
if ack_start = '1' then
in_progress <= '0';
end if;
if ack_done = '1' then
assert in_progress = '0';
in_busy <= '0';
ack_o <= '1';
end if;
end if;
end if;
end if;
end process;
cmp_wr_sync : entity work.gc_sync_ffs
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => in_progress,
synced_o => wr_out,
ppulse_o => wr_out_p);
-- Outputs.
process (clk_out_i)
begin
if rising_edge(clk_out_i) then
if rst_out_n_i = '0' then
data_o <= (others => '0');
wr_o <= '0';
else
if wr_out_p = '1' then
-- Data are stable.
data_o <= data;
wr_o <= '1';
else
wr_o <= '0';
end if;
end if;
end if;
end process;
-- Ack.
cmp_ack_sync : entity work.gc_sync_ffs
port map (
clk_i => clk_in_i,
rst_n_i => rst_in_n_i,
data_i => wr_out,
ppulse_o => ack_start,
npulse_o => ack_done);
end behav;
vlib work
vcom -explicit -93 "../../modules/common/gc_sync_ffs.vhd"
vcom -explicit -93 "../../modules/common/gc_sync_word_wr.vhd"
vcom -explicit -93 "tb_gc_sync_word_wr.vhd"
vsim -t 1ps -voptargs="+acc" -lib work work.tb_gc_sync_word_wr
radix -hexadecimal
#add wave *
do wave.do
run 4 us
wave zoomfull
library ieee;
use ieee.std_logic_1164.all;
entity tb_gc_sync_word_wr is
end;
architecture arch of tb_gc_sync_word_wr is
signal din, dout : std_logic_vector(7 downto 0);
signal clki, clko : std_logic := '0';
signal rsti, rsto : std_logic;
signal wri, wro : std_logic;
signal ack : std_logic;
begin
clki <= not clki after 10 ns;
clko <= not clko after 7 ns;
rsti <= '0', '1' after 30 ns;
rsto <= '0', '1' after 25 ns;
cmp_tb : entity work.gc_sync_word_wr
generic map (
width => 8)
port map (
clk_in_i => clki,
rst_in_n_i => rsti,
clk_out_i => clko,
rst_out_n_i => rsto,
data_i => din,
wr_i => wri,
ack_o => ack,
data_o => dout,
wr_o => wro);
process
procedure send_value (dat : std_logic_vector(7 downto 0)) is
begin
din <= dat;
wait until rising_edge(clki);
wri <= '1';
wait until rising_edge(clki);
wri <= '0';
end send_value;
-- Wait until ack.
procedure wait_ack is
begin
loop
wait until rising_edge(clki);
exit when ack = '1';
end loop;
end wait_ack;
begin
wri <= '0';
wait until rsti = '1';
wait until rising_edge(clki);
send_value(x"a5");
wait_ack;
send_value(x"7b");
wait_ack;
wait;
end process;
end arch;
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb_gc_sync_word_wr/din
add wave -noupdate /tb_gc_sync_word_wr/dout
add wave -noupdate /tb_gc_sync_word_wr/clki
add wave -noupdate /tb_gc_sync_word_wr/clko
add wave -noupdate /tb_gc_sync_word_wr/rsti
add wave -noupdate /tb_gc_sync_word_wr/rsto
add wave -noupdate /tb_gc_sync_word_wr/wri
add wave -noupdate /tb_gc_sync_word_wr/wro
add wave -noupdate /tb_gc_sync_word_wr/ack
add wave -noupdate /tb_gc_sync_word_wr/cmp_tb/in_busy
add wave -noupdate /tb_gc_sync_word_wr/cmp_tb/in_progress
add wave -noupdate /tb_gc_sync_word_wr/cmp_tb/ack_start
add wave -noupdate /tb_gc_sync_word_wr/cmp_tb/ack_done
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {0 ps} 0}
quietly wave cursor active 0
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ps
update
WaveRestoreZoom {0 ps} {262500 ps}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment