📄 altera_vhdl_support.vhd
字号:
result(i) := arg_copy(i);
end LOOP;
RETURN(result);
END;
-------------------------------------------------------
-- Conversions for Verilog $display/$write emulation --
-------------------------------------------------------
subtype slv4 is std_logic_vector(1 to 4);
subtype slv3 is std_logic_vector(1 to 3);
-- Remove leading zeros. Also changes strings of all 'x' or 'z' to one char.
-- This handles the %0<radix> kind of Verilog syntax in the format string.
-- Examples:
-- input output
-- ----- -----------
-- 001f 1f
-- 0000 0
-- xxxx x
-- zzzz z
-- xxzz xxzz
function do_pad_none(
str_in : string) return string is
variable start : integer;
variable all_x : boolean := true;
variable all_z : boolean := true;
begin
-- Nothing to remove if string isn't at least two characters long.
if (str_in'length < 2) then
return str_in;
end if;
for i in str_in'range loop
case str_in(i) is
when 'X' | 'x' => all_z := false;
when 'Z' | 'z' => all_x := false;
when others => all_x := false; all_z := false;
end case;
end loop;
if (all_x or all_z) then
return str_in(str_in'left to str_in'left);
end if;
-- Find index of first non-zero character.
for i in str_in'range loop
start := i;
exit when (str_in(i) /= '0');
end loop;
return str_in(start to str_in'right);
end do_pad_none;
-- Replace leading zeros with spaces.
-- This handles the %d kind of Verilog syntax in the format string.
function replace_leading_zeros(
str_in : string;
c : character) return string is
variable str_out : string(str_in'range) := str_in;
begin
-- Nothing to replace if string isn't at least two characters long.
if (str_in'length < 2) then
return str_in;
end if;
for i in str_in'range loop
if (str_in(i) = '0') then
str_out(i) := c;
else
exit;
end if;
end loop;
return str_out;
end replace_leading_zeros;
function do_pad(
str : string;
pad : pad_type) return string is
begin
case pad is
when pad_none => return do_pad_none(str);
when pad_spaces => return replace_leading_zeros(str, ' ');
when pad_zeros => return str;
end case;
end do_pad;
function round_up_to_multiple(
val : integer;
size : integer) return integer is
begin
return ((val + size - 1) / size) * size;
end round_up_to_multiple;
function to_hex_string(
val : std_logic_vector;
pad : pad_type := pad_zeros) return string is
variable ext_len : integer := round_up_to_multiple(val'length,4);
variable val_ext : std_logic_vector(1 to ext_len) := (others => '0');
variable ptr : integer range 1 to (ext_len/4)+1 := 1;
variable str : string(1 to ext_len/4) := (others=>'0');
variable found_x : boolean := false;
variable found_z : boolean := false;
begin
val_ext(ext_len-val'length+1 to ext_len) := val;
-- Extend MSB to extended sulv unless it starts with one (unsigned).
-- Done to extend 'x' and 'z'.
if ext_len-val'length > 0 and val(val'left) /= '1' then
val_ext(1 to ext_len-val'length) := (others => val(val'left));
end if;
for i in val_ext'range loop
next when i rem 4 /= 1;
case slv4'(to_x01z(val_ext(i to i+3))) is
when "0000" => str(ptr) := '0';
when "0001" => str(ptr) := '1';
when "0010" => str(ptr) := '2';
when "0011" => str(ptr) := '3';
when "0100" => str(ptr) := '4';
when "0101" => str(ptr) := '5';
when "0110" => str(ptr) := '6';
when "0111" => str(ptr) := '7';
when "1000" => str(ptr) := '8';
when "1001" => str(ptr) := '9';
when "1010" => str(ptr) := 'a';
when "1011" => str(ptr) := 'b';
when "1100" => str(ptr) := 'c';
when "1101" => str(ptr) := 'd';
when "1110" => str(ptr) := 'e';
when "1111" => str(ptr) := 'f';
when "XXXX" => str(ptr) := 'x';
when "ZZZZ" => str(ptr) := 'z';
when others =>
for j in 0 to 3 loop
case val_ext(i + j) is
when 'X' => found_x := true;
when 'Z' => found_z := true;
when others => null;
end case;
end loop;
if found_x then
str(ptr) := 'X';
elsif found_z then
str(ptr) := 'Z';
else
str(ptr) := 'X';
end if;
end case;
ptr := ptr + 1;
end loop;
return do_pad(str, pad);
end to_hex_string;
function to_decimal_string(
val : integer;
pad : pad_type := pad_spaces) return string is
variable tmp : integer := val;
variable ptr : integer range 1 to 32 := 32;
variable str : string(1 to 32) := (others=>'0');
begin
if val=0 then
return do_pad("0", pad);
else
while tmp > 0 loop
case tmp rem 10 is
when 0 => str(ptr) := '0';
when 1 => str(ptr) := '1';
when 2 => str(ptr) := '2';
when 3 => str(ptr) := '3';
when 4 => str(ptr) := '4';
when 5 => str(ptr) := '5';
when 6 => str(ptr) := '6';
when 7 => str(ptr) := '7';
when 8 => str(ptr) := '8';
when 9 => str(ptr) := '9';
when others => null;
end case;
tmp := tmp / 10;
ptr := ptr - 1;
end loop;
return do_pad(str(ptr+1 to 32), pad);
end if;
end to_decimal_string;
function to_decimal_string(
val : std_logic_vector;
pad : pad_type := pad_spaces) return string is
variable all_x : boolean := true;
variable all_z : boolean := true;
variable some_x : boolean := false;
variable some_z : boolean := false;
variable fixed_str : string(1 to 1);
begin
for i in val'range loop
case to_x01z(val(i)) is
when 'X' => some_x := true; all_z := false;
when 'Z' => some_z := true; all_x := false;
when others => all_x := false; all_z := false;
end case;
end loop;
if (all_x) then
fixed_str(1) := 'x';
return fixed_str;
elsif (all_z) then
fixed_str(1) := 'z';
return fixed_str;
elsif (some_x) then
fixed_str(1) := 'X';
return fixed_str;
elsif (some_z) then
fixed_str(1) := 'Z';
return fixed_str;
else
return to_decimal_string(conv_integer(val), pad);
end if;
end to_decimal_string;
function to_octal_string(
val : std_logic_vector;
pad : pad_type := pad_zeros) return string is
variable ext_len : integer := round_up_to_multiple(val'length,3);
variable val_ext : std_logic_vector(1 to ext_len) := (others => '0');
variable ptr : integer range 1 to (ext_len/3)+1 := 1;
variable str : string(1 to ext_len/3) := (others=>'0');
variable found_x : boolean := false;
variable found_z : boolean := false;
begin
val_ext(ext_len-val'length+1 to ext_len) := val;
-- Extend MSB to extended sulv unless it starts with one (unsigned).
-- Done to extend 'x' and 'z'.
if ext_len-val'length > 0 and val(val'left) /= '1' then
val_ext(1 to ext_len-val'length) := (others => val(val'left));
end if;
for i in val_ext'range loop
next when i rem 3 /= 1;
case slv3'(to_x01z(val_ext(i to i+2))) is
when "000" => str(ptr) := '0';
when "001" => str(ptr) := '1';
when "010" => str(ptr) := '2';
when "011" => str(ptr) := '3';
when "100" => str(ptr) := '4';
when "101" => str(ptr) := '5';
when "110" => str(ptr) := '6';
when "111" => str(ptr) := '7';
when "XXX" => str(ptr) := 'x';
when "ZZZ" => str(ptr) := 'z';
when others =>
for j in 0 to 2 loop
case val_ext(i + j) is
when 'X' => found_x := true;
when 'Z' => found_z := true;
when others => null;
end case;
end loop;
if found_x then
str(ptr) := 'X';
elsif found_z then
str(ptr) := 'Z';
else
str(ptr) := 'X';
end if;
end case;
ptr := ptr + 1;
end loop;
return do_pad(str, pad);
end to_octal_string;
function to_hex_string(
val : std_logic;
pad : pad_type := pad_zeros) return string is
begin
return to_binary_string(val, pad);
end to_hex_string;
function to_decimal_string(
val : std_logic;
pad : pad_type := pad_spaces) return string is
begin
return to_binary_string(val, pad);
end to_decimal_string;
function to_octal_string(
val : std_logic;
pad : pad_type := pad_zeros) return string is
begin
return to_binary_string(val, pad);
end to_octal_string;
function to_binary_string(
val : std_logic;
pad : pad_type := pad_zeros) return string is
variable str : string(1 to 1);
begin
case to_x01z(val) is
when '0' => str(1) := '0';
when '1' => str(1) := '1';
when 'X' => str(1) := 'x';
when 'Z' => str(1) := 'z';
when others => str(1) := 'x';
end case;
return do_pad(str, pad);
end to_binary_string;
function to_binary_string(
val : std_logic_vector;
pad : pad_type := pad_zeros) return string is
variable str : string(1 to val'length) := (others=>'0');
variable ptr : integer := str'left;
begin
for i in val'range loop
str(ptr to ptr) := to_binary_string(val(i));
ptr := ptr + 1;
end loop;
return do_pad(str, pad);
end to_binary_string;
end altera_vhdl_support_lib;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -