VDHL sfixed decoding code does not work properly

后端 未结 2 1985
情书的邮戳
情书的邮戳 2021-01-26 10:58

I am using David bishop\'s fixed point library to do some math in vhdl. and i need to decode the final value into integers. the method i have followed as below,

相关标签:
2条回答
  • 2021-01-26 11:45

    Modifying your original code with fixes for div10, mod10 (with underscores leaving the declarations alone) and producing an MCVE:

    library ieee;
    use ieee.fixed_pkg.all;
    
    entity iopertyki is
    end entity;
    
    architecture fum of iopertyki is
    begin
        process
            variable  cp:       sfixed(20 downto -19);
            variable mod_10:    sfixed(4 downto 0);
            variable div_10:    sfixed(4 downto 0);
            variable mul_10:    sfixed(4 downto 0); 
    
            variable L0:        sfixed(4 downto 0);
            variable L1:        sfixed(4 downto -4);
            variable L2:        sfixed(4 downto -8);
            variable L3:        sfixed(4 downto -12);
            variable L4:        sfixed(4 downto -16);
            variable L5:        sfixed(4 downto -20);
            variable L6:        sfixed(4 downto -24); 
    
            variable temp_L:    sfixed(19 downto 0);
            variable temp_L1:   sfixed(20 downto -4);
            variable temp_L2:   sfixed(21 downto -8);
            variable temp_L3:   sfixed(22 downto -12);
            variable temp_L4:   sfixed(23 downto -16);
            variable temp_L5:   sfixed(24 downto -20);
            variable temp_L6:   sfixed(25 downto -24);
        begin
            cp    :=  to_sfixed(174334.738295,20,-19);
            report "cp = " & to_string(cp);
            temp_L      := cp(19 downto 0); -- remove sign bit
            report "temp_L = " & to_string(temp_L);
            report "integer'image temp_L = " & integer'image(to_integer(temp_L));
            mod_10 := to_sfixed(10,4,0);                 
            div_10 := to_sfixed(10,4,0);
            mul_10 := to_sfixed(10,4,0);
    
            L0          := temp_L mod mod_10;
            temp_L1     := temp_L/div_10;
            L1          := temp_L1 mod mod_10;
            temp_L2     := temp_L1/div_10;
            L2          := temp_L2 mod mod_10;
            temp_L3     := temp_L2/div_10;
            L3          := temp_L3 mod mod_10; 
            temp_L4     := temp_L3/div_10;
            L4          := temp_L4 mod mod_10;              
            temp_L5     := temp_L4/div_10;
            L5          := temp_L5 mod mod_10;
            temp_L6     := temp_L5/div_10;
            L6          := temp_L6 mod mod_10; 
            -- xx8374.839923 ? 
            report " result   = " & integer'image(to_integer(L6)) &
                                  integer'image(to_integer(L5)) &
                                  integer'image(to_integer(L4)) &
                                  integer'image(to_integer(L3)) &
                                  integer'image(to_integer(L2)) &
                                  integer'image(to_integer(L1)) &
                                  integer'image(to_integer(L0));
    
            report " no round = " & integer'image(to_integer(L6(4 downto 0))) &
                                  integer'image(to_integer(L5(4 downto 0))) &
                                  integer'image(to_integer(L4(4 downto 0))) &
                                  integer'image(to_integer(L3(4 downto 0))) &
                                  integer'image(to_integer(L2(4 downto 0))) &
                                  integer'image(to_integer(L1(4 downto 0))) &
                                  integer'image(to_integer(L0(4 downto 0)));
            wait;
        end process;
    end architecture;
    

    This produces the integer part result (you don't demonstrate how you did this in your question, with the new results:

    ...get 274334.738295 for 174334.738295

    You can demonstrate that to_integer rounding is responsible for L5 being 2 instead of 1:

    ghdl -a --std=08 iopertyki.vhdl
    ghdl -e --std=08 iopertyki
    ghdl -r iopertyki
    
    iopertyki.vhdl:91:9:@0ms:(report note): cp = 000101010100011111110.1011110100000000111
    iopertyki.vhdl:93:9:@0ms:(report note): temp_L = 00101010100011111110.0
    iopertyki.vhdl:94:9:@0ms:(report note): integer'image temp_L = 174334
    iopertyki.vhdl:113:9:@0ms:(report note):  result   = 0274334
    iopertyki.vhdl:121:9:@0ms:(report note):  no round = 0174334
    

    So all this tells you to only use the integer part of L6 - L1 so there is no rounding. (There's a hint for how clipping an sfixed or ufixed value will work in David Bishop's user guide you commented on).

    You could note that clipping an sfixed value will be subject to a sign bias and that you'd either need to change sign of all the recovered decimal digits or use signed magnitude (where your digit calculations might be ufixed) with the sign forwarded to the result for negative numbers. Math in decades can be cumbersome.

    Notes on elaboration and simulation when using ghdl

    There are three architectures of code generation for ghdl, using a GCC backend, an LLVM back end and an mcode just in time code generator.

    From the newest GHDL Documentation section on Invoking GHDL for the run command:

    run -r

    Runs/simulates a design. The options and arguments are the same as for the elaboration command.

    • GGC/LLVM: simply, the filename of the executable is determined and it is executed. Options are ignored. You may also directly execute the program. The executable must be in the current directory.
    • mcode: the design is elaborated and the simulation is launched. As a consequence, you must use the same options used during analysis.

    In an mcode version such as distributed for Win32 the -e elaborate command is redundant and the run command (-r) must include the same options as for the analysis command (-a).

    For GCC/LLVM backend codegenerator versions of ghdl the elaborate (-e) command must have the same options as the analysis command (-a). For --std=08 a different working library is used and any object files produced without the std option or with a different STD value will be overwritten if the library directory is not specified separately.

    There are no object files for the mcode version. The analyzed objects only exist in the ghdl program's memory where the are subsequently elaborated with the run (-r) command into a simulation design model.

    Without specifying versions or release the ghdl user can only rely on ghdl documentation.

    You could also note that ghdl-0.34 has been released in the last day and a Win32 binary image (mcode) and 64 bit binary image (llvm) are available (their names include "mingw").

    0 讨论(0)
  • 2021-01-26 11:54

    Your divisions should be integer divisions; they are not (fixed point divisions). And I do not even imagine what the modulus operator is supposed to return when applied to non integer (fixed point) arguments. Anyway, this fixed point representation is quite simple, so, if you just want the digits of the integer part of a positive fixed point number, you could first convert it to natural, and then compute the digits:

    library ieee;
    use ieee.numeric_std.all;
    use ieee.std_logic_1164.all;
    ...
    variable n: natural;
    subtype digit is natural range 0 to 9;
    type digit_vector is array(natural range <>) of digits;
    variable digits: digit_vector(5 downto 0);
    ...
    n := to_integer(u_unsigned(cp(20 downto 0)));
    for i in 0 to 5 loop
      digits(i) := n mod 10;
      n := n / 10;
    end loop;
    

    Or, if you simply want to print the decimal representation of cp:

    use std.textio.all;
    ...
    variable l: line;
    ...
    write(l, to_integer(u_unsigned(cp(20 downto 0)));
    writeline(output, n);
    

    Or, even simpler, use the write procedure from the library itself:

    variable tmp: sfixed(20 downto 0);
    ...
    tmp := cp(20 downto 0);
    write(l, tmp);
    writeline(output, l);
    
    0 讨论(0)
提交回复
热议问题