lec3 VHDL第三次作业

chapter 10

10.16. 二进制加法。实现两个十六进制数相加 2A + 3C

2A + 3C == 66Hex = 102Dec

10.18. 位计数电路。用全加器设计一个电路,接受一个7位输入,输出一个表示输入中1的个数的3位二进制数。

设计思路:从输入的低位开始扫描序列,设计的全加器为3位,将输入的每一位的高2位补0,并与上一次输入的结果一同输入到一个新的全加器中,若该位为1则结果加1,若该位为0则结果不变,这样最终累加的结果将保存再ypp(6)中,ypp是一个二维数组。

仿真结果图所示,当输入为9时,即 0001001,其中1的个数为2,输出结果y也为2,符合设计要求,其他的输入也同样符合要求,可知设计正确。

10-18-465464658

代码如下所示。其中FA是加法器,count1是技术电路,count_test是计数电路。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity FA is
    generic(n: integer := 8);
    port (
        a,b: in std_logic_vector(n-1 downto 0);
        cin: in std_logic;
        cout: out std_logic;
        s:out std_logic_vector(n -1 downto 0)

    ) ;
end FA;

architecture impl of FA is

    signal sum: std_logic_vector(n downto 0);

begin
    sum <= ('0' & a) + ('0' & b) + cin;
    cout <= sum(n);
    s <= sum(n-1 downto 0);
end impl ; -- impl


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity count1 is
  port (
    a: in std_logic_vector(6 downto 0);
    y: out std_logic_vector(2 downto 0)
  ) ;
end count1;

architecture impl of count1 is
    type PartialP is array(6 downto 0) of std_logic_vector ( 2 downto 0);
    signal ypp : PartialP;
    signal cout: std_logic;
    signal xin: PartialP;

begin
    xin(0) <= "00" & a(0);
    d0: entity work.FA generic map(3) port map(xin(0), "000", '0',cout, ypp(0));
    xin(1) <= "00" & a(1);
    d1: entity work.FA generic map(3) port map(xin(1), ypp(0), '0',cout, ypp(1));
    xin(2) <= "00" & a(2);
    d2: entity work.FA generic map(3) port map(xin(2), ypp(1), '0',cout, ypp(2));
    xin(3) <= "00" & a(3);
    d3: entity work.FA generic map(3) port map(xin(3), ypp(2), '0',cout, ypp(3));
    xin(4) <= "00" & a(4);
    d4: entity work.FA generic map(3) port map(xin(4), ypp(3), '0',cout, ypp(4));
    xin(5) <= "00" & a(5);
    d5: entity work.FA generic map(3) port map(xin(5), ypp(4), '0',cout, ypp(5));
    xin(6) <= "00" & a(6);
    d6: entity work.FA generic map(3) port map(xin(6), ypp(5), '0',cout, ypp(6));
    y <= ypp(6);
end impl ; -- impl


--pragma translate_off

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;


entity count_test is
end count_test;

architecture impl of count_test is
    signal a: std_logic_vector(6 downto 0);
    signal y: std_logic_vector(2 downto 0);
    
    begin

        p1: entity work.count1 port map(a, y);
        process begin
          for i in 0 to 2**7 - 1 loop
              a <= std_logic_vector(to_unsigned(i, 7));
              wait for 10 ns;
          end loop;
        end process;

end impl ; -- test
--pragma translate_on

10.20. 饱和加法器设计。在一些应用中,特别是信号处理中,希望加法器饱和,再溢出状态下产生2n-1 的结果,而不是模运算后的结果。设计一个饱和加法器,可以使用n位加法器和n位多路复用器作为基本器件

饱和加法器,当正向溢出的时候输出输出最大正数,当负向溢出的时候输出最小负数。分析可知,当符号位进位为’1‘,数据最高位进位为‘0‘时发生负向溢出,即两个负数相加超出最小负数表示范围,当符号进位为’0‘且数据最高位进位为’1‘时,发生正向溢出,即两个正数相加超过最大正数表示范围。

因此可以改造全加器,当发生正向溢出时符号位设置为’0‘,数据位全设置为‘1’,表示最大正数;当发生负向溢出时,符号位设置为‘1’,数据位全设置为‘0’表示最小负数

