Combinational Logic Timing - hardware

I am currently trying to implement a data path, which calculates the following, in one clock cycle.
Takes input A and B and add them.
Shift the result of addition, one bit to right. (Dividing by 2)
Subtract the shifted result from another input C.
The behavioral architecture of the entity is simply shown below.
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
process (clock, data_in_a, data_in_b, data_in_c)
begin
if clock'event and clock = '1' then
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
When I simulate the above code, I do get the result I expect to get. However, I get the result, after 3 clock cycles, instead 1 as I wish. The simulation wave form is shown below.
I am not yet familiar with implementing designs with timing concerns. I was wondering, if there are ways to achieve above calculations, in one clock cycle. If there are, how can I implement them?

Do do this with signals simply register only the last element in the chain (data_out). This analyzes, I didn't write a test bench to verify simulation.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity signal_single_clock is
port (
signal clock: in std_logic;
signal data_in_a: in std_logic_vector(7 downto 0);
signal data_in_b: in std_logic_vector(7 downto 0);
signal data_in_c: in std_logic_vector(7 downto 0);
signal data_out: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of signal_single_clock is
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
begin
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
single_reg:
process (clock)
begin
if clock'event and clock = '1' then
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
end architecture;

When you assign a new value to a signal inside a process, this new value will be available only after the process finishes execution. Therefore, anytime you read the signal's value you will be using the original value from when the process started executing.
On the other hand, assignments to varibles take place immediately, and the new value can be used in the subsequent statements if you wish.
So, to solve you problem, simply implement sum_out, shift_out, and data_out using variables, instead of signals. Then simply copy the value of data_out to an output port of your entity.

Without using variables:
sum <= in_a + in_b;
process (clock)
begin
if rising_edge(clock) then
data_out <= in_c - ('0' & sum(7 downto 1));
end if;
end process;
All declarations except clock are unsigned(7 downto 0); why make it more complicated than that?
The original, pipelined to 3 cycles, will probably work at higher clock rates.
EDIT following comment:
I wanted to demonstrate that VHDL doesn't really have to be that verbose.
However there seem to be a lot of people "teaching" VHDL who are focussing on trivial elements and missing the big picture entirely, so I'll say a little bit about that.
VHDL is a strongly typed language, to prevent mistakes that creep in when types are mistaken for each other and (e.g.) you add two large numbers and get a negative result.
It does NOT follow from that, that you need type conversions all over the place.
Indeed, if you need a lot of type conversions, it's a sign that your design is probably wrong, and it's time to rethink that instead of ploughing ahead down the wrong path.
Code - in ANY language - should be as clean and simple as possible.
Otherwise it's hard to read, and there are probably bugs in it.
The big difference between a C-like language and VHDL is this:
In C, using the correct data types you can write sum = in_a + in_b;
and it will work. Using the wrong data types you can also write sum = in_a + in_b;
and it will compile just fine; what it actually does is another matter! The bugs are hidden : it is up to you to determine the correct types, and if you get it wrong there is very little you can do except keep on testing.
in VHDL, using the right types you can write sum <= in_a + in_b;
and using the wrong types, the compiler forces you to write something like sum <= std_logic_vector(unsigned(in_a) + unsigned(in_b)); which is damn ugly, but will (probably: see note 1) still work correctly.
So to answer the question : how do I decide to use unsigned or std_logic_vector?
I see that I need three inputs and an output. I could just make them std_logic_vectorbut I stop and ask: what do they represent?
Numbers.
Can they be negative? Not according to my reading of the specification (your question).
So, unsigned numbers... (Note 1)
Do I need non-arithmetic operations on them? Yes there's a shift.(Note 2)
So, numeric_std.unsigned which is related to std_logic_vector instead of natural which is just an integer.
Now you can't avoid type conversions altogether. Coding standards may impose restrictions such as "all top level ports must be std_logic_vector" and you must implement the external entity specification you are asked to; intermediate signals for type conversions are sometimes cleaner than the alternatives, e.g. in_a <= unsigned(data_in_a);
Or if you are getting instructions, characters and the numbers above from the same memory, for example, you might decide the memory contents must be std_logic_vector because it doesn't just contain numbers. But pick the correct place to convert type and you will find maybe 90% of the type conversions disappear. Take that as a design guideline.
(Note 1 : but what happens if C < (A+B)/2 ? Should data_out be signed? Even thinking along these lines has surfaced a likely bug that std_logic_vector left hidden...
The right answer depends on unknowns including the purpose of data_out : if it is really supposed to be unsigned, e.g. a memory address, you may want to flag an error instead of making it signed)
(Note 2 : there isn't a synthesis tool left alive that won't translate
signal a : natural; ... x <= a/2 into a shift right, so natural would also work, unless there were other reasons to choose unsigned. A lot of people seem to still be taught that integers aren't synthesisable, and that's just wrong.)

Related

How to make while loop, with no definite bounds, synthesizable?

I have this part of code which is not synthesizable because the number of times the loop will execute is not definite. I am a beginner with VHDL, how can I convert it to a synthesizable form?
Note: I tried doing it with for loop too, along with break statement, but it is still not synthesizable due to the break statement.
The code below is to calculate the value of ee such that the greatest common divisor of ee and Phi is 1.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity gcd11 is
Port ( ee : out integer;
Phi : in integer);
--gc : out integer);
end gcd11;
architecture Behavioral of gcd11 is
signal rem1,dd,dv,gc,temp: integer;
begin
process(temp,Phi,rem1,dd,dv,gc)
begin
gc<=2;
temp<=1;
while(gc/=1) loop
temp<=temp+1;
rem1<=1;
if (temp<Phi)then
dd<=Phi;
dv<=temp;
elsif(temp>=Phi) then
dd<=temp;
dv<=Phi;
end if;
while(rem1/=0) loop
rem1<= dd mod dv;
dd<=dv;
gc<=dv;
dv<=rem1;
end loop;
end loop;
ee<=temp;
end process;
end Behavioral;
First of all I would start with reading a book on VHDL as hardware design is very different from software design.
Next to that 3 main this that will not allow you to synthesis:
loops:
It's important to understand that a VHDL loop will not iterate like a software loop but is unfolded during synthesis and the resulting logic (all iterations) will run as parallel hardware blocks
Meaning that if you have a for loop that will run 8 times the circuit described will be instantiated 8 times. The follwing loop will create 8 parallel "AND" gates each taking 1 bit input from bus A and 1 bit from signal B.
for I in 0 to 7 loop
Z(I) <= A(I) and B;
end loop;
This means that at the moment you start the logic synthesis the amount of loops needs to be know as hardware can not be added/removed after synthesis.
mod:
Modulo function are in general not suited for synthisis. Only if your operands (inputs) are fixed (synthisis can calculate the output upfront) or you you have an statement that resembles the code below your synthesizer will allow it.(mod with a power of 2)
z <= y mod 2**x
signal declartion:
In VHDL that need to be synthezised you need to tell the tool how "large" (read: how many bits) a signal is. It is common practice to not use a blunt integer declaration but to use either a std_logic_vector type of an integer of a given range.
signal x : std_logic_vector(31 downto 0);
signal y : integer range 1 to 31;

