时序逻辑实验

实验一:序列检测器

实验代码:

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
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

entity seq_detector is
port(x, clk: in std_logic;
y: out std_logic);
end seq_detector;

architecture utility of seq_detector is
type state is (s0, s1, s2, s3, s4, s5, s6, s7);
signal current_s, next_s: state;
begin

process(clk)
begin
if clk'event and clk = '1' then
current_s <= next_s;
end if;
end process;

process(x, current_s)
begin
case current_s is
when s0 => y <= '0';
if x='1' then
next_s <= s1;
else
next_s <= s0;
end if;
when s1 => y <= '0';
if x='1' then
next_s <= s2;
else
next_s <= s0;
end if;
when s2 => y <= '0';
if x='1' then
next_s <= s3;
else
next_s <= s0;
end if;
when s3 => y <= '0';
if x='1' then
next_s <= s3;
else
next_s <= s4;
end if;
when s4 => y <= '0';
if x='1' then
next_s <= s1;
else
next_s <= s5;
end if;
when s5 => y <= '0';
if x='1' then
next_s <= s6;
else
next_s <= s1;
end if;
when s6 => y <= '0';
if x='1' then
next_s <= s2;
else
next_s <= s7;
end if;
when s7 => y <= '1';
if x='1' then
next_s <= s1;
else
next_s <= s0;
end if;
end case;
end process;

end utility;

代码释义:

  • 代码实现了一个1110010序列检测器,状态转移图如下:
  • clk的process表示上升沿触发,也可以调用库函数来实现(在计数器中有所使用)。

    波形结果:

    波形解读:

  • 30 ~ 150ns,x输入为1110010,因此y在第150ns(此时clk为上升沿)由0变1,之后x输入0,y由1下降为0
  • 230 ~ 370ns,x输入为11110010,后7位符合条件,因此y由0变1,之后x输入0,y由1下降为0。

实验二:计数器