仿真结果如下所示,设计的前20ns位两组特殊的数据,前10ns为 1000 + 1010 发生负向溢出,应该输出1000,仿真结果符合预期,10-20ns输入为0111+ 0010,为正向溢出,输出结果为0111,符合预期,之后输入a从0010开始每隔40ns加1,输入b从0001开始每隔10ns加1,通过观察发现,输出的结果也是符合预期,说明设计正确。

10-20

代码如下所示

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity fulladd is
    generic(N: integer := 8);
    port (
        a,b: in std_logic_vector(n-1 downto 0);
        sub: in std_logic;
        s: out std_logic_vector(n-1 downto 0);
        ovf: out std_logic
    ) ;
end fulladd;

architecture impl of fulladd is

    signal c1, c2: std_logic;
    signal c1n: std_logic_vector(n-1 downto 0);
    signal c2s: std_logic_vector(1 downto 0);

begin
    ovf <= c1 xor c2;
    c1n <= ('0' & a(n-2 downto 0)) + ('0' & (b(n -2 downto 0) xor (n-2 downto 0 => sub))) + sub;
    -- s(n-2 downto 0) <= c1n(n-2 downto 0);
    c1 <= c1n(n - 1);
    c2s <= ('0' & a(n-1)) + ('0' & (b(n - 1) xor sub)) + c1;
    -- s(n - 1) <= c2s(0);
    c2 <= c2s(1);
    s(n - 2 downto 0) <= (n-2 downto 0 => '1') when c1 = '1' and c2 = '0'  
    else (n-2 downto 0 => '0') when c2 = '1' and c1 = '0'
    else c1n(n -2 downto 0);

    s(n - 1) <= '0' when c1 = '1' and c2 = '0' 
    else '1' when c2 = '1' and c1 = '0'
    else c2s(0);
end impl ; -- impl


--pragma translate_off

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;


entity fulladd_test is
end fulladd_test;

architecture impl of fulladd_test is
    signal a: std_logic_vector(3 downto 0);
    signal b: std_logic_vector(3 downto 0);
    signal y: std_logic_vector(3 downto 0);
    signal ovf: std_logic;
    
    begin

        p1: entity work.fulladd generic map(4) port map(a, b, '0', y, ovf);
        process begin
            a <= "1000";
            b <= "1010";
            wait for 10 ns;
            a <= "0111";
            b <= "0010";
            wait for 10 ns;
            for i in 2 to 2**4 -1 loop
                a <= std_logic_vector(to_unsigned(i, 4));
                for j in 1 to 2**4 -1 loop
                    b <= std_logic_vector(to_unsigned(j, 4));
                    wait for 10 ns;
                end loop;
            end loop;
        end process;

end impl ; -- test
--pragma translate_on

10.44. 倍5电路。使用加法器,组合构建块和门,设计一个接收4位基2补码二进制输入a(3 downto 0)的电路,并输入一个7位基2补码输出b(6 downto 0),输出是输入的5倍。不能使用乘法器,使用尽可能少的加法器。

设计思路:将输入左移两位,得到原输入的四倍,在使用一个加法器加上原来输入元素,得到原输入的五倍,需要注意的是,输入的是基2的补码,最高位表示符号位,在左移两位后需要对原数据进行符号扩展。

如下所示,当输入由0000-0111时,输入为正数,输出直接扩大五倍,当输入为1000时,表示的时-8,输出为58Hex 转换为十进制的数为-40,符合题意,同理验证其他复数也符合5倍的要求,可知电路设计正确。

10-44

设计代码如下所示

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity addsub is
    generic(N: integer := 8);
    port (
        a,b: in std_logic_vector(n-1 downto 0);
        sub: in std_logic;
        s: out std_logic_vector(n-1 downto 0);
        ovf: out std_logic
    ) ;
end addsub;

architecture impl of addsub is

    signal c1, c2: std_logic;
    signal c1n: std_logic_vector(n-1 downto 0);
    signal c2s: std_logic_vector(1 downto 0);

begin
    ovf <= c1 xor c2;
    c1n <= ('0' & a(n-2 downto 0)) + ('0' & (b(n -2 downto 0) xor (n-2 downto 0 => sub))) + sub;
    s(n-2 downto 0) <= c1n(n-2 downto 0);
    c1 <= c1n(n - 1);
    c2s <= ('0' & a(n-1)) + ('0' & (b(n - 1) xor sub)) + c1;
    s(n - 1) <= c2s(0);
    c2 <= c2s(1);