Optimizing design with many identical units that could be shared

I have a design that generates a video signal on demand, without using RAM resources for a framebuffer.
I have a hierarchy that represents the screen layout, with a toplevel block generating the pixel clock and sync signals, and creating a signal that shows the coordinates of the next pixel. Below that are various blocks with the same interface:
type point is record
valid : std_logic;
x : unsigned(11 downto 0);
y : unsigned(11 downto 0);
end record;
type color is record
r : std_logic;
g : std_logic;
b : std_logic;
end record;
component source is
port(
pos : in point;
col : out color);
end component;
The general idea is that each of these blocks either generates a signal directly, or contains sub-blocks.
I'd like to stick with the pixel-on-demand schema, as it allows me to do
architecture syn of zoom2_block is
signal slave_pos : point;
begin
slave_pos.valid <= pos.valid;
slave_pos.x <= "0" & pos.x(10 downto 1);
slave_pos.y <= "0" & pos.y(10 downto 1);
slave : source port map(
pos => slave_pos,
col => col);
end architecture;
Now, the innermost pixel generators for several blocks are fairly similar (e.g. font pixel lookup), and because only one pixel will ever be passed outside, I wonder whether I can somehow share blocks, e.g. like the font in the hierarchy
output
source : split_screen
source : zoom
source : text
font
source: text
font
The text blocks themselves cannot be shared, because these contain the actual character codes given to the font blocks -- but the font block is twice exactly the same -- taking a coordinate and character code and returning the appropriate pixel value, with no state. Since the font data is large, not being able to share these is a problem.
Ideas I've had so far:
Have every block output '-' while pos.valid = '0', in the hope that the compiler will notice that this will be the case only for one block in the hierarchy, at all time. I'm not sure the compiler will get this.
Create a special component that arbitrates access to the font block, as a generic with array(1 to N) of point interface, selecting the first input with pos.valid = 1. This would still require me to build a hierarchy that is no longer a tree.
Can this be done?

