VHDL中数据类型转换与移位(STD_LOGIC_ARITH与NUMERIC_STD)

本文介绍了VHDL编程中常用的库文件,包括IEEE标准库的使用方法,对比了std_logic_arith、std_logic_unsigned等库的功能,并重点推荐了NUMERIC_STD库的优势。此外,还详细解释了signed、unsigned及std_logic_vector的区别。

1. VHDL目前常用库文件

目前写VHDL程序时,大部分人已经熟悉的库调用如下所示:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all; --或者 use ieee.std_logic_signed.all;

这几个库文件的源码可以在IEEE库文件链接中查看,首先阐述一下这些文件的内容和主要作用:
- std_logic_1164 : 声明了std_Ulogic类型及其决断子类型std_logic,也声明了这种类型构成的数组std_logic_vector,还有这些类型的逻辑运算符函数。如果你需要使用std_logic类型,并只做逻辑类运算的话。就只需要声明 LIBRARY IEEE和 USE std_logic_1164.ALL就可以了。
- std_logic_arith : 声明了signed和unsigned两种数据类型。这两种数据类型与std_logic_vector很相似,在后面详细解释。该库函数只对 integer、signed、unsigned以及std_ulogic的算术运算(包括类型转换)做了定义!
注意:该库函数无法对STD_LOGIC_VECTOR做任何运算
- std_logic_unsigned/std_logic_signed : 这两个库文件是对std_logic_arith 的延伸,适用与对STD_LOGIC_VECTOR进行运算,std_logic_unsigned将会把STD_LOGIC_VECTOR转换成无符号数进行运算;而std_logic_signed 将把STD_LOGIC_VECTOR转换成有符号数进行运算。

2. signed、unsigned以及std_logic_vector之间的区别

在讲述NUMERIC_STD之前先来阐述几点小问题。首先就是signed与unsigned这两种数据类型。他们的定义为:

type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;
type SIGNED is array (NATURAL range <>) of STD_LOGIC;

与std_logic_vector的定义完全相同。所不同的是表示的意义不同。举例来说:

“1001”的含义对这三者而言是不同的:
*std_logic_vector : 简单的四个二进制位;
*unsigned : 代表数字9;
*signed : 代表数字 -7(补码表示的);

一定要重视signed与unsigned这两种类型。

3. NUMERIC_STD

终于来到了故事的主人公: NUMERIC_STD。使用NUMERIC_STD可以完全替代std_logic_arith、std_logic_unsigned、std_logic_signed这三个库文件!
- 首先,NUMERIC_STD这个库文件才是血统最正的IEEE库文件!!上述的其他三个其实都是Synopsis 这个公司的,但是由于这个公司抢先了一步,所以占据了大量的用户资源。
- std_logic_arith、std_logic_unsigned、std_logic_signed的问题在于当在同一文件中同时使用signed和unsigned时,会出现函数重载的冲突,导致错误。
- 其次,NUMERIC_STD是完全基于signed和unsigned所写的算术重载函数和数据类型转换函数。不管是INTEGER还是STD_LOGIC_VECTOR要进行算术运算,都必须转换为signed和unsigned两种数据类型。
数据类型转换函数
数据类型转换总表
下面举个例子来说明NUMERIC_STD库的使用。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity decode is 
port
(
  DIN : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
  EN : IN STD_LOGIC;
  DOUT : OUT STD_LOGIC_VECTOR(63 DOWNTO 0)
);
end decoder;
architecture behave of decoder is 
begin
DOUT <= std_logic_vector(to_unsigned(0,64));
if EN='1' then
DOUT(to_integer(unsigned(DIN))) <= '1';
end if;
end process;
end behave;

4. shift_left() and shift_right()

虽然有srl, sll, sra, sla这几个移位操作符,但是这几个操作符已经被 shift_left() and shift_right()这两个函数所取代,原因移位操作运算符的发展历史

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;               -- Needed for shifts
entity example_shift is
end example_shift;
architecture behave of example_shift is
  signal r_Shift1     : std_logic_vector(3 downto 0) := "1000";
  signal r_Unsigned_L : unsigned(3 downto 0)         := "0000";
  signal r_Unsigned_R : unsigned(3 downto 0)         := "0000";
  signal r_Signed_L   : signed(3 downto 0)           := "0000";
  signal r_Signed_R   : signed(3 downto 0)           := "0000";  
