VHDL记录

使用function名称作为“常量”

测试代码如下,function仅有名称,没有输入,在function内部使用全局constant进行参数处理,后续代码中可以直接使用function名称作为常量
在这里插入图片描述

numeric_std包集中使用乘法的注意项

近日看到一个VHDL Coding Style中提示说,使用numeric_std包集时,不要直接将unsigned/signed数据与natural/integer类型的数据相乘。

今天看了一下numeric_std的源码发现,如果直接直接将无符号数/有符号数与整数相乘的话,乘积很有可能会溢出。主要原因是由于,包集在实现整数与符号数相乘的时候,是先将整数转成了无符号数/有符号数,之后再进行的乘法运算,而整数转换后的位宽是与输入的符号数的位宽相一致的,这就可能导致在整数进行类型转换的过程中,出现数据溢出的情况。

这其实算不上bug,因为源码中对此进行了明确说明,主要是在使用的时候需要注意规避这一点,不要让符号数与整数直接相乘,可以手动进行位宽转换后再做运算。相应的源码如下图所示,
在这里插入图片描述

在这里插入图片描述

对于entity设置属性的方法

在这里插入图片描述
类似的,对于verilog的module设置attribute的方法如下,
在这里插入图片描述

在entity声明中嵌入function的定义

在这里插入图片描述

VHDL仿真

有时写vhdl时,使用了record、array等数据类型,此时使用verilog进行仿真时略有不便,用vhdl仿真倒是方便不少。

读写文件

File declaration/File handing

在这里插入图片描述

File reading

在这里插入图片描述

File writing

在这里插入图片描述

小例子

在这里插入图片描述

在这里插入图片描述

使用函数

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

entity test is
end test;