XOR outputs one because of propagaton delay in (basic) counter (FPGA)

I have a basic counter example, counter is 6-bits wide.
reg[5:0] currcounterval_reg;
always #(posedge clk_g0)
currcounterval_reg <= currcounterval_reg+ 1'b1;
My constraints
Clock is running at 83 Mhz 912ns period) on Virtex 7 chip. The counter has no reset and the output is connected to board pins. When I run the circuit, I see switching in the signals as shown in the attached (hardware run) o/p. In the attached screenshot, if you look at the counter, after 7(seven), I should get '8'...but it first switches to '12' as bit-2 goes to zero later than the others. I have an xor gate downstream where I compare o/p of two counters. How to I avoid getting into this problem?
Whatever I do for constraining, it doesn't go away. Please help me with some strategies to remove the switching.
Please feel free to ask me if you have more questions.
You can find a my waveform here
http://i.imgur.com/btEMiFD.png?1
Thanks.
I am guessing that it is an improper constraint issue. But try wiring a synchronous counter explicitly to solve the issue.
reg[5:0] counter;
always #(posedge clk_g0)
begin
counter[0] <= ~counter[0] ;
counter[1] <= (counter[0] ) ? ~counter[1] : counter[1];
counter[2] <= (&counter[1:0] ) ? ~counter[2] : counter[2];
counter[3] <= (&counter[2:0] ) ? ~counter[3] : counter[3];
counter[4] <= (&counter[3:0] ) ? ~counter[4] : counter[4];
counter[5] <= (&counter[4:0] ) ? ~counter[5] : counter[5];
end
You need to make the XOR output synchronous. The XOR output should go to the D input of a FF that is clocked on the same rising edge that increments the counters. Bring the Q output of the FF to an FPGA pin rather than the XOR output.
You shouldn't try to match the combinational logic delays and routing delays of the two counters. The delay paths from two counters to your XOR gates will almost certainly be different so a fast XOR (like on a Virtex 7) will generate glitches. In a good synchronous design that doesn't matter, because you only care that the combinational logic outputs are valid before the next clock edge.

"unsigned" type conversion demands input in sequential process sensitivity list

