diff options
author | Tristan Gingold | 2015-06-03 03:39:39 +0200 |
---|---|---|
committer | Tristan Gingold | 2015-06-03 03:39:39 +0200 |
commit | 9cec02a48c94505246ad829692817035c0b422f7 (patch) | |
tree | 2e66347c0067d915e5fdb5b70565286573dfb438 | |
parent | 2153aea92dfa3f28990f00f85fcff3a552ee21b0 (diff) | |
download | ghdl-9cec02a48c94505246ad829692817035c0b422f7.tar.gz ghdl-9cec02a48c94505246ad829692817035c0b422f7.tar.bz2 ghdl-9cec02a48c94505246ad829692817035c0b422f7.zip |
Reimplementation of std_logic_1164.
-rw-r--r-- | libraries/redist1164/build.py | 361 | ||||
-rw-r--r-- | libraries/redist1164/std_logic_1164-body.proto | 123 | ||||
-rw-r--r-- | libraries/redist1164/std_logic_1164-body.vhdl | 768 | ||||
-rw-r--r-- | libraries/redist1164/std_logic_1164.vhdl | 143 |
4 files changed, 1395 insertions, 0 deletions
diff --git a/libraries/redist1164/build.py b/libraries/redist1164/build.py new file mode 100644 index 0000000..6255938 --- /dev/null +++ b/libraries/redist1164/build.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python +# Generate the body of ieee.std_logic_1164 from a template. +# This file is part of GHDL. +# Copyright (C) 2015 Tristan Gingold +# +# GHDL is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2, or (at your option) any later +# version. +# +# GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +import re +import sys + +binary_funcs = [ "and", "nand", "or", "nor", "xor" ] + +# Python modelisation of std_ulogic type. +std_logic = "UX01ZWLH-" + +# Normalization map. +ux01_map = { 'U': 'U', + 'X': 'X', 'Z': 'X', 'W': 'X', '-': 'X', + '0': '0', 'L': '0', + '1': '1', 'H': '1' } + +def sl_and(a,b): + """and definition""" + na = ux01_map[a] + nb = ux01_map[b] + if na == '0' or nb == '0': + return '0' + if na == 'U' or nb == 'U': + return 'U' + if na == 'X' or nb == 'X': + return 'X' + return '1' + +def sl_not(a): + """not definition""" + na = ux01_map[a] + if na == 'U': + return 'U' + if na == 'X': + return 'X' + if na == '1': + return '0' + else: + return '1' + +def sl_or(a,b): + "or definition" + return sl_not(sl_and (sl_not(a), sl_not(b))) + +def sl_xor(a,b): + "xor definition" + return sl_or(sl_and(a, sl_not(b)), + sl_and(sl_not(a), b)) + +# Stream to write. +out=sys.stdout + +def w(s): + "Write S to the output" + out.write(s) + +def gen_log_table2(name, func): + "Generate a logic table for binary operator NAME using its model FUNC" + w(""" + constant {0}_table : table_2d := + -- UX01ZWLH- + (""".format(name)) + for a in std_logic: + w('"') + for b in std_logic: + w(func (a, b)) + w('"') + if a != '-': + w(',') + else: + w(' ') + w(' -- {}\n'.format(a)) + w(' ') + w(');\n') + +def gen_log_table1(name, func): + "Generate a logic table for unary operator NAME using its model FUNC" + w(""" + constant {0}_table : table_1d := + -- UX01ZWLH- + """.format(name)) + w('"') + for b in std_logic: + w(func (b)) + w('";\n') + +def disp_tables(): + "Generate logic tables" + gen_log_table2("and", sl_and) + gen_log_table2("nand", lambda a,b : sl_not(sl_and(a, b))) + gen_log_table2("or", sl_or) + gen_log_table2("nor", lambda a,b : sl_not(sl_or(a,b))) + gen_log_table2("xor", sl_xor) + if "xnor" in binary_funcs: + gen_log_table2("xnor", lambda a,b : sl_not(sl_xor(a,b))) + gen_log_table1("not", sl_not) + +vec_types = ['ulogic', 'logic'] + +def disp_scalar_binary(fun): + "Generate scalar binary function body" + w(""" + function "{0}" (l, r : std_ulogic) return UX01 is + begin + return {0}_table (l, r); + end "{0}";\n""".format(fun)) + +def disp_scalar_unary(fun): + "Generate scalar unary function body" + w(""" + function "{0}" (l : std_ulogic) return UX01 is + begin + return {0}_table (l); + end "{0}";\n""".format(fun)) + +def disp_vec_binary(func, typ): + "Generate vector binary function body" + w(""" + function "{0}" (l, r : std_{1}_vector) return std_{1}_vector + is + subtype res_type is std_{1}_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_{1}_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded '{0}' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := {0}_table (la (I), ra (I)); + end loop; + end if; + return res; + end "{0}";\n""".format(func, typ)) + +def disp_vec_unary(func, typ): + "Generate vector unary function body" + w(""" + function "{0}" (l : std_{1}_vector) return std_{1}_vector + is + subtype res_type is std_{1}_vector (1 to l'length); + alias la : res_type is l; + variable res : res_type; + begin + for I in res_type'range loop + res (I) := {0}_table (la (I)); + end loop; + return res; + end "{0}";\n""".format(func, typ)) + +def disp_all_log_funcs(): + "Generate all function bodies for logic operators" + for f in binary_funcs: + disp_scalar_binary(f) + disp_scalar_unary("not") + for v in vec_types: + typ = "std_" + v + "_vector" + for f in binary_funcs: + disp_vec_binary(f, v) + disp_vec_unary("not", v) + +def disp_sv_to_bv_conv(typ): + "Generate logic vector to bit vector function body" + w(""" + function to_bitvector (s : std_{0}_vector; xmap : bit := '0') + return bit_vector + is + subtype res_range is natural range s'length - 1 downto 0; + alias as : std_{0}_vector (res_range) is s; + variable res : bit_vector (res_range); + variable b : bit; + begin + for I in res_range loop + -- Inline for efficiency. + case as (I) is + when '0' | 'L' => + b := '0'; + when '1' | 'H' => + b := '1'; + when others => + b := xmap; + end case; + res (I) := b; + end loop; + return res; + end to_bitvector;\n""".format(typ)) + +def disp_bv_to_sv_conv(typ): + "Generate bit vector to logic vector function body" + w(""" + function to_std{0}vector (b : bit_vector) return std_{0}_vector is + subtype res_range is natural range b'length - 1 downto 0; + alias ab : bit_vector (res_range) is b; + variable res : std_{0}_vector (res_range); + begin + for I in res_range loop + res (I) := bit_to_std (ab (I)); + end loop; + return res; + end to_std{0}vector;\n""".format(typ)) + +def disp_sv_to_sv_conv(s,d): + "Generate logic vector to logic vector function body" + w(""" + function to_std{1}vector (b : std_{0}_vector) return std_{1}_vector + is + subtype res_type is std_{1}_vector (b'length - 1 downto 0); + begin + return res_type (b); + end to_std{1}vector;\n""".format(s,d)) + +def disp_all_conv_funcs(): + "Generate conversion function bodies" + for v in vec_types: + disp_sv_to_bv_conv(v) + for v in vec_types: + disp_bv_to_sv_conv(v) + disp_sv_to_sv_conv('logic', 'ulogic') + disp_sv_to_sv_conv('ulogic', 'logic') + +def disp_conv_vec_vec(typ, v): + "Generate function body for vector conversion" + utyp = typ.upper(); + w(""" + function to_{1} (s : std_{2}_vector) return std_{2}_vector + is + subtype res_type is std_{2}_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_{0} (sa (i)); + end loop; + return res; + end to_{1};\n""".format(typ, utyp, v)) + +def disp_conv_std(typ): + "Generate function body for scalar conversion" + utyp = typ.upper(); + w(""" + function to_{1} (s : std_ulogic) return {1} is + begin + return std_to_{0} (s); + end to_{1};\n""".format(typ, utyp)) + +def disp_conv_bv_vec(typ, v): + "Generate function body for bit vector conversion" + utyp = typ.upper(); + w(""" + function to_{1} (b : bit_vector) return std_{2}_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_{2}_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_{1};\n""".format(typ, utyp, v)) + +def disp_conv_b_t(typ): + "Generate function body for bit conversion" + utyp = typ.upper(); + w(""" + function to_{1} (b : bit) return {1} is + begin + return bit_to_x01 (b); + end to_{1};\n""".format(typ, utyp)) + +def disp_all_norm_funcs(): + "Generate all function bodies for conversion" + for typ in [ "x01", "x01z", "ux01" ]: + for v in vec_types: + disp_conv_vec_vec(typ, v) + disp_conv_std (typ) + for v in vec_types: + disp_conv_bv_vec(typ, v) + disp_conv_b_t(typ) + +def disp_all_isx_funcs(): + "Generate all function bodies for isx functions" + for v in vec_types: + w(""" + function is_X (s : std_{0}_vector) return boolean is + begin + for i in s'range loop + if std_x (s (i)) then + return true; + end if; + end loop; + return false; + end is_X;\n""".format(v)) + + w(""" + function is_X (s : std_ulogic) return boolean is + begin + return std_x (s); + end is_X;\n""") + + +# Patterns to replace +pats = {' @TAB\n' : disp_tables, + ' @LOG\n' : disp_all_log_funcs, + ' @CONV\n': disp_all_conv_funcs, + ' @NORM\n': disp_all_norm_funcs, + ' @ISX\n' : disp_all_isx_funcs } + +spec_file='std_logic_1164.vhdl' +proto_file='std_logic_1164-body.proto' + +def gen_body(): + w('-- This file was generated from ' + proto_file + '\n') + for line in open(proto_file): + if line in pats: + pats[line]() + continue + w(line) + +# Copy spec +out=open('std_logic_1164.v87', 'w') +for line in open(spec_file): + if '"xnor"' in line: + w("--" + line[2:]) + else: + w(line) +out.close() + +out=open('std_logic_1164.v93', 'w') +for line in open(spec_file): + w(line) +out.close() + +# Generate bodies +out=open('std_logic_1164-body.v87', 'w') +gen_body() +out.close() + +binary_funcs.append("xnor") +out=open('std_logic_1164-body.v93', 'w') +gen_body() +out.close() diff --git a/libraries/redist1164/std_logic_1164-body.proto b/libraries/redist1164/std_logic_1164-body.proto new file mode 100644 index 0000000..aacf4c2 --- /dev/null +++ b/libraries/redist1164/std_logic_1164-body.proto @@ -0,0 +1,123 @@ +-- This is an implementation of -*- vhdl -*- ieee.std_logic_1164 based only +-- on the specifications. This file is part of GHDL. +-- Copyright (C) 2015 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING3. If not see +-- <http://www.gnu.org/licenses/>. + +-- This is a template file. To avoid errors and duplication, the python +-- script build.py generate most of the bodies. + +package body std_logic_1164 is + + type table_1d is array (std_ulogic) of std_ulogic; + type table_2d is array (std_ulogic, std_ulogic) of std_ulogic; + + constant resolution : table_2d := + -- UX01ZWLH- + ("UUUUUUUUU", -- U + "UXXXXXXXX", -- X + "UX0X0000X", -- 0 + "UXX11111X", -- 1 + "UX01ZWLHX", -- Z + "UX01WWWWX", -- W + "UX01LWLWX", -- L + "UX01HWWHX", -- H + "UXXXXXXXX" -- - + ); + + function resolved (s : std_ulogic_vector) return std_ulogic + is + variable res : std_ulogic := 'Z'; + begin + for I in s'range loop + res := resolution (res, s (I)); + end loop; + return res; + end resolved; + + @TAB + + @LOG + + -- Conversion functions. + -- The result range (for vectors) is S'Length - 1 downto 0. + -- XMAP is return for values not in '0', '1', 'L', 'H'. + function to_bit (s : std_ulogic; xmap : bit := '0') return bit is + begin + case s is + when '0' | 'L' => + return '0'; + when '1' | 'H' => + return '1'; + when others => + return xmap; + end case; + end to_bit; + + type bit_to_std_table is array (bit) of std_ulogic; + constant bit_to_std : bit_to_std_table := "01"; + + @CONV + + function to_stdulogic (b : bit) return std_ulogic is + begin + return bit_to_std (b); + end to_stdulogic; + + -- Normalization. + type table_std_x01 is array (std_ulogic) of X01; + constant std_to_x01 : table_std_x01 := ('U' | 'X' | 'Z' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1'); + + type table_bit_x01 is array (bit) of X01; + constant bit_to_x01 : table_bit_x01 := ('0' => '0', + '1' => '1'); + + + type table_std_x01z is array (std_ulogic) of X01Z; + constant std_to_x01z : table_std_x01 := ('U' | 'X' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1', + 'Z' => 'Z'); + + type table_std_ux01 is array (std_ulogic) of UX01; + constant std_to_ux01 : table_std_ux01 := ('U' => 'U', + 'X' | 'Z' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1'); + + @NORM + + function rising_edge (signal s : std_ulogic) return boolean is + begin + return s'event + and to_x01 (s'last_value) = '0' + and to_x01 (s) = '1'; + end rising_edge; + + function falling_edge (signal s : std_ulogic) return boolean is + begin + return s'event + and to_x01 (s'last_value) = '1' + and to_x01 (s) = '0'; + end falling_edge; + + type std_x_array is array (std_ulogic) of boolean; + constant std_x : std_x_array := ('U' | 'X' | 'Z' | 'W' | '-' => true, + '0' | '1' | 'L' | 'H' => false); + + @ISX +end std_logic_1164; diff --git a/libraries/redist1164/std_logic_1164-body.vhdl b/libraries/redist1164/std_logic_1164-body.vhdl new file mode 100644 index 0000000..f5170fa --- /dev/null +++ b/libraries/redist1164/std_logic_1164-body.vhdl @@ -0,0 +1,768 @@ +-- This is an implementation of -*- vhdl -*- ieee.std_logic_1164 based only +-- on the specifications. This file is part of GHDL. +-- Copyright (C) 2015 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING3. If not see +-- <http://www.gnu.org/licenses/>. + +-- This is a template file. To avoid errors and duplication, the python +-- script build.py generate most of the bodies. + +package body std_logic_1164 is + + type table_1d is array (std_ulogic) of std_ulogic; + type table_2d is array (std_ulogic, std_ulogic) of std_ulogic; + + constant resolution : table_2d := + -- UX01ZWLH- + ("UUUUUUUUU", -- U + "UXXXXXXXX", -- X + "UX0X0000X", -- 0 + "UXX11111X", -- 1 + "UX01ZWLHX", -- Z + "UX01WWWWX", -- W + "UX01LWLWX", -- L + "UX01HWWHX", -- H + "UXXXXXXXX" -- - + ); + + function resolved (s : std_ulogic_vector) return std_ulogic + is + variable res : std_ulogic := 'Z'; + begin + for I in s'range loop + res := resolution (res, s (I)); + end loop; + return res; + end resolved; + + + constant and_table : table_2d := + -- UX01ZWLH- + ("UU0UUU0UU", -- U + "UX0XXX0XX", -- X + "000000000", -- 0 + "UX01XX01X", -- 1 + "UX0XXX0XX", -- Z + "UX0XXX0XX", -- W + "000000000", -- L + "UX01XX01X", -- H + "UX0XXX0XX" -- - + ); + + constant nand_table : table_2d := + -- UX01ZWLH- + ("UU1UUU1UU", -- U + "UX1XXX1XX", -- X + "111111111", -- 0 + "UX10XX10X", -- 1 + "UX1XXX1XX", -- Z + "UX1XXX1XX", -- W + "111111111", -- L + "UX10XX10X", -- H + "UX1XXX1XX" -- - + ); + + constant or_table : table_2d := + -- UX01ZWLH- + ("UUU1UUU1U", -- U + "UXX1XXX1X", -- X + "UX01XX01X", -- 0 + "111111111", -- 1 + "UXX1XXX1X", -- Z + "UXX1XXX1X", -- W + "UX01XX01X", -- L + "111111111", -- H + "UXX1XXX1X" -- - + ); + + constant nor_table : table_2d := + -- UX01ZWLH- + ("UUU0UUU0U", -- U + "UXX0XXX0X", -- X + "UX10XX10X", -- 0 + "000000000", -- 1 + "UXX0XXX0X", -- Z + "UXX0XXX0X", -- W + "UX10XX10X", -- L + "000000000", -- H + "UXX0XXX0X" -- - + ); + + constant xor_table : table_2d := + -- UX01ZWLH- + ("UUUUUUUUU", -- U + "UXXXXXXXX", -- X + "UX01XX01X", -- 0 + "UX10XX10X", -- 1 + "UXXXXXXXX", -- Z + "UXXXXXXXX", -- W + "UX01XX01X", -- L + "UX10XX10X", -- H + "UXXXXXXXX" -- - + ); + + constant xnor_table : table_2d := + -- UX01ZWLH- + ("UUUUUUUUU", -- U + "UXXXXXXXX", -- X + "UX10XX10X", -- 0 + "UX01XX01X", -- 1 + "UXXXXXXXX", -- Z + "UXXXXXXXX", -- W + "UX10XX10X", -- L + "UX01XX01X", -- H + "UXXXXXXXX" -- - + ); + + constant not_table : table_1d := + -- UX01ZWLH- + "UX10XX10X"; + + + function "and" (l, r : std_ulogic) return UX01 is + begin + return and_table (l, r); + end "and"; + + function "nand" (l, r : std_ulogic) return UX01 is + begin + return nand_table (l, r); + end "nand"; + + function "or" (l, r : std_ulogic) return UX01 is + begin + return or_table (l, r); + end "or"; + + function "nor" (l, r : std_ulogic) return UX01 is + begin + return nor_table (l, r); + end "nor"; + + function "xor" (l, r : std_ulogic) return UX01 is + begin + return xor_table (l, r); + end "xor"; + + function "xnor" (l, r : std_ulogic) return UX01 is + begin + return xnor_table (l, r); + end "xnor"; + + function "not" (l : std_ulogic) return UX01 is + begin + return not_table (l); + end "not"; + + function "and" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'and' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := and_table (la (I), ra (I)); + end loop; + end if; + return res; + end "and"; + + function "nand" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'nand' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := nand_table (la (I), ra (I)); + end loop; + end if; + return res; + end "nand"; + + function "or" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'or' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := or_table (la (I), ra (I)); + end loop; + end if; + return res; + end "or"; + + function "nor" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'nor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := nor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "nor"; + + function "xor" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'xor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := xor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "xor"; + + function "xnor" (l, r : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_ulogic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'xnor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := xnor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "xnor"; + + function "not" (l : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to l'length); + alias la : res_type is l; + variable res : res_type; + begin + for I in res_type'range loop + res (I) := not_table (la (I)); + end loop; + return res; + end "not"; + + function "and" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'and' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := and_table (la (I), ra (I)); + end loop; + end if; + return res; + end "and"; + + function "nand" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'nand' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := nand_table (la (I), ra (I)); + end loop; + end if; + return res; + end "nand"; + + function "or" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'or' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := or_table (la (I), ra (I)); + end loop; + end if; + return res; + end "or"; + + function "nor" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'nor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := nor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "nor"; + + function "xor" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'xor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := xor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "xor"; + + function "xnor" (l, r : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + alias ra : std_logic_vector (1 to r'length) is r; + variable res : res_type; + begin + if la'length /= ra'length then + assert false + report "arguments of overloaded 'xnor' operator are not of the same length" + severity failure; + else + for I in res_type'range loop + res (I) := xnor_table (la (I), ra (I)); + end loop; + end if; + return res; + end "xnor"; + + function "not" (l : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to l'length); + alias la : res_type is l; + variable res : res_type; + begin + for I in res_type'range loop + res (I) := not_table (la (I)); + end loop; + return res; + end "not"; + + -- Conversion functions. + -- The result range (for vectors) is S'Length - 1 downto 0. + -- XMAP is return for values not in '0', '1', 'L', 'H'. + function to_bit (s : std_ulogic; xmap : bit := '0') return bit is + begin + case s is + when '0' | 'L' => + return '0'; + when '1' | 'H' => + return '1'; + when others => + return xmap; + end case; + end to_bit; + + type bit_to_std_table is array (bit) of std_ulogic; + constant bit_to_std : bit_to_std_table := "01"; + + + function to_bitvector (s : std_ulogic_vector; xmap : bit := '0') + return bit_vector + is + subtype res_range is natural range s'length - 1 downto 0; + alias as : std_ulogic_vector (res_range) is s; + variable res : bit_vector (res_range); + variable b : bit; + begin + for I in res_range loop + -- Inline for efficiency. + case as (I) is + when '0' | 'L' => + b := '0'; + when '1' | 'H' => + b := '1'; + when others => + b := xmap; + end case; + res (I) := b; + end loop; + return res; + end to_bitvector; + + function to_bitvector (s : std_logic_vector; xmap : bit := '0') + return bit_vector + is + subtype res_range is natural range s'length - 1 downto 0; + alias as : std_logic_vector (res_range) is s; + variable res : bit_vector (res_range); + variable b : bit; + begin + for I in res_range loop + -- Inline for efficiency. + case as (I) is + when '0' | 'L' => + b := '0'; + when '1' | 'H' => + b := '1'; + when others => + b := xmap; + end case; + res (I) := b; + end loop; + return res; + end to_bitvector; + + function to_stdulogicvector (b : bit_vector) return std_ulogic_vector is + subtype res_range is natural range b'length - 1 downto 0; + alias ab : bit_vector (res_range) is b; + variable res : std_ulogic_vector (res_range); + begin + for I in res_range loop + res (I) := bit_to_std (ab (I)); + end loop; + return res; + end to_stdulogicvector; + + function to_stdlogicvector (b : bit_vector) return std_logic_vector is + subtype res_range is natural range b'length - 1 downto 0; + alias ab : bit_vector (res_range) is b; + variable res : std_logic_vector (res_range); + begin + for I in res_range loop + res (I) := bit_to_std (ab (I)); + end loop; + return res; + end to_stdlogicvector; + + function to_stdulogicvector (b : std_logic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (b'length - 1 downto 0); + begin + return res_type (b); + end to_stdulogicvector; + + function to_stdlogicvector (b : std_ulogic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (b'length - 1 downto 0); + begin + return res_type (b); + end to_stdlogicvector; + + function to_stdulogic (b : bit) return std_ulogic is + begin + return bit_to_std (b); + end to_stdulogic; + + -- Normalization. + type table_std_x01 is array (std_ulogic) of X01; + constant std_to_x01 : table_std_x01 := ('U' | 'X' | 'Z' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1'); + + type table_bit_x01 is array (bit) of X01; + constant bit_to_x01 : table_bit_x01 := ('0' => '0', + '1' => '1'); + + + type table_std_x01z is array (std_ulogic) of X01Z; + constant std_to_x01z : table_std_x01 := ('U' | 'X' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1', + 'Z' => 'Z'); + + type table_std_ux01 is array (std_ulogic) of UX01; + constant std_to_ux01 : table_std_ux01 := ('U' => 'U', + 'X' | 'Z' | 'W' | '-' => 'X', + '0' | 'L' => '0', + '1' | 'H' => '1'); + + + function to_X01 (s : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_x01 (sa (i)); + end loop; + return res; + end to_X01; + + function to_X01 (s : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_x01 (sa (i)); + end loop; + return res; + end to_X01; + + function to_X01 (s : std_ulogic) return X01 is + begin + return std_to_x01 (s); + end to_X01; + + function to_X01 (b : bit_vector) return std_ulogic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_ulogic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_X01; + + function to_X01 (b : bit_vector) return std_logic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_logic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_X01; + + function to_X01 (b : bit) return X01 is + begin + return bit_to_x01 (b); + end to_X01; + + function to_X01Z (s : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_x01z (sa (i)); + end loop; + return res; + end to_X01Z; + + function to_X01Z (s : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_x01z (sa (i)); + end loop; + return res; + end to_X01Z; + + function to_X01Z (s : std_ulogic) return X01Z is + begin + return std_to_x01z (s); + end to_X01Z; + + function to_X01Z (b : bit_vector) return std_ulogic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_ulogic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_X01Z; + + function to_X01Z (b : bit_vector) return std_logic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_logic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_X01Z; + + function to_X01Z (b : bit) return X01Z is + begin + return bit_to_x01 (b); + end to_X01Z; + + function to_UX01 (s : std_ulogic_vector) return std_ulogic_vector + is + subtype res_type is std_ulogic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_ux01 (sa (i)); + end loop; + return res; + end to_UX01; + + function to_UX01 (s : std_logic_vector) return std_logic_vector + is + subtype res_type is std_logic_vector (1 to s'length); + alias sa : res_type is s; + variable res : res_type; + begin + for i in res_type'range loop + res (i) := std_to_ux01 (sa (i)); + end loop; + return res; + end to_UX01; + + function to_UX01 (s : std_ulogic) return UX01 is + begin + return std_to_ux01 (s); + end to_UX01; + + function to_UX01 (b : bit_vector) return std_ulogic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_ulogic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_UX01; + + function to_UX01 (b : bit_vector) return std_logic_vector + is + subtype res_range is natural range 1 to b'length; + alias ba : bit_vector (res_range) is b; + variable res : std_logic_vector (res_range); + begin + for i in res_range loop + res (i) := bit_to_x01 (ba (i)); + end loop; + return res; + end to_UX01; + + function to_UX01 (b : bit) return UX01 is + begin + return bit_to_x01 (b); + end to_UX01; + + function rising_edge (signal s : std_ulogic) return boolean is + begin + return s'event + and to_x01 (s'last_value) = '0' + and to_x01 (s) = '1'; + end rising_edge; + + function falling_edge (signal s : std_ulogic) return boolean is + begin + return s'event + and to_x01 (s'last_value) = '1' + and to_x01 (s) = '0'; + end falling_edge; + + type std_x_array is array (std_ulogic) of boolean; + constant std_x : std_x_array := ('U' | 'X' | 'Z' | 'W' | '-' => true, + '0' | '1' | 'L' | 'H' => false); + + + function is_X (s : std_ulogic_vector) return boolean is + begin + for i in s'range loop + if std_x (s (i)) then + return true; + end if; + end loop; + return false; + end is_X; + + function is_X (s : std_logic_vector) return boolean is + begin + for i in s'range loop + if std_x (s (i)) then + return true; + end if; + end loop; + return false; + end is_X; + + function is_X (s : std_ulogic) return boolean is + begin + return std_x (s); + end is_X; +end std_logic_1164; diff --git a/libraries/redist1164/std_logic_1164.vhdl b/libraries/redist1164/std_logic_1164.vhdl new file mode 100644 index 0000000..0ee62a1 --- /dev/null +++ b/libraries/redist1164/std_logic_1164.vhdl @@ -0,0 +1,143 @@ +-- This is an implementation of ieee.std_logic_1164 based only on the +-- specifications. This file is part of GHDL. +-- Copyright (C) 2015 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING3. If not see +-- <http://www.gnu.org/licenses/>. + +-- This package is valid for VHDL version until but not including 2008. +-- For VHDL87, the functions xnor should be removed. + +package std_logic_1164 is + + -- Unresolved logic state. + type std_ulogic is + ('U', -- Uninitialized, this is also the default value. + 'X', -- Unknown / conflict value (forcing level). + '0', -- 0 (forcing level). + '1', -- 1 (forcing level). + 'Z', -- High impedance. + 'W', -- Unknown / conflict (weak level). + 'L', -- 0 (weak level). + 'H', -- 1 (weak level). + '-' -- Don't care. + ); + + -- Vector of logic state. + type std_ulogic_vector is array (natural range <>) of std_ulogic; + + -- Resolution function. + -- If S is empty, returns 'Z'. + -- If S has one element, return the element. + -- Otherwise, 'U' is the strongest. + -- then 'X' + -- then '0' and '1' + -- then 'W' + -- then 'H' and 'L' + -- then 'Z'. + function resolved (s : std_ulogic_vector) return std_ulogic; + + -- Resolved logic state. + subtype std_logic is resolved std_ulogic; + + -- Vector of std_logic. + type std_logic_vector is array (natural range <>) of std_logic; + + -- Subtypes of std_ulogic. The names give the values. + subtype X01 is resolved std_ulogic range 'X' to '1'; + subtype X01Z is resolved std_ulogic range 'X' to 'Z'; + subtype UX01 is resolved std_ulogic range 'U' to '1'; + subtype UX01Z is resolved std_ulogic range 'U' to 'Z'; + + -- Logical operators. + -- For logical operations, the inputs are first normalized to UX01: + -- 0 and L are normalized to 0, 1 and 1 are normalized to 1, U isnt changed, + -- all other states are normalized to X. + -- Then the classical electric rules are followed. + function "and" (l, r : std_ulogic) return UX01; + function "nand" (l, r : std_ulogic) return UX01; + function "or" (l, r : std_ulogic) return UX01; + function "nor" (l, r : std_ulogic) return UX01; + function "xor" (l, r : std_ulogic) return UX01; + function "xnor" (l, r : std_ulogic) return UX01; + function "not" (l : std_ulogic) return UX01; + + -- Logical operators for vectors. + -- An assertion of severity failure fails if the length of L and R aren't + -- equal. The result range is 1 to L'Length. + function "and" (l, r : std_logic_vector) return std_logic_vector; + function "nand" (l, r : std_logic_vector) return std_logic_vector; + function "or" (l, r : std_logic_vector) return std_logic_vector; + function "nor" (l, r : std_logic_vector) return std_logic_vector; + function "xor" (l, r : std_logic_vector) return std_logic_vector; + function "xnor" (l, r : std_logic_vector) return std_logic_vector; + function "not" (l : std_logic_vector) return std_logic_vector; + + function "and" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "nand" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "or" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "nor" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "xor" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "xnor" (l, r : std_ulogic_vector) return std_ulogic_vector; + function "not" (l : std_ulogic_vector) return std_ulogic_vector; + + -- Conversion functions. + -- The result range (for vectors) is S'Length - 1 downto 0. + -- XMAP is return for values not in '0', '1', 'L', 'H'. + function to_bit (s : std_ulogic; xmap : bit := '0') return bit; + function to_bitvector (s : std_logic_vector; xmap : bit := '0') + return bit_vector; + function to_bitvector (s : std_ulogic_vector; xmap : bit := '0') + return bit_vector; + + function to_stdulogic (b : bit) return std_ulogic; + function to_stdlogicvector (b : bit_vector) return std_logic_vector; + function to_stdlogicvector (b : std_ulogic_vector) return std_logic_vector; + function to_stdulogicvector (b : bit_vector) return std_ulogic_vector; + function to_stdulogicvector (b : std_logic_vector) return std_ulogic_vector; + + -- Normalization. + -- The result range (for vectors) is 1 to S'Length. + function to_X01 (s : std_logic_vector) return std_logic_vector; + function to_X01 (s : std_ulogic_vector) return std_ulogic_vector; + function to_X01 (s : std_ulogic) return X01; + function to_X01 (b : bit_vector) return std_logic_vector; + function to_X01 (b : bit_vector) return std_ulogic_vector; + function to_X01 (b : bit) return X01; + + function to_X01Z (s : std_logic_vector) return std_logic_vector; + function to_X01Z (s : std_ulogic_vector) return std_ulogic_vector; + function to_X01Z (s : std_ulogic) return X01Z; + function to_X01Z (b : bit_vector) return std_logic_vector; + function to_X01Z (b : bit_vector) return std_ulogic_vector; + function to_X01Z (b : bit) return X01Z; + + function to_UX01 (s : std_logic_vector) return std_logic_vector; + function to_UX01 (s : std_ulogic_vector) return std_ulogic_vector; + function to_UX01 (s : std_ulogic) return UX01; + function to_UX01 (b : bit_vector) return std_logic_vector; + function to_UX01 (b : bit_vector) return std_ulogic_vector; + function to_UX01 (b : bit) return UX01; + + -- Edge detection. + -- An edge is detected in case of event on s, and X01 normalized value + -- rises from 0 to 1 or falls from 1 to 0. + function rising_edge (signal s : std_ulogic) return boolean; + function falling_edge (signal s : std_ulogic) return boolean; + + -- Test for unknown. Only 0, 1, L and H are known values. + function is_X (s : std_ulogic_vector) return boolean; + function is_X (s : std_logic_vector) return boolean; + function is_X (s : std_ulogic) return boolean; +end std_logic_1164; |