So, if I have something like this:
signal A : unsigned(7 downto 0);
signal B : unsigned(16 downto 0);
signal C : std_logic;
and I wanted to do multiplication of signal A and B and store the 8th bit as signal C, what is the easiest way to do this approach? The only way I got working was the following:
C <= resize(A * B, 8)(7 downto 7);
I also tried something like:
C <= (A * B)(7);
C <= (A * B)(7 downto 7)
So, is there any way to do this without having to resize it first? The only reason I care is because I'm doing this with the two signals a few times and then adding them up, and then my final output ends up being 17 bits, which requires me to resize each set, and then resize the final output, like so:
signal A : unsigned(7 downto 0);
signal B : unsigned(16 downto 0);
signal C : std_logic_vector(16 downto 0);
C <= resize(((A + 1) * B / 2**8) + resize(((A + 1) * B), 8)(7 downto 7), 17);
and I just think it would look simpler if I could so something like:
C <= resize(((A + 1) * B / 2**8) + ((A + 1) * B)(7), 17);
thanks for any suggestions
Related
I'm trying to implement a testbench using a Golden Model and a DUT, in this case I'm testing a full adder 4 bits. I'm always getting undefined at the signal s_dut while s_gm works just fine. I'm stuck on this for a while and I really don't know what the problem would be.
Here is the top module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity topmodule is
end topmodule;
architecture Behavioral of topmodule is
component SomadorCompleto4bits_dut is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
Cout : out STD_LOGIC);
end component;
component SomadorComOperador_golden_model is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
S : out STD_LOGIC_VECTOR (4 downto 0));
end component;
component testbench is
port (s_dut, s_gm : in STD_LOGIC_VECTOR (4 downto 0);
a, b : out STD_LOGIC_VECTOR (3 downto 0));
end component;
signal a, b : STD_LOGIC_VECTOR (3 downto 0);
signal s_dut, s_gm : STD_LOGIC_VECTOR (4 downto 0);
begin
U0: SomadorCompleto4bits_dut port map(a, b, '0', s_dut (3 downto 0), s_dut(4));
U1: SomadorComOperador_golden_model port map(a, b, s_gm);
U2: testbench port map(s_dut, s_gm, a, b);
end Behavioral;
and here the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity testbench is
port (s_dut, s_gm : in STD_LOGIC_VECTOR (4 downto 0);
a, b : out STD_LOGIC_VECTOR (3 downto 0));
end testbench;
architecture Behavioral of testbench is
begin
process
variable a_teste_in, b_teste_in : STD_LOGIC_VECTOR (3 downto 0);
begin
report "Iniciando teste..." severity NOTE;
a_teste_in := "0000";
b_teste_in := "0000";
for i in 1 to 16 loop
for j in 1 to 16 loop
a <= a_teste_in;
b <= b_teste_in;
wait for 500 ns;
assert (s_dut = s_gm) report "Falhou: i = " & integer'image(i) & " j = " & integer'image(j) severity ERROR;
a_teste_in := a_teste_in + 1;
end loop;
b_teste_in := b_teste_in + 1;
end loop;
report "Teste finalizado!" severity NOTE;
wait;
end process;
end Behavioral;
I believe the error is somewhat related with the line:
U0: SomadorCompleto4bits_dut port map(a, b, '0', s_dut (3 downto 0), s_dut(4));
---edited:
Here's the DUT:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--DEVICE UNDER TEST--
entity SomadorCompleto is
Port ( S : out STD_LOGIC;
Cout : out STD_LOGIC;
A : in STD_LOGIC;
B : in STD_LOGIC;
Cin : in STD_LOGIC);
end SomadorCompleto;
architecture Behavioral of SomadorCompleto is
begin
S <= A xor B xor Cin;
Cout <= (A and B) or (A and Cin) or (B and Cin);
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SomadorCompleto4bits_dut is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
Cout : out STD_LOGIC);
end SomadorCompleto4bits_dut;
architecture Behavioral of SomadorCompleto4bits_dut is
signal fio_c1, fio_c2, fio_c3 : STD_LOGIC;
component SomadorCompletoSimples is
Port ( a : in STD_LOGIC;
b : in STD_LOGIC;
cin : in STD_LOGIC;
s : out STD_LOGIC;
cout : out STD_LOGIC);
end component;
begin
U0: SomadorCompletoSimples port map(A(0),B(0),'0',S(0),fio_c1);
U1: SomadorCompletoSimples port map(A(1),B(1),fio_c1,S(1),fio_c2);
U2: SomadorCompletoSimples port map(A(2),B(2),fio_c2,S(2),fio_c3);
U3: SomadorCompletoSimples port map(A(3),B(3),fio_c3,S(3),Cout);
end Behavioral;
--------------------------------------
Thanks in advance!
I just forgot to put "Simples" on SomadorCompleto, because both are the same
1-) I am curious about how ISE synthesizer implements adders in Virtex. I mean what is the smallest adder block size in slices? I was searching Xilinx documentations and I came up with this Virtex-4 FPGA User Guide
On page 204 it says, "The arithmetic logic includes an XOR gate that allows a 2-bit full adder to be implemented within a slice.". But there should be carry lookahead implementation. Because critical path increases logarithmic with the input width.
2-) The other question is, I want to implement long signed vector in VHDL. To achieve higher operating frequencies I want to implement two stage pipelined adder. For example:
signal a, b, c: signed(63 downto 0);
conventional method
c <= a + b;
What I want to implement
signal c_hi : signed(31 downto 0);
signal c_lo : signed(32 downto 0);
process(clk)
begin
if rising_edge (clk) then
--1st stage
c_lo <= ('0' & a(31 downto 0)) + ('0' & b(31 downto 0));
c_hi <= a(63 downto 32) + b(63 downto 32);
--2nd stage
c(63 downto 32) <= c_hi(31 downto 0) + (to_signed(0,31) & c_lo(32 downto 32));
c(31 downto 0) <= c_lo(31 downto 0);
end if;
end process;
But that includes 2x32bit adder + 1x33bit adder. So, what I asking is how can I give the carry out bit of lower addition while summing higher bits?
3-) Is there a way to obtain carry out/overflow bit without increasing width by one.
That's a pipelined adder:
signal a : signed(63 downto 0);
signal b : signed(63 downto 0);
signal c : signed(64 downto 0);
signal sum_stage1 : unsigned(32 downto 0);
process(clk)
begin
if rising_edge(clk) then
-- stage 1: add first 32 bits
sum_stage1 <= ('0' & a(31 downto 0)) + ('0' & b(31 downto 0));
-- stage 2: add next 32 bits (incl. C_in)
c(31 downto 0) <= sum_stage1(31 downto 0); -- optional: align intermediate sums
c(64 downto 32) <= (32 downto 1 => '0') & sum_stage1(sum_stage1'high) +
('0' & a(63 downto 32)) +
('0' & b(63 downto 32));
end if;
end process;
Step 1: add 32 bits (31..0)
Step 2: add 32 bits (63..32) (incl. C_in; C_in = C_out from step 1)
Minimum resources consumption:
2x 32 bit adder or 32 + 33 bit adder if its signed and C_out is relevant
33 bit register
My lab partner and I can't figure out why we're not getting any output in our waveform simulation of this component. We simulated the component by itself and obtained the expected behavior, but nested inside the entity, the output signal was not being initialized and only had uninitialized 'X' response.
This is the component declaration in the top level entity:
99 component CH is
100 Port ( clk : in std_logic;
101 X : in std_logic_vector(31 downto 0);
102 Y : in std_logic_vector(31 downto 0);
103 Z : in std_logic_vector(31 downto 0);
104 CH_OUT : out std_logic_vector(31 downto 0)
105 );
106 end component;
This is the process we use to assign input/output:
289 round_compute2 : process (clk, CH_OUT_sig, e_sig, f_sig, g_sig, T1_sig)
290 begin
291 CH_X_in <= e_sig;
292 CH_Y_in <= f_sig;
293 CH_Z_in <= g_sig;
294 T1_sig <= std_logic_vector(unsigned(CH_OUT_sig));
295 end process;
This is the code for the CH component
1 library IEEE;
2 use IEEE.STD_LOGIC_1164.ALL;
3 use IEEE.STD_LOGIC_ARITH.ALL;
4 use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6 -- CH is defined as (X AND Y) XOR (X' AND Z)
7 -- Verified working
8
9 entity CH is
10 Port ( clk : in std_logic;
11 X : in std_logic_vector(31 downto 0);
12 Y : in std_logic_vector(31 downto 0);
13 Z : in std_logic_vector(31 downto 0);
14 CH_OUT : out std_logic_vector(31 downto 0)
15 );
16 end CH;
17
18 architecture Behavioral of CH is
19
20 begin
21
22 Compute : process (clk, X, Y, Z)
23 begin
24
25 CH_OUT <= (X and Y) xor ((not X) and Z);
26
27 end process;
28
29 end Behavioral;
These questions are similar, but do not address the issue in this post because-
VHDL component and outputs based on generic
- Does not involve processes
Simple VHDL Problem with synchronous/asynchronous logic
- Does not involve components and signals that are assigned from the system to the component
Why doesn't my code produce output?
- Our code has the correct sensitivity list, I think
You should look through your tool's output for warnings. It sounds like you have an unbound component CH.
With:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- 3 use IEEE.STD_LOGIC_ARITH.ALL;
-- 4 use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- CH is defined as (X AND Y) XOR (X' AND Z)
-- Verified working
entity CH is
Port ( clk : in std_logic;
X : in std_logic_vector(31 downto 0);
Y : in std_logic_vector(31 downto 0);
Z : in std_logic_vector(31 downto 0);
CH_OUT : out std_logic_vector(31 downto 0)
);
end CH;
architecture Behavioral of CH is
begin
Compute : process (clk, X, Y, Z)
begin
CH_OUT <= (X and Y) xor ((not X) and Z);
end process;
end Behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ch_comp is
end entity;
architecture foo of ch_comp is
component CH is
Port ( clk : in std_logic;
X : in std_logic_vector(31 downto 0);
Y : in std_logic_vector(31 downto 0);
Z : in std_logic_vector(31 downto 0);
CH_OUT : out std_logic_vector(31 downto 0)
);
end component;
signal CH_X_in: std_logic_vector(31 downto 0);
signal CH_Y_in: std_logic_vector(31 downto 0);
signal CH_Z_in: std_logic_vector(31 downto 0);
signal CH_OUT_sig: std_logic_vector(31 downto 0);
signal e_sig: std_logic_vector(31 downto 0) := X"feedface";
signal f_sig: std_logic_vector(31 downto 0) := X"deadbeef";
signal g_sig: std_logic_vector(31 downto 0) := X"ffffffff";
signal T1_sig: std_logic_vector(31 downto 0);
signal clk: std_logic := '0';
begin
round_compute2 : process (clk, CH_OUT_sig, e_sig, f_sig, g_sig) --, T1_sig)
begin
CH_X_in <= e_sig;
CH_Y_in <= f_sig;
CH_Z_in <= g_sig;
T1_sig <= std_logic_vector(unsigned(CH_OUT_sig));
end process;
UUT:
CH
port map (
clk => clk,
X => CH_X_in,
Y => CH_Y_in,
Z => CH_Z_in,
CH_OUT => CH_OUT_sig
);
TEST:
process
begin
wait for 10 ns;
e_sig <= X"deadface";
f_sig <= X"facebeef";
g_sig <= X"EEEEFFFF";
wait for 10 ns;
wait;
end process;
end architecture;
I got:
Which is to say, it appears not to exhibit only uninitialized 'X's on CH_out_sig or T1_sig.
And it would appear you haven't revealed either enough or your VHDL design description or enough of the tool build and simulation process for a third party to see where you went wrong.
I'm a beginner at vhdl and I'm trying to make a 8 bit divider using shift and subtract method. The code for the divider is okay, I guess, but I'm having problems in simulating the inputs. When I use the Verilog test fixture, my inputs which should be (dividend=51 [00110011b], divisor=19 [00010011b]) always end up becoming (dividend=49 [00110001b], divisor=49 [00110001b])) in iSim, and then the outputs (Quotient and remainder = xxxxxxx (unknown)) instead of (quotient=2[00000010b] and remainder=13 [00001101b])...
As I mentioned before, I'm a beginner at vhdl and I've been at this for five hours, I've tried my best to search for a solution online, but failed.... so any help or alternative solution would be greatly appreciated.
I'm using Xilinx ISE 14.3 and iSim.
Here is the code for the 8 bit binary divider.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.STD_LOGIC_ARITH.all;
entity division is
generic(SIZE: INTEGER := 8);
port(reset: in STD_LOGIC; --reset
en: in STD_LOGIC; --enable
clk: in STD_LOGIC; --clock
num: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --dividend
den: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --divisor
res: out STD_LOGIC_VECTOR((SIZE - 1) downto 0); --result/quotient
rm: out STD_LOGIC_VECTOR((SIZE - 1) downto 0) --remainder
);
end division;
architecture behav of division is
signal bufreg: STD_LOGIC_VECTOR((2 * SIZE - 1) downto 0); --signal array to hold both accumulator and dividend registers as one i.e bufreg(18 bits)
signal dbuf: STD_LOGIC_VECTOR((SIZE - 1) downto 0); --signal array to hold the divisor
signal count: INTEGER range 0 to SIZE; --count to determine when to stop
alias ADreg is bufreg((2 * SIZE - 1) downto SIZE); --ADreg is is alias for top half of bufreg register(17th to 9th bit)
alias DVNDreg is bufreg((SIZE - 1) downto 0); --DVNDreg is is alias for bottom half of bufreg register(8th to 0th bit)
begin
--our process begins here
p_001: process(reset, en, clk)
begin
if reset = '1' then
res <= (others => '0');
rm <= (others => '0');
count <= 0;
elsif rising_edge(clk) then
if en = '1' then
case count is
when 0 =>
ADreg <= (others => '0');
DVNDreg <= num;
dbuf <= den;
res <= DVNDreg;
rm <= ADreg;
count <= count + 1;
when others =>
if bufreg((2 * SIZE - 2) downto (SIZE - 1)) >= dbuf then
ADreg <= '0' & (bufreg((2 * SIZE - 3) downto (SIZE - 1)) - dbuf((SIZE - 2) downto 0));
DVNDreg <= DVNDreg ((SIZE - 2) downto 0) & '1';
else
bufreg <= bufreg((2 * SIZE - 2) downto 0) & '0';
end if;
if count /= SIZE then
count <= count + 1;
else
count <= 0;
end if;
end case;
end if;
end if;
end process;
end behav;
And here is the code for the Verilog test fixture (.v file):
module BINdivisionTEST;
// Inputs
reg reset;
reg en;
reg clk;
reg [7:0] num ;
reg [7:0] den ;
// Outputs
wire [7:0] res;
wire [7:0] rm;
// Instantiate the Unit Under Test (UUT)
division uut (
.reset(reset),
.en(en),
.clk(clk),
.num(num),
.den(den),
.res(res),
.rm(rm)
);
initial begin
// Initialize Inputs
reset = 0;
en = 0;
clk = 0;
//num = 0;
//den = 0;
// Wait 100 ns for global reset to finish
#100;
en = 1;
#100;
clk=1;
num <= "00110011" ;
den <= "00010011" ;
// Add stimulus here
end
endmodule
My biggest problems seem to be initialization of the inputs and probably some mistaken assignments, misuse of the test fixture file and some bad coding.
I should also add that the divider code was compiled in vhdl, ISE 14.3.
I'm extremely sorry if this has been answered before and I don't mean to piss anyone off by uploading bad and amateur code. If this kind of problem has been addressed before could you please provide me with a link.
Again, any help is greatly appreciated.
The simulator may be treating those as strings instead of numbers. Try changing:
num <= "00110011" ;
den <= "00010011" ;
to:
num <= 8'b00110011;
den <= 8'b00010011;
I'm no expert on Verilog but it looks as if you might not be asserting Reset to your VHDL component before testing it.
That would lead "Count" in an uninitialised state so that when you use it, anything could happen and the "XXXX" outputs are a reflection of that.
The reset sequence should look like
En <= '0';
Clk <= '0';
Reset <= '1';
wait for 100 ns;
Reset <= '0';
wait for 100 ns;
-- start testing here
(in VHDL of course ... but it'll translate to Verilog easily)
I have two nested procedures, where the "main" procedure
makes use of "subproc" to accumulates a result in variables
t0 and t1, which is then returned at the end. This should all
be computed in one clock cycle, and the circuit more or less
just consists of simple logic gates (xor, or, and). When I try
to describe the circuit as below I get the following error:
Acutal (variable t0) for formal "a" is not a signal
That makes sense as the subprocure requires signals as input,
but I wanna pass it a variable during the main procedure. Is
there a simple way to circumvent this problem with casting for
example?
Thanks
procedure subproc
(
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal c : in std_logic_vector(31 downto 0);
signal d : in std_logic_vector(31 downto 0);
signal e : out std_logic_vector(31 downto 0);
signal f : out std_logic_vector(31 downto 0)
)
is
variable x : std_logic_vector(31 downto 0);
variable y : std_logic_vector(31 downto 0);
begin
x := (others => '0');
y := (others => '0');
for i in 0 to 31 loop
x(i) := (a(i) xor b(i)) and (c(i) xor d(i));
y(i) := (a(i) xor b(i)) or ((d(i) xor c(i)) xor b(i));
end loop;
e <= x(31 downto 0);
f <= y(31 downto 0);
end;
procedure main
(
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal r : out std_logic_vector(31 downto 0)
)
is
variable res : std_logic_vector(31 downto 0);
variable t0, t1 : std_logic_vector(31 downto 0);
constant c : std_logic_vector(31 downto 0) := X"fedcba90";
constant d : std_logic_vector(31 downto 0) := X"7654321f";
begin
t0 := (others => '0');
t1 := (others => '0');
for i in 0 to 31 loop
if ( (c(i) = '0') && (d(i) = '1') ) then
subproc( t0, t1,
a, b, t0, t1 );
end if;
end loop;
r <= t0;
end;
First off, your "if" clause is written in C-style. You want to say:
if (c(i) = '0') and (d(i) = '1') then
But the problem really is that you describe the procedure as taking SIGNALs as arguments. If you want the results to be assigned to variables, you need to declare a different procedure signature:
procedure subproc (
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal c : in std_logic_vector(31 downto 0);
signal d : in std_logic_vector(31 downto 0);
variable e : out std_logic_vector(31 downto 0);
variable f : out std_logic_vector(31 downto 0))
But then, you also need to change all assignments to e and f, so that they are variable assignments:
e := x(31 downto 0);
Why don't you just define the subproc parameters as variables instead of signals?