实验代码:

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
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity counter_4 is
port (
clk : in std_logic;
rst : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;

architecture rtl of counter_4 is
signal cnt : std_logic_vector(3 downto 0) := "0000";
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
cnt <= "0000";
else
cnt <= cnt + 1;
end if;
end if;
end process;

count <= cnt;
end architecture;

代码释义:

  • moore型计数器,通过rising_edge函数实现clk上升沿触发,在每次加1,达到1111后的一次上升沿变为0000。有人工复位输入接口rst

    波形结果:

    波形解读:

  • 0 ~ 160ns,计数器正常运行,完成一个计数周期。
  • 160ns时刻,计数器归0
  • 190 ~ 210ns,rst输入为1,人工复位为0000。

    实验三:8位寄存器74374

    实验代码:

    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
    library ieee;
    use ieee.std_logic_1164.all;

    entity register_8bit is
    port(
    D:in std_logic_vector(7 downto 0);
    CLK,OE:in std_logic;
    Q:out std_logic_vector(7 downto 0)
    );
    end register_8bit;

    architecture arch of register_8bit is
    signal current_data: std_logic_vector(7 downto 0);
    begin

    process(CLK)
    begin
    if clk'event and clk = '1' then
    current_data <= D;
    end if;
    end process;

    process(D,OE)
    begin
    if OE = '0' then
    Q <= current_data;
    else
    Q <= "ZZZZZZZZ";
    end if;
    end process;

    end arch;

    代码释义:

  • D表示输入,Q表示输出,architecture中的current_data表示寄存器现有数据。process(CLK)实现上升沿触发,process(D,OE)实现寄存器数据传递以及使能端控制高阻态。

    波形结果:

    波形解读:

  • 0 ~ 40ns,OE=1,输出维持高阻态。
  • 40 ~ 100ns,OE=0,随clk上升沿更新寄存器数据。
  • 100 ~ 160ns,虽然D输入变化多次,但仅在clk上升沿寄存器才读取数据,其他时间保持寄存器数据和输出不变。

组合逻辑实验

实验一:8421码和格雷码的转换

实验代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
library ieee;
use ieee.std_logic_1164.all;

entity gray_8421 is
port (inp: in std_logic_vector(3 downto 0);
outp: out std_logic_vector(3 downto 0));
end gray_8421;

architecture arch of gray_8421 is
begin
outp(3) <= inp(3);
outp(2) <= inp(3) xor inp(2);
outp(1) <= inp(2) xor inp(1);
outp(0) <= inp(1) xor inp(0);
end arch;

代码释义:

  • 这段代码实现的是将输入的4位二进制码转换为4位格雷码。其中,格雷码是一种二进制编码方式,相邻两个数值之间仅有一位二进制数不同。这种编码方式可以用于减少数字转换时的误差和噪声。
  • 格雷码的生成方式是通过将二进制码的每一位与其前一位进行异或运算得到的。在这段代码中,首先将输入的第3位二进制码直接赋值给输出的第3位格雷码。然后,将输入的第3位和第2位二进制码进行异或运算,并将结果赋值给输出的第2位格雷码。接着,将输入的第2位和第1位二进制码进行异或运算,并将结果赋值给输出的第1位格雷码。最后,将输入的第1位和第0位二进制码进行异或运算,并将结果赋值给输出的第0位格雷码。

例如,对于二进制码1001,其对应的格雷码为1100。这是因为:

波形结果:

波形解读:

  • 输入inp随机输入二进制码,结果outp输出为对应格雷码

实验二:数值比较器

实验代码:

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
library IEEE;
use IEEE.std_logic_1164.all;

entity comparer is
port (A,B: in std_logic_vector(3 downto 0);
YA,YB,YC: out std_logic);
end comparer;

architecture comparer_arch of comparer is
begin
process(A,B)
begin
if A(3)>B(3) then
YA <= '1';
YB <= '0';
YC <= '0';
elsif A(3)<B(3) then
YA <= '0';
YB <= '1';
YC <= '0';
else
if A(2)>B(2) then
YA <= '1';
YB <= '0';
YC <= '0';
elsif A(2)<B(2) then
YA <= '0';
YB <= '1';
YC <= '0';
else
if A(1)>B(1) then
YA <= '1';
YB <= '0';
YC <= '0';
elsif A(1)<B(1) then
YA <= '0';
YB <= '1';
YC <= '0';
else
if A(0)>B(0) then
YA <= '1';
YB <= '0';
YC <= '0';
elsif A(0)<B(0) then
YA <= '0';
YB <= '1';
YC <= '0';
else
YA <= '0';
YB <= '0';
YC <= '1';
end if;
end if;
end if;
end if;
end process;
end comparer_arch;

代码释义:

  • 通过if逻辑语句实现对每一位大小的判断,若相等,则依靠下一位判断,如有需求,最后一位还可以增加三个输入去判断实现元器件叠加使用的功能,但实验并无要求,遂没有实现。如需要实现也很简单,更改else语句为后位数判断结果即可。

波形结果:

波形解读:

  • A与B为随机输入的二进制码,其波形如图所示。A > B则YA输出1,其余输出0;A < B则YB输出1,其余输出0;A = B则YC输出1,其余输出0。

实验三:全加器

实验代码:

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
library ieee;
use ieee.std_logic_1164.all;

entity half_adder is
port(ain,bin: in std_logic; cout, sout: out std_logic);
end half_adder;

architecture half_adder_arch of half_adder is
begin
sout <= ain xor bin;
cout <= ain and bin;
end half_adder_arch;

library ieee;
use ieee.std_logic_1164.all;

entity full_adder is
port (input_a, input_b, carry_in : in std_logic; carry_out, sum_out : out std_logic);
end full_adder;

architecture full_adder_arch of full_adder is
signal carry_1 : std_logic;
signal carry_2 : std_logic;
signal sum_1 : std_logic;
component half_adder
port(ain,bin: in std_logic; cout, sout: out std_logic);
end component;
begin
ha1: half_adder port map (ain => input_a, bin => input_b, sout => sum_1, cout => carry_1);
ha2: half_adder port map (ain => sum_1, bin => carry_in, sout => sum_out, cout => carry_2);
carry_out <= carry_1 or carry_2;
end full_adder_arch;

代码释义:

  • 代码实现了两个实体:半加器和全加器。其中全加器通过半加器实现,全加器代码主要描述如何将半加器连线成新电路。个人认为此处用作图会更方便直观,因为vhdl语言实现连线语法比较晦涩;此外,半加器已经可以抽象为一个元器件,作图比较简单。但按照要求还是写了代码。

波形结果:

波形解读:

  • input_a 和 input_b 表示当前位输入,carry_in 表示进位输入,carry_out 表示进位输出,sum_out 表示当前位输出。

实验四:3线-8线译码器

实验代码:

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
library ieee;
use ieee.std_logic_1164.all;

entity decoder_38 is
port(A:in std_logic_vector(2 downto 0);
G1,G2A,G2B:in std_logic;
Y:out std_logic_vector(7 downto 0));
end decoder_38;

architecture arch of decoder_38 is
signal enable: boolean;
begin

process(G1,G2A,G2B)
begin
if G1 = '1' and G2A = '0' and G2B = '0' then
enable <= true;
else
enable <= false;
end if;
end process;

process(A)
begin
if enable = true then
case A is
when "000" => Y <= "11111110";
when "001" => Y <= "11111101";
when "010" => Y <= "11111011";
when "011" => Y <= "11110111";
when "100" => Y <= "11101111";
when "101" => Y <= "11011111";
when "110" => Y <= "10111111";
when "111" => Y <= "01111111";
end case;
else
Y <= "11111111";
end if;
end process;

end arch;

代码释义:

  • 这段代码实现的是一个3-8译码器。其中,输入端口A是一个3位二进制码,G1、G2A和G2B是3个控制信号,Y是8位输出信号。
  • 在这段代码中,首先通过一个process语句判断是否需要启用译码器。如果G1为1且G2A和G2B均为0,则启用译码器。否则,不启用译码器。
  • 接着,通过另一个process语句对输入信号进行译码。如果启用了译码器,则根据输入信号的不同取值,将输出信号Y赋值为相应的8位二进制码。如果没有启用译码器,则将输出信号Y赋值为全1的8位二进制码。

波形结果:

波形解读:

  • 在使能端运行工作时,即G1为1且G2A和G2B均为0时,A输入为随机三位二进制数,Y对应位置输出为0,其余输出为1。
  • 在使能端不满足G1为1且G2A和G2B均为0时,Y输出均为1。

实验五:表决器

实验代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
library ieee;
use ieee.std_logic_1164.all;

entity voter_4 is
port(A :in std_logic_vector(3 downto 0);
Y :out std_logic);
end voter_4;

architecture arch of voter_4 is
begin

process(A)
begin
if A = "1111" or A = "1110" or A = "1101" or A = "1011" or A = "0111" then
Y <= '1';
else
Y <= '0';
end if;
end process;

end arch;

代码释义:

  • 这段代码实现的是一个4选1投票器。其中,输入端口A是一个4位二进制码,Y是1位输出信号。
  • 在这段代码中,通过一个process语句对输入信号进行判断。如果输入信号的值为”1111”、“1110”、“1101”、”1011”或”0111”中的任意一种,则将输出信号Y赋值为1。否则,将输出信号Y赋值为0。

波形结果:

波形解读:

  • 输入信号的值为”1111”、“1110”、“1101”、”1011”或”0111”中的任意一种时,输出信号Y为1。否则,输出信号Y为0。