begin
  process is
  begin
    -- Left Shift
    r_Unsigned_L <= shift_left(unsigned(r_Shift1), 1);
    r_Signed_L   <= shift_left(signed(r_Shift1), 1);
    -- Right Shift
    r_Unsigned_R <= shift_right(unsigned(r_Shift1), 2);
    r_Signed_R   <= shift_right(signed(r_Shift1), 2); 
    wait for 100 ns;
  end process;
end architecture behave;

shift_left() and shift_right()具体用法在此不赘述。

5. 总结

我个人觉得,虽然NUMERIC_STD有时候操作有点繁琐,但是更加规矩,并且可以有效避免一些错误,所以我觉得今后应该首选使用该库文件。

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; entity crc_cal_16 is port( rst_n : in std_logic; clk : in std_logic; crc_en : in std_logic; crc_int : in std_logic; sc_data : in std_logic_vector(7 downto 0); sc_crc : in std_logic_vector(15 downto 0); sc_crc_calc_times : in std_logic_vector(7 downto 0); crc_invalid_16 : out std_logic; crc_err_counter_16 : out std_logic_vector(31 downto 0) ); end crc_cal_16; architecture Behavioral of crc_cal_16 is signal crc_temp_16 : std_logic_vector(15 downto 0):=(others => '0'); signal crc_state_16 : integer range 0 to 6:= 0; signal crc_0_16 : std_logic_vector(15 downto 0):=(others => '0'); signal crc_1_16 : std_logic_vector(15 downto 0):=(others => '0'); signal crc_2_16 : std_logic_vector(15 downto 0):=(others => '0'); signal cal_byte_count_16 : integer range 0 to 8:= 0; signal crc_locked_16_temp : std_logic_vector(15 downto 0):=(others => '0'); signal crc_locked_16 : std_logic:='0'; signal crc_locked_16_last : std_logic:='0'; signal crc_en_last : std_logic:='0'; signal crc_data_16 : std_logic_vector(15 downto 0):=(others => '0'); signal crc_err_counter_16_temp : std_logic_vector(31 downto 0):=(others => '0'); signal sc_data_t : std_logic_vector(7 downto 0):=(others => '0'); signal loop_cnt : integer range 0 to 15:= 0; begin crc_err_counter_16 <= crc_err_counter_16_temp; sc_data_t <= sc_data(0) & sc_data(1) & sc_data(2) & sc_data(3) & sc_data(4) & sc_data(5) & sc_data(6) & sc_data(7); signals_pipeline: process(clk) begin if clk'event and clk = '1' then crc_locked_16_last <= crc_locked_16; crc_en_last <= crc_en; end if; end process signals_pipeline; crc_locked_16_gen: process(rst_n,clk) begin if rst_n = '0' then crc_locked_16_temp <= (others => '0'); elsif clk'event and clk = '1' then if crc_locked_16 = '1' then crc_locked_16_temp <= crc_temp_16; else crc_locked_16_temp <= crc_locked_16_temp; end if; end if; end process crc_locked_16_gen; crc_invalid_16_gen: process(rst_n,clk) begin if rst_n = '0' then crc_invalid_16 <= '0'; crc_err_counter_16_temp <= (others => '0'); elsif clk'event and clk = '1' then if crc_en = '0' and crc_en_last = '1' then if crc_locked_16_temp /= sc_crc then crc_err_counter_16_temp <= crc_err_counter_16_temp + 1; crc_invalid_16 <= '1'; else crc_invalid_16 <= '0'; end if; end if; end if; end process crc_invalid_16_gen; crc_16_process: process(rst_n,clk) begin if rst_n = '0' then crc_temp_16 <= (others => '0'); crc_state_16 <= 0; crc_0_16 <= (others => '0'); crc_1_16 <= (others => '0'); crc_2_16 <= (others => '0'); crc_locked_16 <= '0'; cal_byte_count_16 <= 0; elsif clk'event and clk = '1' then case crc_state_16 is when 0 => crc_temp_16 <= (others => '0'); crc_0_16 <= (others => '0'); crc_1_16 <= (others => '0'); crc_2_16 <= (others => '0'); crc_locked_16 <= '0'; cal_byte_count_16 <= 0; crc_state_16 <= 1; when 1 => if CRC_en = '1' and CRC_en_last = '0' then crc_state_16 <= 2; else crc_state_16 <= 1; end if; when 2 => if crc_int = '1' then crc_0_16(7 downto 0) <= crc_temp_16(7 downto 0) xor sc_data_t; crc_state_16 <= 3; else crc_state_16 <= 2; end if; when 3 => crc_1_16 <= crc_temp_16(15 downto 8) & crc_0_16(7 downto 0); crc_state_16 <= 4; when 4 => if crc_1_16(loop_cnt) = '1' then crc_temp_16 <= ('0' & crc_1_16(15 downto 1)) xor x"8408"; else crc_temp_16 <= ('0' & crc_1_16(15 downto 1)); end if; crc_state_16 <= 5; when 5 => if loop_cnt >= 7 then loop_cnt <= 0; crc_state_16 <= 6; else loop_cnt <= loop_cnt + 1; crc_1_16 <= crc_temp_16; crc_state_16 <= 4; end if; when 6 => crc_state_16 <= 6; when others => crc_state_16 <= 0; end case; end if; end process crc_16_process; end Behavioral;
最新发布
09-06
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; ENTITY counter_80 IS PORT( clk: in STD_LOGIC; -- 2.048MHz 时钟 en : in STD_LOGIC; -- 使能 co : out STD_LOGIC; -- 进位 data:OUT STD_LOGIC_VECTOR(6 DOWNTO 0):="0000000"; --1位数码管显示 led_pattern :out STD_LOGIC_VECTOR(7 downto 0):="00000000" --数码管位选 ); END counter_80; ARCHITECTURE behavior OF counter_80 IS signal clk_show: STD_LOGIC; signal z_reg : STD_LOGIC_VECTOR(7 downto 0) ; --二进制计数值 signal bcd : STD_LOGIC_VECTOR(11 downto 0):="000000000000"; --bcd计数值 signal q : STD_LOGIC_VECTOR(3 downto 0) ; --数码管显示二进制 begin counter_80_smg_inst : entity work.counter_80_smg Port map ( trig => clk, en => en, num => z_reg, co => co ); -- --每次当新的一位输入前, 都需要对表示 百位/十位/个位 的连续4bit数据判断大小. 大于4, 则进行加3移位处理. -- binary_to_bcd_inst: entity work.binary_to_bcd -- Port map ( -- bin => z_reg , -- bai => bcd(11 downto 8), -- one => bcd(3 downto 0), -- ten => bcd(7 downto 4) -- ); clock_divider_inst:entity work.clock_divider Port map( clk => clk, clk_1khz => clk_show ); -- --数码管扫描显示 -- led_chaser_inst:entity work.led_chaser -- Port map( -- clk => clk_show, -- AA=>"0000", -- BB=>"0000", -- CC=>"0000", -- DD=>"0000", -- EE=>"0000", -- FF=>"0000", -- GG=> bcd(7 downto 4), -- HH=> bcd(3 downto 0), -- show_num => q, -- smg_sel => led_pattern -- ); -- z_reg<="00011010"; led_chaser_inst:entity work.led_chaser Port map( clk => clk_show, AA=>"000"&z_reg(7), BB=>"000"&z_reg(6), CC=>"000"&z_reg(5), DD=>"000"&z_reg(4), EE=>"000"&z_reg(3), FF=>"000"&z_reg(2), GG=>"000"&z_reg(1), HH=>"000"&z_reg(0), show_num => q, smg_sel => led_pattern ); -- led_chaser_inst:entity work.led_chaser -- Port map( -- clk => clk_show, -- AA=>"0000", -- BB=>"0001", -- CC=>"0010", -- DD=>"0011", -- EE=>"0100", -- FF=>"0101", -- GG=>"0110", -- HH=>"0111", -- show_num => q, -- smg_sel => led_pattern -- ); -- smg7_inst:entity work.smg7 Port map( q=>q, data=>data ); end behavior; --模为80计数器模块 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY counter_80_smg IS PORT( trig: IN STD_LOGIC; en : IN STD_LOGIC; --使能 num : out STD_LOGIC_VECTOR(7 DOWNTO 0); --二进制计数值 co : out STD_LOGIC ); END counter_80_smg; ARCHITECTURE behavior OF counter_80_smg IS SIGNAL q: STD_LOGIC_VECTOR(7 downto 0):="00000000"; BEGIN PROCESS(trig) BEGIN if rising_edge(trig) then if(en='1') then IF(q ="01001111") THEN q <= "00000000"; ELSE q <= q + 1; END IF; END IF; END IF; END PROCESS; num <= q; co <= '1' when q ="01001111" else '0'; END behavior;为什么无法实现从0开始计数,进位也一直显示1
07-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值