end impl ; -- impl


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity fives is
  port (
    num: in std_logic_vector(3 downto 0);
    y: out std_logic_vector(6 downto 0)
  ) ;
end fives;

architecture impl of fives is

    signal num_sll_2, num_temp: std_logic_vector(6 downto 0) := "0000000";
    signal ovf: std_logic;

begin
num_temp <= "111" & num when num(3) = '1' else "000" & num ;
num_sll_2(5 downto 0) <= num & "00";
num_sll_2(6) <= '1' when num(3) = '1' else '0';

e0: entity work.addsub generic map(7) port map(num_temp, num_sll_2, '0', y, ovf);
end impl ; -- impl


--pragma translate_off

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;


entity fives_test is
end fives_test;

architecture impl of fives_test is
    signal a: std_logic_vector(3 downto 0);
    signal y: std_logic_vector(6 downto 0);
    
    begin

        p1: entity work.fives  port map(a, y);
        process begin
          for i in 0 to 2**4 - 1 loop
              a <= std_logic_vector(to_unsigned(i, 4));
              wait for 10 ns;
          end loop;
        end process;

end impl ; -- test
--pragma translate_on

chapter 11

11.6. 定点数表示。将0.3775转化到最近的s1.5格式定点数表示,给出绝对跟相对误差

0.3775 * 25 = 12.08 ≈ 12 = 01100

转为s1.5的形式为0.01100 = 0.375

绝对误差 = | 0.375 - 0.3775 | = 0.0025

相对误差为(0.3775 - 0.375) / 0.3775 = 0.0066

11.11. 选择定点表示方案。以0.1PSI的精度表示一个范围从-10PSI到10PSI的相对压力信号。选择一个指定精度的并且以最少位数覆盖此范围的定点表示方法

由于2-4 < 0.1 所以小数部分可以用四位二进制表示,由于要表示正负数,需要一位符号位,整数位可以用4位二进制数表示,因此最终表示格式位9位:s4.4

11.18. 浮点表示。将100 000转化成偏移量为8,格式为s3E5的浮点数,并给出相对误差跟绝对误差

s3E5从左到右为1位符号,5位指数,3位小数,将(100,000)10 转化为2进制数位 1 1000 0110 1010 0000 = 1.1000011010100000 * 21 0000

由于偏移量为8,指数部分需要加上1000,最终得到指数位1 1000

要求保留三位小数,可得小数部分为100

最终得到的s3E5浮点数为 0 11000 100,表示为十进制数为98,304

绝对误差 = 100,000 - 98,304 = 1,696

相对误差为(100,000 - 98,000) / 100,000 = 0.01696

复习题

1. 噪声容限,VOL = 0.1V, VOH = 0.9V, VIL = 0.5V, VIH = 0.7V

  • 噪声容限的最大值和最小值是多少?

    VNMH = VOH - VIH = 0.2V

    VNML = VIL - VOL = 0.4V

  • 电源电压(相对于GND)的允许容限如何估算?

    电源电压的最小值不能小于器件允许的最小值,不能超过器件允许的最大值,同时避免在(VIL, VIH)之间

  • 假定 VIH-VIL >= 0.2V,如何调整这些?

    增大VIH 减小VIL ,但若需要保证传输曲线增益不变根据VOH - VIL也需要相应的增大

2. 为了用数字技术处理信号,信号怎么表示

  • 单一信号可以如何表示?举例说明

    单一信号可以用1bit表示,如白天跟晚上,0便是白天,1表示晚上

  • 集合信号可以如何表示?举例说明

    集合信号可以用01集合进行编码,如红绿蓝紫,可以用2bit表示,00表示红,01表示绿,10表示蓝,11表示紫色。

  • 讨论如何表示棋盘

    • 围棋棋盘

      可以使用位图表示,其中每一位包括2bit信息,00表示没有棋子,01表示有白子,10表示有黑子。

    • 中国象棋棋盘

      象棋棋盘同样也可以用位图表示,位图中每一位有8bit数据,8b'0表示一个位子没有数据,若不全为0,最高位1表示红方,0表示蓝方,剩下的7位分别对卒车马象帅等棋子进行编码

