-
Notifications
You must be signed in to change notification settings - Fork 5
/
sipo.vhdl
103 lines (85 loc) · 4.28 KB
/
sipo.vhdl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
--------------------------------------------------------------------------------
-- Copyright (C) 2018 Dominik Salvet
-- SPDX-License-Identifier: MIT
--------------------------------------------------------------------------------
-- Compliant: IEEE Std 1076-1993
-- Target: independent
--------------------------------------------------------------------------------
-- Description:
-- The file represents the description of a Serial-In, Parallel-Out module.
-- It can be set up to operate in LSB-first mode or MSB-first mode.
--------------------------------------------------------------------------------
-- Notes:
-- 1. No buffer for parallel data output is used, so it has to be checked
-- the o_data_valid indicator before read.
-- 2. For continuous reading the serial input data as a stream, assign '1'
-- to i_data_start. Then the o_data_valid output will have '1' only for
-- one i_clk period.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.verif_pkg.all;
entity sipo is
generic (
g_DATA_WIDTH : integer range 2 to integer'high := 4; -- output parallelized data width
-- least significant bit first of the serial input
g_LSB_FIRST : boolean := true
);
port (
i_clk : in std_ulogic; -- clock signal
i_rst : in std_ulogic; -- reset signal
i_data_start : in std_ulogic; -- start of the serial input data
i_data : in std_ulogic; -- current bit of the serial input data
o_data_valid : out std_ulogic; -- output data validity
o_data : out std_ulogic_vector(g_DATA_WIDTH - 1 downto 0) -- output parallelized data
);
end entity sipo;
architecture rtl of sipo is
signal r_receiving : boolean; -- receiving indicator
-- shifter register used for parallelize the serial input data
signal r_shifter : std_ulogic_vector(g_DATA_WIDTH - 1 downto 0);
begin
o_data <= r_shifter; -- the shifter is directly assigned to the output, see 1. note
-- Description:
-- Perform one conversion step. Basically it fills the shifter register to parallelize.
conversion_step : process (i_clk) is
variable r_received_count : integer range 0 to g_DATA_WIDTH - 1; -- number of received bits
begin
if (rising_edge(i_clk)) then
if (i_rst = '1') then -- initialize the module
o_data_valid <= '0';
r_receiving <= false;
r_received_count := 0;
else
if (i_data_start = '1' or r_receiving) then -- receive one bit
o_data_valid <= '0'; -- data are valid as long as not receiving
r_receiving <= true; -- begin the reading the serial input data
if (g_LSB_FIRST) then -- first least significant bit
r_shifter <= i_data & r_shifter(r_shifter'left downto 1);
else -- first most significant bit
r_shifter <= r_shifter(r_shifter'left - 1 downto 0) & i_data;
end if;
if (r_received_count = g_DATA_WIDTH - 1) then -- last received bit
o_data_valid <= '1'; -- data are valid after the receive
r_receiving <= false; -- stop receiving
r_received_count := 0; -- reset the received bits count
else -- not last received bit
r_received_count := r_received_count + 1; -- increment the received count
end if;
end if;
end if;
end if;
end process conversion_step;
-- rtl_synthesis off
input_prevention : process (i_clk) is
begin
if (rising_edge(i_clk)) then
if (i_data_start = '1' or r_receiving) then -- accept new data to the conversion
assert (contains_01(i_data))
report "Undefined i_data when receiving the serial input bits!"
severity failure;
end if;
end if;
end process input_prevention;
-- rtl_synthesis on
end architecture rtl;