How to tell when outputs from VHDL settle at their final values? - vhdl

First off, I would like to state this is on a practice exam I am taking. I know the answers to be: cout = 4ns, and S = 7ns. Just looking for a little explanation. Thanks in advance.
For the VHDL implementation of a full adder shown below, when do the outputs cout and S settle at their final values (consider the worst case timing path with the worst case inputs)?
architecture concurrent_behavior of full_adder is
signal t1, t2, t3, t4, t5: std_logic;
begin
t1 <= not A after 1 ns;
t2 <= not cin after 1 ns;
t4 <= not ((A or cin) and B) after 2 ns;
t3 <= not ((t1 or t2) and (A or cin)) after 2 ns;
t5 <= t3 nand B after 2 ns;
S <= not((B or t3) and t5) after 2 ns;
cout <= not(t1 or t2) and t4) after 2 ns;
end concurrent_behavior;

You basically just trace through the dependencies, and add up the dependencies for each route through the logic. Normally it's easiest to trace backwards from an output to the inputs it needs. For example:
cout <= not(t1 or t2) and t4) after 2 ns;
So, the last stage for cout has a 2 ns delay. Its inputs are t1, t2 and t4, so its 2 ns delay can't start until t1, t2 and t4 are all ready (i.e., the single longest of those delays determines the start time for the last stage).
In this case, t1 and t2 are delayed by 1 ns apiece, and t4 is delayed by 2 ns. Therefore, the last stage starts 2 ns after the initial input. That gives 2+2 = 4 ns from initial input to final output.
Looking at it from an algorithmic viewpoint, we could state it that the delay for any signal is the delay of the final "stage" for that signal plus the maximum of the delays for any of its inputs.
For S:
total = 2 + max_delay(B, t3, t5)
total = 2 + delay(t5);
total = 2 + 2 + max_delay(t3, B)
total = 2 + 2 + delay(t3)
total = 2 + 2 + 2 + max_delay(t1, t2, A, cin)
total = 2 + 2 + 2 + delay(t1) (or delay(t2) -- they're the same).
total = 2 + 2 + 2 + 1

Related

How is this calculating CRC-A using polynomial - x^16 + x^12 + x^5 + 1

I came across this piece of code. But I am not sure how is CRC calculated here. I know the theoretical way of calculating CRC but I guess here it is using some kind of different logic, maybe. Please correct me.
r_o[14:13] <= r_o[13:12];
r_o[12] <= r_o[11]^r_o[15]^x16;
r_o[11] <= r_o[10];
r_o[10:6] <= r_o[9:5];
r_o[5] <= r_o[4]^r_o[15]^x16;
r_o[4] <= r_o[3];
r_o[3:1] <= r_o[2:0];
r_o[0] <= r_o[15]^x16;
Well, if you know about the theoretical way to do we can start with
Assuming u is the input bit, and that every iteration you calculate r = r * x + u*x^16, remember that in the given ring x^16 = x^12 + x^5 + 1, a direct implementation of this would be
parameter X16_MASK = 16'h1021; // (1 << 12) ^ (1 << 5) ^ 1
function [15:0] step(input [15:0] prev_state, input u);
logic [15:0] state;
begin
state = {prev_state[14:0], 1'b0};
if(state[15]) state = state ^ X16_MASK;
if(u) state = state ^ X16_MASK;
step = state;
end
endfunction
This could simply be written as {r_o[14:0], 1'b0} ^ (X16_MASK * (r_o[15] ^ u)) and let the synthesis to optimize whatever is necessary, it should be able to simplify the multiplication by a 1-bit signal. Now check the positions where the mask has an effect you will get to assignments above.
I would simplify
r_o[11] <= r_o[10];
r_o[10:6] <= r_o[9:5];
to r_o[11:6] = r_o[10:5]
and
r_o[4] <= r_o[3];
r_o[3:1] <= r_o[2:0];
to r_o[4:1] = r_o[3:0]
In the code you presented I am missing the assignment to r_o[15].
So you could say
r_o[15:13] <= r_o[14:12];
r_o[12] <= r_o[11]^r_o[15]^x16;
r_o[11:6] <= r_o[10:5];
r_o[5] <= r_o[4]^r_o[15]^x16;
r_o[4:1] <= r_o[3:0];
r_o[0] <= r_o[15]^x16;
And if you like the one linear bit packing
r_o <= {r_o[14:12], r_o[11]^r_o[15]^x16, r_o[10:5], r_o[4]^r_o[15]^x16,r_o[3:0], r_o[15]^x16}

VHDL: assign new value to the specific element of 2D Array

I want to copy the Average Variable value to the specific location of 2d Array. For this code it is array_new_signal11(3,2).
Can anyone guide me how can I do this? This code gives me error while simulation.
architecture Behavioral of Correction is
type array_new is array (0 to 4, 0 to 4) of integer;
signal array_new_signal: array_new;
begin
array_new_signal11 <= ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
Process(kelvin)
variable Sum1: integer:= 0;
Variable Sum2: integer:= 0;
Variable Total_Sum: integer:= 0;
Variable Average: integer:= 0;
begin
for Row in 0 to 4 loop
for Column in 0 to 4 loop
if(Row = 1 and Column = 1) then
for Column in 1 to 3 loop
sum1 := array_new_signal11(Row, Column) + Sum1;
end loop;
end if;
if(Row = 2 and Column = 1) then
for Column in 1 to 3 loop
sum2 := array_new_signal11(Row, Column) + Sum2;
end loop;
end if;
end loop;
end loop;
Total_Sum := Sum1 + Sum2;
Average := Total_Sum / 8;
**array_new_signal11(3,2) <= Average;**
end Process;
end Behavioral;
Constructing a Minimal, Complete and Verifiable example from the question:
entity correction is
end correction;
architecture behavioral of correction is
type array_new is array (0 to 4, 0 to 4) of integer;
signal array_new_signal11: array_new := ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
signal kelvin: boolean;
begin
-- array_new_signal11 <= ((1,2,3,4,5),
-- (4,5,6,7,8),
-- (7,8,9,0,1),
-- (1,3,6,5,9),
-- (2,3,5,4,5));
process (kelvin)
variable sum1: integer:= 0;
variable sum2: integer:= 0;
variable total_sum: integer:= 0;
variable average: integer:= 0;
begin
for row in 0 to 4 loop
for column in 0 to 4 loop
if row = 1 and column = 1 then
for column in 1 to 3 loop
sum1 := array_new_signal11(row, column) + sum1;
end loop;
end if;
if row = 2 and column = 1 then
for column in 1 to 3 loop
sum2 := array_new_signal11(row, column) + sum2;
end loop;
end if;
end loop;
end loop;
total_sum := sum1 + sum2;
average := total_sum / 8;
report "sum1 = " & integer'image(sum1) & ", " &
"sum2 = " & integer'image(sum2) & ", " &
"average = " & integer'image(average);
array_new_signal11(3,2) <= average;
end process;
MONITOR_PROCESS:
process
begin
wait on array_new_signal11;
for row in 0 to 4 loop
report "row" & integer'image(row) & " = " &
integer'image(array_new_signal11(row,0)) & ", " &
integer'image(array_new_signal11(row,1)) & ", " &
integer'image(array_new_signal11(row,2)) & ", " &
integer'image(array_new_signal11(row,3)) & ", " &
integer'image(array_new_signal11(row,4));
end loop;
end process;
end behavioral;
We see the report statements tell us the average and report the new array values.
We see the Row 3 Column 2 was initialized to 6 and is now 4:
ghdl -a correction.vhdl
ghdl -e correction
ghdl -r correction
correction.vhdl:42:7:#0ms:(report note): sum1 = 18, sum2 = 17, average = 4
correction.vhdl:52:13:#0ms:(report note): row0 = 1, 2, 3, 4, 5
correction.vhdl:52:13:#0ms:(report note): row1 = 4, 5, 6, 7, 8
correction.vhdl:52:13:#0ms:(report note): row2 = 7, 8, 9, 0, 1
correction.vhdl:52:13:#0ms:(report note): row3 = 1, 3, 4, 5, 9
correction.vhdl:52:13:#0ms:(report note): row4 = 2, 3, 5, 4, 5
as specified by the value of average.
As Renaud Pacalet notes you have two different processes driving array_new_signal11, which is not legal in VHDL, as it's element type integer is not a resolved data type.
The solution is to initialize the array in this case where it's declared.
Otherwise every assignment to an element of array signal must be in the same process. The concurrent signal assignment you had will be elaborated to an equivalent process statement and generate an error when elaborated as it was originally shown:
ghdl -r correction
for signal: .correction(behavioral).array_new_signal11(3,2)
./correction:error: several sources for unresolved signal
./correction:error: error during elaboration
(For the ghdl simulator part of elaboration (which consists of linking and loading) is done when invoking simulation (the -r command, the loading part, where the design network is created)).
Renaud Pacalet suggests assigning the array value inside the process, but without an intervening wait statement the values are not available for subsequent use in the same simulation cycle. The new signal values are not available in the same simulation cycle they are assigned.
Each signal assignment schedules a waveform update and only one entry for a particular simulation time is available. In this case it would guarantee array(3, 2) would be the average of eight values of integer'left (which would be incorrect, you should get errors causing simulation to end during the accumulation of sum1 in the unlabelled 3rd loop statement first loop iteration).
And that tells us you need the array initialized before being read.
The only reason the above example succeeds is that there are no array elements when added together won't violate the value range of type integer with the values you specified.
You can get around this sort of thing by using binary array equivalents of integers and paying attention to the needed accuracy.
There are several morals to this story. First, VHDL isn't a programming language, second it's strongly typed and third signals assignment values are never visible in the simulation cycle they are made in.
Note that kelvin has been added as boolean signal to trigger execution of the process once without changing it.
You are trying to drive the array_new_signal11 signal from two different processes. Yes, your first concurrent signal assignment:
array_new_signal11 <= ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
is a shorthand for a process. It models a hardware driver that continuously imposes these values to your array signal (which is just a bunch of wires, at the end).
Your second process also tries to impose a value to one cell of your array (cell array_new_signal11(3,2)). In electrical engineering, this situation is called a short-circuit: what would you expect when the two drivers disagree? This is also the reason why your simulator refuses this: it does not know what to do with this signal.
Solution: drive this signal from one single process:
process(kelvin)
...
begin
array_new_signal11 <= (
(1,2,3,4,5),
(4,5,6,7,8),
...
for Row in 0 to 4 loop
...
end process;
Notes:
Average being a variable you should have another error on:
Average <= Total_Sum / 8;
which should be:
Average := Total_Sum / 8;
You are using the same loop index (Column) in two nested loops. Not sure what you are trying to do but this is not very safe.
Even with my suggestion to fix your error you will hit another problem: the array_new_signal11 is both an input (you read it) and an output (you assign it) of your process. It should thus also be listed in the sensitivity list. In electrical engineering this is called a combinatorial loop and is usually highly undesirable, except if you want to create an oscillator or a kind of random generator.
Your process is sensitive to signal Kelvin but does not use it. Strange situation. Do you have a clear idea of what hardware you are trying to model?
You probably believe that your process variables are re-initialized to 0 each time the process resumes (that is, each time Kelvin changes). This is not the case: they retain the last value they were assigned. Probably not what you want. You should initialize them at the beginning of your process body.

Good game sequences

Given two games A and B and the constraints is that A can be played on odd minutes and B can be played on even minutes only. Like Play A on 1st second then on 3rd second, likewise for B.
Now good sequence is defined as:
(1) If games are played according to their rule i.e., A will be played on odd minutes and B is played on even minutes.
(2) A and B are not played alternatively in the whole sequence.
For e.g.,
AXAXA : X denotes no game played on that minute, good sequence.
ABXXXB : Good sequence because both are played according to rule as well as first A is played then B and then again B.
XXXX: Good sequence.
ABXXAB: Not good sequence.
Given the total number of minutes till which the game is played, calculate total number of good sequences. As the number can be quite large provide the answer modulo 1000000007.
I am doing it by creating every string and checking its correctness. It is O(2^n). I have got answers for fewer n as 2, 3, 5, 9, 18, 38, 82, 177, 379, 803,.... n starting from 1.
How do I do it through DP?
does this code work for you, I have added a demo here. please check it out
#include <iostream>
#include <cstdio>
using namespace std;
#define MOD 1000000007
int dp[100005][3][4]= {0};
int main() {
int n;
cin >> n;
dp[1][0][1] = 1;
dp[1][2][0] = 1;
for(int i=2; i<=n; i++){
if(i&1){
dp[i][2][0] = dp[i-1][2][0];
dp[i][0][1] = dp[i-1][2][0];
dp[i][2][1] = (dp[i-1][0][1] + dp[i-1][2][1]);
dp[i][1][3] = dp[i-1][1][3];
dp[i][2][2] = (dp[i-1][1][2] + dp[i-1][2][2])%MOD;
dp[i][0][3] = ((dp[i-1][1][2] + dp[i-1][2][2])%MOD + (dp[i-1][1][3] + dp[i-1][0][3])%MOD)%MOD;
}
else {
dp[i][2][0] = dp[i-1][2][0];
dp[i][1][2] = dp[i-1][2][0];
dp[i][2][1] = (dp[i-1][0][1] + dp[i-1][2][1]);
dp[i][1][3] = ((dp[i-1][0][1] + dp[i-1][2][1])%MOD + (dp[i-1][1][3] + dp[i-1][0][3])%MOD)%MOD;
dp[i][2][2] = (dp[i-1][1][2] + dp[i-1][2][2])%MOD;
dp[i][0][3] = dp[i-1][0][3];
}
// for(int j=0;j<=2;j++){
// for(int k=0;k<=3;k++){
// if(dp[i][j][k])
// printf("i=%d j=%d k=%d dp=%d\n",i,j,k,dp[i][j][k]);
// }
// }
}
int p = 1;
for(int i=1; i<=n; i++){
p = (p*2) % MOD;
}
p = (p - dp[n][0][3] - dp[n][1][3] )%MOD;
p = (p+MOD)%MOD;
cout << p << endl;
return 0;
}
Let say we have states
x, xx, - when adding b it leads to state 2, when a it leads to 3, when x no changes in state
xb, xbxbx , - when x no changes in state, b no changes in state, when a it leads to state 5
a, axa, - when x no changes in state, when a no changes in state, when b it leads to state 4
ab, xxab, abx - x no changes in state, for b it changes to state 2, should neglect adding a
xba, xbax - x no changes in state, for a it changes to 3, for b we should neglect adding b
So you solve by going from small range(length 1) to given range and keep counting the states while adding x or a,b.
Let see for length
adding a and x to empty string
State1 - 0 + 1 (x)
State2 - 0
State3 - 0 + 1 (a)
State4 - 0
State5 - 0
Total 2
adding b and x
State1 - 1
State2 - 0 + 1 (from state1 by adding b)
State3 - 1
State4 - 0 + 1 (from state3 by adding b)
State5 - 0
Total 4
adding a and x
State1 - 1
State2 - 1
State3 - 1 + 1 (from state1 by adding a to it) + 1 (from state3 itself axa..)
State4 - 1
State5 - 0 + 1 (from stat2 by adding a to it)
Total 7
Adding b and x
State1 - 1
State2 - 1 + 1 (from state 1) + 1 (from state2 itself) + 1 (from state4)
State3 - 3
State4 - 1 + 3 (from state3)
State5 - 1
Total 13
Adding a and x
State1 - 1
State2 - 4
State3 - 3 + 1(from state1) + 3(from state3 itself) + 1(from state5)
State4 - 4
State5 - 1 + 4(from state2)
Total 22
Complexity will be O (n)
code will be added soon

Easy way of dividing an integer by 3

I'm working on a project that is to make a simple music player on an FPGA. It takes a music file of a specified format from the PC and plays it out loud in loops.
We need to implement the standard note lengths, i.e. Quaver for half a beat, Minim for 2 beats, etc. Currently we have a table of the lengths of a beat in numbers of clock cycles at various BPM values. We need to multiply them by these note lengths to yield the correct clock cycles. The only problem is Tuplet, which is a third of a full beat.
Without implementing a full-blown divider circuit, are there any maths tricks one can do to divide, approximately, an integer by 3?
Dividing by 3 is the same as multiplying by 1/3 (=0.33333). 0.3333 can be expressed as an addition of two or more (depending on the needed accuracy) (left) shifted input values.
input*2^-a + input*2^-b + input*2^-c ...
Just find suitable values for a, b, c, ...
This works for (almost) all divisions.
The following is a VHDL translation of some code from Hank Warren’s Hacker’s Delight. It divides an unsigned integer by the constant value 3 using only shifts, additions, and multiplications by the constant values 3 and 5 (which can also be reduced to shifts and additions).
-- q is quotient, d is dividend
q := (d srl 2) + (d srl 4); -- q = d*0.0101 (approx)
q := q + (q srl 4); -- q = d*0.01010101
q := q + (q srl 8);
q := q + (q srl 16);
r := resize(d - q * 3, 32); -- 0 <= r <= 15.
q := resize(q + (5 * (r + 1) srl 4), 32);
If the exact result of integer division by 3 (x / 3) is required for an unsigned value of length LEN, then truncating integer operations can be used with a little trick. The constant for 1/3 should be of length LEN + 1 and 1 should be added. Truncation can then be used afterwards. Pseudo code as:
C = 2 ** (LEN + 1) / 3 + 1
y = (x * C) / 2 ** (LEN + 1)
A Python function that shows and tests the algorithm for all values is:
def div_by_3_test(LEN):
DIVISOR = 3
C = 2 ** (LEN + 1) // DIVISOR + 1
for x in range(2 ** LEN):
if (x * C) // 2 ** (LEN + 1) != x // DIVISOR: exit('Failed')
A VHDL module that implements this as:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity div_by_3 is
generic(
LEN : natural := 12);
port(
x_i : in std_logic_vector(LEN - 1 downto 0);
y_o : out std_logic_vector(LEN - 1 downto 0));
end entity;
architecture syn of div_by_3 is
-- Constant to multiply, basically 1/3, but adding 1 to avoid error
constant C : std_logic_vector(LEN - 1 + 1 downto 0) :=
std_logic_vector(to_unsigned(2 ** (LEN + 1) / 3 + 1, LEN + 1));
-- Intermediate, with length as 2 * LEN + 1
signal t : std_logic_vector(2 * LEN + 1 - 1 downto 0);
begin
-- Intermediate with full length result
t <= std_logic_vector(unsigned(C) * unsigned(x_i));
-- Result after truncation for division by LEN + 1
y_o <= t(2 * LEN + 1 - 1 downto LEN + 1);
end architecture;
The advantage is that a division by 3 of an LEN bit number can be made in one cycle using only a single 2 * LEN + 1 bit multiplication.
Registers may be added to allow pipeline for high speed design.
Note that a similar scheme is possible for any divisor, but length of C must then be LEN + ceil(log2(DIVISOR)), with C scaled accordingly. Please see https://math.stackexchange.com/q/2444306/275980 regarding the mathematical foundation.
As mentioned by dieli, multiply by 0.333333.
However, instead of using several negative powers of 2 (i.e. a, b, c,..) just multiply 1/3 by some large power of 2, e.g. 2^24 * (1/3) = 5592405. After multiplying the clock cycles and 5592405, just divide by 2^24.
B = (clock cycles)*5592405
result = B/2^24
The size of B would depend the maximum size of clock cycles and can be computed by
maximum register size for B = integer of ( (log10((max size of clock cycles)*5592405)/log10(2)) + 0.5)

VHDL Design - Clock

Can someone please help me with the following:
Design a digital circuit, using VHDL, to keep track of time in the form of HH:MM:SS. The circuit should produce 6 separate four bit digital outputs (2 four bit outputs for the HH, 2 for the MM, 2 for the SS). The HH can just be a 2 digit number in the range 00 to 99 i.e. it’s not a clock, it just a counter for hours even though 99 hour tapes don’t exist. The time is to be displayed on the 6 right most 7 segment displays of the DE2. You have already designed a 7 segment decoder and driver as part of a previous lab, so that can be used to convert each 4 bit output into a 7 bit signal for each the 7-segment display. Don’t forget to set up the pin planer for these display (and all other signals)
The circuit should have the following single bit inputs: A Clock, an increment, a decrement and a reset. The increment/decrement inputs should cause the tape counter to add or subtract 1 second from the tape time on the next rising edge of the clock signal. If neither the increment or decrement inputs are present, the tape counter does not change. The reset is synchronous to the clock (to avoid glitches accidentally resetting it). The increment and decrement signals are all active high signals (i.e. a logic 1), the reset is active low (logic 0).
You tape counter should handle full hour, minute and second roll over, e.g. if the counter is showing 9:59:59, then the next increment should make it display 10:00:00 and vice versa when decrement is present.
Rather than solving your homework, I'd like to give you an idea. Most designers will tend to implement this clock using digit-by-digit rollover (some digits will rollover from 9-0, others from 5-0). I'd like to propose someting different.
The overall idea is: keep your time value in seconds as an integer. This will greatly facilitate the tasks of incrementing and decrementing. Then, you simply implement a conversion function that returns the number of hours, minutes, and seconds, given an integer number of seconds.
Your clock entity would look like this:
library ieee;
use ieee.std_logic_1164.all;
use work.clock_pkg.all;
entity clock is
port (
clock: in std_logic;
n_reset: in std_logic;
increment: in std_logic;
decrement: in std_logic;
hours: out natural range 0 to 99;
minutes: out natural range 0 to 59;
seconds: out natural range 0 to 59
);
end;
architecture rtl of clock is
signal time_in_seconds: natural range 0 to 359999;
begin
process (clock, n_reset) begin
if rising_edge(clock) then
if n_reset = '0' then
time_in_seconds <= 0;
elsif increment then
time_in_seconds <= time_in_seconds + 1;
elsif decrement then
time_in_seconds <= time_in_seconds - 1;
end if;
end if;
end process;
process (time_in_seconds) begin
(hours, minutes, seconds) <= seconds_to_time_type(time_in_seconds);
end process;
end;
As you can imagine, the workhorse of this solution is the seconds_to_time_type() function. You could implement it like this:
package clock_pkg is
type time_type is record
hours: natural range 0 to 99;
minutes, seconds: natural range 0 to 59;
end record;
function seconds_to_time_type(seconds: in natural) return time_type;
end;
package body clock_pkg is
function seconds_to_time_type(seconds: in natural) return time_type is
variable hh: natural range 0 to 99;
variable mm: natural range 0 to 119;
variable ss: natural range 0 to 119;
begin
hh := seconds / 3600;
mm := (seconds mod 3600) / 60;
ss := (seconds mod 3600) mod 60;
return (hh, mm, ss);
end;
end;
Now you have an entity that outputs separate integer values for hours, minutes, and seconds. Converting those values from integers to BCD, and showing those values on the displays is left as an exercise to the reader.
The typical way of implementing a counting clock is using binary coded decimal (BCD), where each digit consists of a separate n-bit counter, with a range as needed.
For example, in order to count seconds (from 0-59), you could use something like the following code:
process(clk, reset) begin
if(reset='1') then
second_tens <= (others=>'0');
second_ones <= (others=>'0');
elsif(rising_edge(clk)) then
if(count_en='1') then
if(second_ones = 9) then
second_ones <= (others=>'0');
if(second_tens = 5) then
second_tens <= (others=>'0');
-- Count up minutes.
else
second_tens <= second_tens + 1;
end if;
else
second_ones <= second_ones + 1;
end if;
end if;
end if;
end process;
Minutes and hours can be counted analogously.
You have skipped a step. You are trying to think about code with just a worded problem statement. First step is to design the hardware by drawing a block diagram. Break the problem down into pieces.
Initial partitioning might be Seconds, Minutes, and Hours. If you are counting in BCD, it you may wish to partition it further digit by digit. Work out what your hardware is supposed to do. Draw a picture. Write code that describes what is in the picture.
At the end of the day, your RTL block diagram is your HDL flow chart.

Resources