3. 化简逻辑函数

  • f = (x & y & z) | (x & y) | (x’ & y & z)

    = (y & z & x ) | (y & z & x') | (x & y)

    = (y & z) & (x | x') | (x & y)

    = (y & z) | (y & x)

    = y & (x | z)

  • f = (x & y & z) | (x & y’) | (x & z’)

    = (x & y & z) | [x & (y & z)']

    = x & [(y & z) | (y & z)']

    = x

4. 对偶与互补

给定一个逻辑函数 f(a,b,c),其互补函数写作f’ = f’(a,b,c),对偶函 数写作fD = f’(a’,b’,c’)

  • 假定 f = AND (与运算), 其互补函数是 _____?对偶函数是_____?

    互补函数是 OR

    对偶函数是 NOR

  • 假定 f = 3-bit 质数函数,f 输入为1,2,3,5,7时输出为1(Ture)

    f函数的真值表如下所示

c\ba 00 01 11 10
0 0 1 1 1
1 0 1 1 0

f = a | ( b & c')

  • 互补函数f’ 在输入为_______时产生输出“1”?

    f’ = a & ( b | c')

    1,3,7

  • 对偶函数fD 在输入围_______时产生输出“1”?

    fD = a‘ & ( b’ | c)

    0,4,6

5. 6. 手工组合逻辑电路设计(感觉第五第六题再说一个东西,没太明白题意)

从设计规范入手,写出卡诺图,找出关键蕴含项( prime implicants ), 选择覆盖逻辑函数的关键蕴含项的最小集

  • 试图设计组合逻辑电路,实现4-bit 输入的Fibonacci 数列判断 (给出设计过程,一种电路图,一种VHDL描述)

    • 不是设计电路产生Fibonacci数列

    • 是类似讲义中质数(素数)的判断

    • 斐波那契数列(Fibonacci ),又称黄金分割数列 “兔子数列”。这个序列的前几项是这样的:0,1,1,2,3,5,8,13,21,34,⋯在数学上,斐波纳契数列以如下被以递归的方法定义:

      • F(0)=0

      • F(1)=1

      • F(n)=F(n−1)+F(n−2) ,(n≥2,n∈N)

        4-输入信号的Fibonacci(斐波那契数列)电路 当输入(dcba)为1,2,3,5,8, 及 13时,输出为True

        1584115827
  • 补充其他方法,至少包含一种VHDL描述

    将每个位1的项或起来直接输出

    7bac1874682a0da3086eb5294d4718f
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity fib_condition is
      port (
        num : in std_logic_vector(3 downto 0);
        is_fib: out std_logic);
    end fib_condition;
    
    architecture fib_condition_impl of fib_condition is
    begin
      process( num )
      begin
        case num is
          when "0000" | "0001" | "0010" | "0011" | "0101" | "1000" | "1101"
           => is_fib <= '1';
          when others => is_fib <= '0';
        end case;
      end process ;
    end fib_condition_impl;
    

7. 写出 该电路行为的一种 VHDL描述

5d8e4ed2974e38bdf10248a3fa89f4a
library ieee;
use ieee.std_logic_1164.all;

entity fib_condition is
  port (
    num : in std_logic_vector(3 downto 0);
    is_fib: out std_logic);
end fib_condition;

architecture fib_condition_impl of fib_condition is
begin
  process( num )
  begin
    case num is
      when "0000" | "0001" | "0010" | "0011" | "0101" | "1000" | "1101"
       => is_fib <= '1';
      when others => is_fib <= '0';
    end case;
  end process ;
end fib_condition_impl;

8. 写出 该电路行为的一种 VHDL描述

1584117550
library ieee;
use ieee.std_logic_1164.all;

entity test is
  port (
    num : in std_logic_vector(3 downto 0);
    is_fib: out std_logic);
end fib_condition;

architecture fib_condition_impl of test is
begin
  process( num )
  begin
    case num is
      when "0111" | "1100" | "1101" | "1111" | "1110" | "1011" => is_fib <= '1';
      when others => is_fib <= '0';
    end case;
  end process ;
end fib_condition_impl;

9. 组合逻辑电路模块(单元)的利用

  • 提高抽象层次,使用组件(组合逻辑单元)而不是直接使用卡诺图设计电路

    • 假定组合逻辑电路来自预定义的电路单元
    • 编码器Encoder – 将one-hot信号转换为2进制
    • 复接器(多路选择器)Multiplexer – 根据One-hot信号选择某个输入信号
    • 仲裁器Arbiter – 选择第一个Ture
    • 比较器Comparators – 相等或者幅度大小
    • 只读存储器ROMs
  • 采用划分的方式由小的电路单元构造大的电路单元

    Decoder, encoder, multiplexer

  • 基于复接器和译码器的逻辑电路(FPGA中查表的基础)

  • 位片(Bit-slice)编码风格

  • 如何得到求三个数的中间数的电路?复习练习09:写出这个电路的VHDL模型。

    1584342453

    vhdl代码如下所示,复用三个比较器,agb代表a大于b,agc代表a大于c,bgc代表b大于c,三者两两之间比较之后,可以得到三者之间得大小关系,若a位mid,则agb xor agc为1,即a只大于两个中的一个;若b为mid,agb xor bgc 为0,也是表示b只大于两个中的一个,同理若c为mid,agc xor bgc 为1,仿真结果如下图所示。result输出中间的数,可知结果正确。

    1584164213

    代码如下所示

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.std_logic_misc.all;
    
    entity magComp is
        generic(k: integer := 8);
        port (
            a,b: in std_logic_vector(k-1 downto 0);
            gt: out std_logic
        ) ;
    end magComp;
    
    architecture impl of magComp is
    
        signal eqi, gti: std_logic_vector(k-1 downto 0);
        signal gta, eqa: std_logic_vector(k downto 0);
    
    
    begin
        eqi <= a xnor b;
        gti <= a and not b;
        gta <= '0' & (gta(k downto 1) or (gti and eqa(k downto 1)));
        eqa <= '1' & (eqa(k downto 1) and eqi);
        gt <= or_reduce(gta);
    end impl ; -- impl
    
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity midle is
        generic(k : integer := 8);
        port (
            a,b,c: in std_logic_vector(k-1 downto 0);
            mid: out std_logic_vector(k-1 downto 0)
        ) ;
    end midle;
    
    architecture impl of midle is
    
        signal agb, agc, bgc: std_logic;
    
    begin
    p1: entity work.magComp generic map(k) port map(a, b, agb);
    p2: entity work.magComp generic map(k) port map(a, c, agc);
    p3: entity work.magComp generic map(k) port map(b, c, bgc);
    
    mid <= a when (agb xor agc) = '1' else
         b when (agb xor bgc)  = '0' else
         c when (agc xor bgc) = '1' else
         (k-1 downto 0 => '-');
    
    end impl ; -- impl
    
    
    --pragma translate_off
    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use ieee.numeric_std.all;
    use std.textio.all;
    use ieee.std_logic_textio.all;
    
    
    entity midletest is
    end midletest;
    
    architecture test of midletest is
        signal a, b, c, result: std_logic_vector(3 downto 0);
        
        begin
            p0: entity work.midle generic map (4) port map(a, b, c, result);
            process is
    
            begin
                for i in 0 to 10 loop
                    a <= std_logic_vector(to_signed(i, 4));
                    b <= std_logic_vector(to_signed(i + 1 , 4));
                    c <= std_logic_vector(to_signed(i + 2 , 4));
    
                    wait for 10 ns;
                end loop;
            end process;
    
    end test ; -- test
    --pragma translate_on
    

组合逻辑电路单元的问题: 复习练习10

  • 设计一个组合逻辑电路,输入为4个4-bit One-hot信号, 输出为4个信号中最高有效位位置为“1”对应的数字

    如下图所示,使用比较器跟多路复用器构造电路,最高有效位为1表示最大的数,将a与b,c与d比较,输出较大的,在比较这两个输出,选出大的一个。

    1584168059
  • 电路的输入是4个4-bit数字(任意设定数据格式),输出是“1的个数最少的那个输入信号”

    如图所示,使用比特加法器,统计输入内有多少个1,在使用与上一题一样的结构,输出四个输入中最小的那个数。

    1584168521

复习练习11

  • 设计一个电路,实现将输入a变换成-2a

    • 方法:左移1位 (2x),诸位求反,再+1

      如图所示的电路,将输入左移两位,得到输入的两倍,在通过与ff异或得到反码,在加一的到其补码电路。

      158416568sad
  • 将10进制浮点数35.6转化为IEEE 754 二进制s8.3格式浮 点数,写出变换步骤

    我理解成指数部分3位小数部分8位的浮点数,没有给偏移量,先将整数部分表示为10 0011,小数部分表示为0.1001 1001,该数可以表示为10 0011.1001 1001,格式化为1.0001 1100 1100 * 25 ,故指数部分为101,s为0,故IEEE754格式可以写成0 101 0001 1100

你可能感兴趣的:(lec3 VHDL第三次作业)