architecture Behavioral of test is

    -- convert a hex string to a std_logic_vector
    function hex_string_to_std_logic_vector(inp: string; width : integer)
        return std_logic_vector is

        constant strlen       : integer := inp'LENGTH;
        variable result       : std_logic_vector(width-1 downto 0);
        variable bitval       : std_logic_vector((strlen*4)-1 downto 0);
        variable posn         : integer;
        variable ch           : character;
        variable vec          : string(1 to strlen);
    begin
        vec := inp;

        -- default value is zero
        result := (others => '0');
        posn := (strlen*4)-1;

        for i in 1 to strlen loop
            ch := vec(i);
            case ch is
                when '0' => bitval(posn downto posn-3) := "0000";
                when '1' => bitval(posn downto posn-3) := "0001";
                when '2' => bitval(posn downto posn-3) := "0010";
                when '3' => bitval(posn downto posn-3) := "0011";
                when '4' => bitval(posn downto posn-3) := "0100";
                when '5' => bitval(posn downto posn-3) := "0101";
                when '6' => bitval(posn downto posn-3) := "0110";
                when '7' => bitval(posn downto posn-3) := "0111";
                when '8' => bitval(posn downto posn-3) := "1000";
                when '9' => bitval(posn downto posn-3) := "1001";
                when 'A' | 'a' => bitval(posn downto posn-3) := "1010";
                when 'B' | 'b' => bitval(posn downto posn-3) := "1011";
                when 'C' | 'c' => bitval(posn downto posn-3) := "1100";
                when 'D' | 'd' => bitval(posn downto posn-3) := "1101";
                when 'E' | 'e' => bitval(posn downto posn-3) := "1110";
                when 'F' | 'f' => bitval(posn downto posn-3) := "1111";
                when others => bitval(posn downto posn-3) := "XXXX";
                               -- synthesis translate_off
                               ASSERT false
                                   REPORT "Invalid hex value" SEVERITY ERROR;
                               -- synthesis translate_on
            end case;
            posn := posn - 4;
        end loop;

        if (width <= strlen*4) then
            -- bitval larger than desired width
            result :=  bitval(width-1 downto 0);
        else
            -- bitval smaller than desired width
            -- MSB is padded with zeros since default value for result is all 0s
            result((strlen*4)-1 downto 0) := bitval;
        end if;
        return result;
    end;
    
    -- convert a binary string into a std_logic_vector (e.g., 0b10.1 = 101)
    function bin_string_to_std_logic_vector (inp : string)
        return std_logic_vector
    is
        variable pos : integer;
        variable vec : string(1 to inp'length);
        variable result : std_logic_vector(inp'length-1 downto 0);
    begin
        vec := inp;
        pos := inp'length-1;
        -- Set default value
        result := (others => '0');

        for i in 1 to vec'length loop
            -- synthesis translate_off
            if (pos < 0) and (vec(i) = '0' or vec(i) = '1' or vec(i) = 'X' or vec(i) = 'U')  then
                assert false
                    report "Input string is larger than output std_logic_vector. Truncating output.";
                return result;
            end if;
            -- synthesis translate_on

            if vec(i) = '0' then
                result(pos) := '0';
                pos := pos - 1;
            end if;
            if vec(i) = '1' then
                result(pos) := '1';
                pos := pos - 1;
            end if;
            -- synthesis translate_off
            if (vec(i) = 'X' or vec(i) = 'U') then
                result(pos) := 'U';
                pos := pos - 1;
            end if;
            -- synthesis translate_on
        end loop;
        return result;
    end;
    
    signal data_1  : std_logic_vector(5  downto 0);
    signal data_2  : std_logic_vector(7  downto 0);
     
begin
    
    data_1 <= bin_string_to_std_logic_vector("101001");
    data_2 <= hex_string_to_std_logic_vector("45",8);

end Behavioral;

模块中打印出调试信息

VHDL的仿真不如verilog方便,因此一般我都是用verilog对整个模块做仿真。但有的时候,想在某个可综合的VHDL模块内部嵌入仿真调试信息,这样在仿真时可以更直观的观测到运行结果。这在verilog中可以直接使用display和monitor函数,在VHDL中则需要借用report函数或者自己编写函数实现。

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
library work;
--    use work.stdio_h.all;

entity counter is
generic(
    SIM_VERBOSE : natural := 1
); 
port ( 
    clk : in  std_logic;
    cnt : out std_logic_vector(15 downto 0)
);
end counter;

architecture Behavioral of counter is
    
    signal cnt_i : unsigned(15 downto 0) := (others=>'0');
    
begin
    
    cnt <= std_logic_vector(cnt_i);
    process(clk)
    begin
        if rising_edge(clk) then
            cnt_i <= cnt_i + 1;
            
--            if(SIM_VERBOSE=1) then
--                if(cnt_i = 20) then
--                    printf("The time is %d ns\n",now);
--                    printf("The cnt_i value is %u\n",std_logic_vector(cnt_i)); 
--                    printf("-------------------------\n");
--                end if;
--            end if;
        end if;
    end process;
    
    -- synthesis translate_off
    gen_sim_info : if SIM_VERBOSE=1 generate
    begin
        process(cnt_i)
            use work.stdio_h.all;
        begin
            if(cnt_i = 20) then
                printf("The time is %d ns\n",now);
                printf("The cnt_i value is %u\n",std_logic_vector(cnt_i)); 
                printf("-------------------------------------------------------\n");
                printf("The cnt_i value is %s,the cnt_i part value is %u \n",std_logic_vector(cnt_i),std_logic_vector(cnt_i(3 downto 0)));
                printf("-------------------------------------------------------\n");
            end if;
        end process;
    end generate;
    -- synthesis translate_on

end Behavioral;

Modelsim运行结果如下所示,
在这里插入图片描述

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

entity example is
    generic(
        SIM_EN : natural := 1
    );
    port ( 
        clk  : in  std_logic;
        dout : out std_logic_vector(7 downto 0)
    );
end example;

architecture Behavioral of example is
    
    procedure writeNowToScreen(text_string : in string) is
        variable L : line;
    begin
        write(L,string'("[ "));
        write(L,now);
        write(L,string'(" ]"));
        write(L,text_string);
        writeline(output, L);
    end writeNowToScreen;
    
    procedure writeInfoToScreen(text_string : in string;data : in integer) is
        variable L : line;
    begin
        write(L,string'("[ "));
        write(L,now);
        write(L,string'(" ]"));
        write(L,text_string);
        write(L,data);
        writeline(output, L);
    end writeInfoToScreen;
        
    signal cnt : unsigned(7 downto 0) := (others=>'0');
    
begin
    
    dout <= std_logic_vector(cnt);
    process(clk)
    begin
        if rising_edge(clk) then
            cnt <= cnt + 1;
            
            if (SIM_EN=1) then
                if (cnt=7) then
                    writeNowToScreen("cnt is 7");
                end if;
                    
                case cnt is
                    when X"10"  => writeInfoToScreen("A   -> ",to_integer(cnt));
                    when X"20"  => writeInfoToScreen("BB  -> ",to_integer(cnt));
                    when X"30"  => writeInfoToScreen("CCC -> ",to_integer(cnt));
                    when others => null;
                end case;
            end if;
        end if;
    end process;
    
end Behavioral;

在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值