I have an address counter in a VHDL sequential process. Its idle value is set in a configuration register to a certain max value; afterwards, anytime it enters a certain state it should increment by one.
To get the maximum value, I declare a subset of an input std_logic_vector as an alias.
I declared address_int as an unsigned variable. I then defined a sequential process with a clk and a reset in the sensitivity list. When the reset is asserted, the address counter is set to the alias value. After reset is released, the counter is rolled over/incremented on rising edges when in a certain state.
The synthesis tool gives me this message:
*WARNING:Xst:819 line 134: The following signals are missing in the process sensitivity list: DL_CADU_SIZE*
And all the address lines have become asynchronous signals! What is going on here? Is there some strange behavior with unsigned that doesn't occur with integers? I usually use integers here, but the conversion seemed more straightforward from unsigned for purposes of code maintenance. I have tried ditching the alias and doing the straight conversion, but it didn't help.
library IEEE;
use ieee.std_logic_1164.a
use ieee.numeric_std.all;
-- entity declaration, ports, architecture, etc.
signal address_int : unsigned(8 downto 0);
alias aMaxWords : std_logic_vector(8 downto 0) is DL_CADU_SIZE(10 downto 2);
begin
WADDR <= std_logic_vector(address_int);
OUT_PROC: process (CLK_CORE, RST_N_CORE)
begin
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords);
elsif rising_edge(CLK_CORE) then
if next_state = WRITE_WORD then
if address_int = unsigned(aMaxWords) then
address_int <= (others => '0');
else
address_int <= address_int + 1;
end if;
end if; -- WRITE_WORD
end if; -- rising_edge
end process OUT_PROC;
end RTL;
This:
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords)
describes an async reset - therefore aMaxWords will be treated as asynchronous by the synthesiser irrespective of whether it is or not.
What the synthesiser interprets your code as is "while rst_n_core is low, copy the value of aMaxWords to address_int" so if aMaxWords changes during reset, the value must be copied across. The lack of that signal in your sensitivity list means that the synthesiser is making a circuit which behaves differently to what the language says it should, hence the warning.
It really shouldn't do this: without the signal in the sensitivity list, it ought to capture the signal on the falling edge of the reset line. But as that's not how most chips work, the synthesiser designers (in their infinite wisdom) decided many years ago to assume the designer intended to have that signal in the sensitivity list, and issue a warning, rather than saying "this can't work, fix it". So then you get code which works differently in simulation and synthesis. End rant.
Your reset code:
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords);
is wrong. The definition of reset is set your circuit to known-state. But your code assign it to a signal. You should assign it as all 0 or all 1 for reset, or your aMaxWords must be constant (note that your synthesizer may be not enough intellegent for known it, then should assign it as constant) :
if RST_N_CORE = '0' then
address_int <= (others => '0');
or
if RST_N_CORE = '0' then
address_int <= (others => '1');

signal vs variable

VHDL provides two major object types to hold data, namel signal and variable, but I can't find anywhere that is clear on when to use one data-type over the other. Can anyone shed some light on their strengths/limitations/scope/synthesis/situations in which using one would be better than the other?
Signals can be used to communicate values between processes. Variables cannot. There are shared variables which can in older compilers, but you really are asking for problems (with race conditions) if you do that - unless you use protected types which are a bit like classes. Then they are same to use for communication, but not (as far as I know) synthesisable.
This fundamental restriction on communication comes from the way updates on signals and variables work.
The big distinction comes because variables update immediately they are assigned to (with the := operator). Signals have an update scheduled when assigned to (with the <= operator) but the value that anyone sees when they read the signal will not change until some time passes.
(Aside: That amount of time could be as small as a delta cycle, which is the smallest amount of time in a VHDL simuator - no "real" time passes. Something like wait for 0 ps; causes the simulator to wait for the next delta cycle before continuing.)
If you need the same logic to feed into multiple flipflops a variable is a good way of factoring that logic into a single point, rather than copying/pasting code.
In terms of logic, within a clocked process, signals always infer a flipflop. Variables can be used for both combinatorial logic and inferring a flipflop. Sometimes both for the same variable. Some think this confusing, personally, I think it's fine:
process (clk)
variable something : std_logic;
if rising_edge(clk) then
if reset = '1' then
something := '0';
else
output_b <= something or input c; -- using the previous clock's value of 'something' infers a register
something := input_a and input_b; -- comb. logic for a new value
output_a <= something or input_c; -- which is used immediately, not registered here
end if;
end if;
end process;
One thing to watch using variables is that because if they are read after they are written, no register output is used, you can get long chains of logic which can lead to missing your fmax target
One thing to watch using signals (in clocked processes) is that they always infer a register, and hence leads to latency.
As others have said signals get updated with their new value at the end of the time slice, but variables are updated immediately.
// inside some process
// varA = sigA = 0. sigB = 2
varA := sigB + 1; // varA is now 3
sigC <= varA + 1; // sigC will be 4
sigA <= sigB + 1; // sigA will be 3
sigD <= sigA + 1; // sigD will be 1 (original sigA + 1)
For hardware design, I use variables very infrequently. It's normally when I'm hacking in some feature that really needs the code to be re-factored, but I'm on a deadline. I avoid them because I find the mental model of working with signals and variables too different to live nicely in one piece of code. That's not to say it can't be done, but I think most RTL engineers avoid mixing... and you can't avoid signals.
Other points:
Signals have entity scoping. Variables are local to the process.
Both synthesize