我正在尝试在函数中实现解码代码以返回多个变量,因为我必须解码两个固定点变量,并且我在fpga中得到错误,因为逻辑不足。所以我需要像在c语言中那样执行解码代码 - >使用两个变量调用该函数两次,并以单个数字返回。这可能会执行吗?如果有可能怎么办?或者还有其他方法吗?
我正在为两个固定点数执行以下两次代码 并且对小数部分进行解码。解码对整数部分和小数部分工作正常。 解码后我将它们转换为std_logic_vector并发送到我的lcd。这就是我解码价值的原因。代码大约1000行。 所以我不能把它放在这里。
在当前代码中我执行两次相同的解码,因此它产生了fpga不支持的大逻辑。他们个人工作。所以我需要把它放到一个函数中并调用该函数两次。
VDHL sfixed decoding code does not work properly
如链接代码所示,我得到整数部分的6个变量和小数部分的6个变量。我需要将此代码放在一个返回12个变量的函数中。
答案 0 :(得分:2)
在引用的问题中VDHL sfixed decoding code does not work properly Renaud Pacalet在他的回答Your divisions should be integer divisions; they are not (fixed point divisions).中评论说,没有特别的理由在实际的转换过程中使用签名的修正点数,也没有整数。
有一种算法(Double dabble)使用移位和4位条件添加,可以在循环语句中实现。这里的一个是20位整数部分算法的扩展。
还有一种实现小数部分的等价物的方法:
[多位二进制到十进制转换器(小数部分也是如此!)](http://www.minecraftforum.net/forums/minecraft-discussion/redstone-discussion-and/redstone-creations/352668-multi-digit-binary-to-decimal-converter-decimal"多位二进制到十进制转换器(小数部分也是如此!)")
有关算法如何运作的说明,请访问此网站:http://www.johnloomis.org/ece314/notes/devices/binary_to_BCD/bin_to_bcd.html
我更进了一步,并想出了如何应用相同的原理将二元分数转换为十进制分数。例如,0.11(bin)可以转换为0.75(dec)。通过使用具有执行反函数的转换表(如果为8或更多则为-3)并且在相反方向上移位。
最近由Hans_Lemurson编辑:2012年6月9日
虽然没有在Minecraft游戏中实现,但是分数涉及每个比较和减法的逻辑单元,就像双重涉及添加一样。
这些位是串行移位的,双倍的dabble是乘法器,分数dabble是一个分频器。双重dabble具有20位×7个BCD位(28位)或140个逻辑单元的最大add3逻辑单元数。它根据不能达到阈值(> 4)或保证全部' 0'或者保证全部' 0'投入。最终为57个逻辑单元(每4个4x1 LUT)。
分数dabble使用更多单元格,因为从左侧移位会立即抛出sub3操作的阈值。从18位x 6 BCD数字或108个sub3单元合成映射后的减少 只损失6,产生102个逻辑单元。 add3和sub3之间的差异是模4加法与减法,并且阈值(> 4)对比(> 7)。
通过使BCD值成为时钟寄存器并一次迭代20或18个操作时钟,可以进一步减少逻辑单元的数量(对于分数dabble来说更远)。需要状态机与输入和输出握手,并迭代表示二进制输入值长度的时钟数。
绝对值转换小于40个逻辑单元。
这里的想法是,一次使用顺序操作位代表性能与大小权衡(注意你没有使用固定除法和模数减少来指定当前实现的大小)。
以下代码将两个dabbles实现为不同的函数,这些函数可以针对更大或更小的固定值和BCD数字进行缩放,并且可能在Brian Drummond所指出的多路复用器之前,尽管根据它们的大小似乎不太可能&#39保证。 (多路复用器有多大?)。
“慢”的含义'性能是你不会比绝对值转换的下降时间更快地更新输入值(此处显示为cp
),这与两个dabbles(较大的一个)的最长时间连接在一起。
此代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.fixed_pkg.all; -- included in -2008
entity iopertyki is
end entity;
architecture fum of iopertyki is
function doubledabble_20bit (inp: std_logic_vector(19 downto 0))
return unsigned is
variable bin: std_logic_vector(inp'range);
variable bcd: unsigned(27 downto 0);
begin
bin := inp;
bcd := (others => '0');
for i in 0 to 19 loop
if bcd(3 downto 0) > 4 then
bcd(3 downto 0) := bcd(3 downto 0) + 3;
end if;
if bcd(7 downto 4) > 4 then
bcd(7 downto 4) := bcd(7 downto 4) + 3;
end if;
if bcd(11 downto 8) > 4 then
bcd(11 downto 8) := bcd(11 downto 8) + 3;
end if;
if bcd(15 downto 12) > 4 then
bcd(15 downto 12) := bcd(15 downto 12) + 3;
end if;
if bcd(19 downto 16) > 4 then
bcd(19 downto 16) := bcd(19 downto 16) + 3;
end if;
if bcd(23 downto 20) > 4 then
bcd(23 downto 20) := bcd(23 downto 20) + 3;
end if;
bcd := bcd(26 downto 0) & bin(19);
bin := bin(18 downto 0) & '0';
end loop;
return bcd;
end function;
function fracdabble_19bit (inp: std_logic_vector(18 downto 0))
return unsigned is
variable bin: std_logic_vector(inp'range);
variable bcd: unsigned(23 downto 0);
-- variable tbcd: unsigned(23 downto 0); -- DEBUG
begin
bin := inp;
bcd := (others => '0'); -- DEBUG
for i in 0 to 18 loop
bcd := bin(0) & bcd(23 downto 1);
bin := '0' & bin(18 downto 1);
-- tbcd := bcd; -- DEBUG
if bcd(3 downto 0) > 7 then
bcd(3 downto 0) := bcd(3 downto 0) - 3;
end if;
if bcd(7 downto 4) > 7 then
bcd(7 downto 4) := bcd(7 downto 4) - 3;
end if;
if bcd(11 downto 8) > 7 then
bcd(11 downto 8) := bcd(11 downto 8) - 3;
end if;
if bcd(15 downto 12) > 7 then
bcd(15 downto 12) := bcd(15 downto 12) - 3;
end if;
if bcd(19 downto 16) > 7 then
bcd(19 downto 16) := bcd(19 downto 16) - 3;
end if;
if bcd(23 downto 20) > 7 then
bcd(23 downto 20) := bcd(23 downto 20) - 3;
end if;
-- report "i = " & integer'image(i) & LF & HT & -- DEBUG
-- "prior sub3 bcd = " & to_string (tbcd) & LF & HT & -- DEBUG
-- "after sub3 bcd = " & to_string (bcd); -- DEBUG
end loop;
bcd(0) := inp(0); -- An odd binary produces an odd decimal value
return bcd; -- the algorithm loses the LSB
end function;
signal cp: sfixed(20 downto -19) := to_sfixed(174334.738295,20,-19);
begin
BCD_CONVERT:
process (cp)
variable int_digits: unsigned(27 downto 0);
variable frac_digits: unsigned(23 downto 0);
alias L6: unsigned(3 downto 0) is int_digits(27 downto 24);
alias L5: unsigned(3 downto 0) is int_digits(23 downto 20);
alias L4: unsigned(3 downto 0) is int_digits(19 downto 16);
alias L3: unsigned(3 downto 0) is int_digits(15 downto 12);
alias L2: unsigned(3 downto 0) is int_digits(11 downto 8);
alias L1: unsigned(3 downto 0) is int_digits(7 downto 4);
alias L0: unsigned(3 downto 0) is int_digits(3 downto 0);
alias R5: unsigned(3 downto 0) is frac_digits(23 downto 20);
alias R4: unsigned(3 downto 0) is frac_digits(19 downto 16);
alias R3: unsigned(3 downto 0) is frac_digits(15 downto 12);
alias R2: unsigned(3 downto 0) is frac_digits(11 downto 8);
alias R1: unsigned(3 downto 0) is frac_digits(7 downto 4);
alias R0: unsigned(3 downto 0) is frac_digits(3 downto 0);
variable scp: sfixed(20 downto -19);
variable sign: character;
begin
if cp < 0.0 then
scp := "-"(0.0, cp)(20 downto -19); -- change sign, slice length
sign := '-';
else
scp := cp;
sign := ' '; -- no sign instead of '+'
end if;
report LF & HT & " cp = " & to_string(cp) &
LF & HT & "absolute val cp = " & to_string(scp);
report LF & HT & "slv int = " & to_string(to_slv(scp)(38 downto 19))
& " slv frac = " & to_string(to_slv(scp)(18 downto 0));
-- leave off sign bit:
int_digits := doubledabble_20bit(to_slv(scp)(38 downto 19));
report "int_digits = " & to_string (int_digits);
-- 55 logic cells following mspping and reduction:
frac_digits := fracdabble_19bit(to_slv(scp)(18 downto 0));
report "frac_digits = " & to_string (frac_digits);
-- R6 = "0000"
report "result = " & sign &
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)) &
'.' &
integer'image(to_integer(R5)) &
integer'image(to_integer(R4)) &
integer'image(to_integer(R3)) &
integer'image(to_integer(R2)) &
integer'image(to_integer(R1)) &
integer'image(to_integer(R0));
end process;
MORE:
process
begin
wait for 20 ns;
cp <= "-"(cp)(20 downto -19); -- change sign, slice length
wait for 20 ns;
cp <= to_sfixed(-307.83929,20,-19);
wait;
end process;
end architecture;
经过分析,精心制作和模拟产生:
ghdl -a --std=08 iopertyki.vhdl ghdl -e --std=08 iopertyki ghdl -r --std=08 iopertyki iopertyki.vhdl:112:9:@0ms:(report note): cp = 000101010100011111110.1011110100000000111 absolute val cp = 000101010100011111110.1011110100000000111 iopertyki.vhdl:114:9:@0ms:(report note): slv int = 00101010100011111110 slv frac = 1011110100000000111 iopertyki.vhdl:118:9:@0ms:(report note): int_digits = 0000000101110100001100110100 iopertyki.vhdl:121:9:@0ms:(report note): frac_digits = 011100111000001010010101 iopertyki.vhdl:124:9:@0ms:(report note): result = 0174334.738295 iopertyki.vhdl:112:9:@20ns:(report note): cp = 111010101011100000001.0100001011111111001 absolute val cp = 000101010100011111110.1011110100000000111 iopertyki.vhdl:114:9:@20ns:(report note): slv int = 00101010100011111110 slv frac = 1011110100000000111 iopertyki.vhdl:118:9:@20ns:(report note): int_digits = 0000000101110100001100110100 iopertyki.vhdl:121:9:@20ns:(report note): frac_digits = 011100111000001010010101 iopertyki.vhdl:124:9:@20ns:(report note): result = -0174334.738295 iopertyki.vhdl:112:9:@40ns:(report note): cp = 111111111111011001100.0010100100100100010 absolute val cp = 000000000000100110011.1101011011011011110 iopertyki.vhdl:114:9:@40ns:(report note): slv int = 00000000000100110011 slv frac = 1101011011011011110 iopertyki.vhdl:118:9:@40ns:(report note): int_digits = 0000000000000000001100000111 iopertyki.vhdl:121:9:@40ns:(report note): frac_digits = 100000111001001010010000 iopertyki.vhdl:124:9:@40ns:(report note): result = -0000307.839290
证明正确的转换。
在不了解您的液晶显示器的情况下,尝试将BCD数字映射到它是不切实际的。
从固定值到BCD数字的这些转换表示硬件思维与机器指令方面的思考。如果dabbles不满足减少空间的需要,则使用时钟移位寄存器可以进一步减小尺寸,从而减少了使用小型状态机对add3或sub3单元进行折衷的要求。这可以起作用,因为眼睛和LCD显示器的工作方式都具有光学持久性。你根本无法看到不会持续数毫秒的事情。