Adress Generator: Bit Swapping Problem (VHDL) - vhdl

what I want to do is the following:
In order to generate the appropriate OUTPUT I have to add a value(2^(stage-small_p+1) to my INPUT and then swapping the LSB (0) with a bit, which position depends on a the difference between the stage-signal and the constant small_p (stage-small_p).
Thanks for your help!
PROCESS(INPUT,stage)
BEGIN
IF stage > small_p THEN
OUTPUT_sig<=STD_LOGIC_VECTOR(TO_UNSIGNED(to_integer(UNSIGNED(INPUT)+2**
(stage-small_p+1)),m));
bit_0 <= OUTPUT_SIG(0);
bit_sp <=OUTPUT_SIG(stage-small_p);
FOR i in 0 to m-1 LOOP
IF (i=0) THEN
OUTPUT(i)<=bit_sp ;
ELSIF (i=(stage-small_p)) THEN
OUTPUT(i)<=bit_0;
ELSE
OUTPUT(i)<=OUTPUT_SIG(i);
END IF;
END LOOP;
ELSE
OUTPUT <= STD_LOGIC_VECTOR(TO_UNSIGNED(0,m));
END IF;
The error seems to be when assigning OUTPUT_SIG(i) to OUTPUT(i):
For example stage = 9 and p_small = 4:
My INPUT is 00110010,
OUTPUT_SIG has the value: 01110010,
whereas the OUTPUT has the value: 01010101.
stage-small_p = 5, so I would expect: 01010011 (Bit 5 and Bit 0 swapped).

Related

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.

Verilog Code:FIR Filter= RAM modeling for reading coefficients values from file .. not showing simulation results

In verilog for only this line of code its showing simulation output
1)
#( parameter width=1, length=16 )
(* ram_style = "block" *)
reg [(width)-1:0] mem[(1<<length)-1:0];
2)but for the below line it is not showing simulation output
#( parameter width=8, length=16 )
(* ram_style = "block" *)
reg [(2*width)-1:0] mem[(1<<length)-1:0];
Explain why 2nd set of code is not showing simulation results?
actually I want store 8 bits of min 65535 filter coefficients.. I want to read and write ..
please guide me in this...
A model of a RAM might look some thing like the code below, to write to it it is just a mater of sequencing the wr_addr, wr_data and wr_en.
module ram #(
parameter DATA_W = 8,
parameter DATA_D = 256
) (
input clk,
input rst_an,
input [0:$clog2(DATA_D)] rd_addr,
input [0:$clog2(DATA_D)] wr_addr,
input [0:DATA_W-1] wr_data,
input wr_en,
output [0:DATA_W-1] rd_data
);
reg [0:DATA_W-1] ram_data [0:DATA_D-1];
//READ
always #* begin
rd_data = ram_data[rd_addr];
end
//WRITE
always #(posedge clk, negedge rst_an) begin
if (~rst_an) begin
for(int i = 0; i<DATA_D ; i++) begin
ram_data[i] <= 'b0 ;
end
end
else begin
if (wr_en) begin
ram_data[wr_addr] <= wr_data ;
end
end
end
for(int i = 0; i<DATA_D ; i++) is system verilog syntax.
for plain verilog declare integer i then replace the for loop with :
for(i = 0; i<DATA_D ; i=1+1)
clog2 : is used to get the address width required for the given depth.
If you want a depth of 4, you need 2 bits to address it. Depth of 16, 4 bits to address, ie
log2( 4) => 2
log2(16) => 4
If you use non-powers of two you want to round up or ceiling
log2(5) => 2.32192809489
clog2(5) => 3
Therefore clog2 is very useful to get the required addressing width from the depth of the RAM.

Division on the last outputs

Counter count the number of input samples. Then the counter output (n) and I want to check if the number of samples is even,then n_of_samples = (n*n) else if odd make that ((n*n)-1)
will be something like that
signal dis : integer range 0 to 255 := 0;
signal n : integer range 0 to 255 :=0;
if n mod 2=1 then
n_of samples<= ((n*n)-1);
else
n_of_samples <= n*n;
end if;
norm_dis <= dis / n_of_samples ;
the two signals will have values as (1,6,9,8,.....100) and (0,2,8,9.......,200)
and i want to fetch the two last outputs from the two signal (100,200)
and divide 100/200.how can i write it in vhdl and how can overcome the divide by zero error.
just make sure that you do not divide by zero!
if n_of_samples/=0 then
norm_dis <= dis / n_of_samples ;
end if;

vhdl "for loop" with step size not equal to 1

I have a simple question . Is it possible to write a VHDL for loop with step size not equal to 1 e.g 16
The loop should go like
0--> 16 --> 32--> 48.... to some value
any immediate help is appreciated
A possible solution is to use a range that is 1/16th of the desired range and unroll the loop inside it to generate the desired range:
for i in 0 to 3 -- Actually 0 to 48
loop
x(16*i) <= ...
x((16*i)+1) <= ...
(...)
x((16*i)+15) <= ...
end loop;
Another solution would be to use a while instead. Assuming your count variable is an integer:
while (i < 48)
loop
--Do something
i := count + 16;
end loop;
Edit: I haven't tested the code above, you might be unable to change the variable count inside the loop, I'm not sure. Maybe the first solution is the best one.
It is not possible to have a for loop with a step different then 1. You are not even allowed to change it inside the for, like this:
--THIS WILL NOT WORK
for i in 0 to 48 loop
--Do Something
i := i + 15; -- This will NOT increment the loop index by 16
end loop;
And finally, for steps of 2 or 3 you might use nested for's.
But anyway, What are you trying to accomplish? VHDL is a low-level hardware description language, you should be able to achieve whatever you are trying to without fancy for loops.
VHDL has no step parameter in for loop, so the step is always 1 for to
range direction and -1 for downto range direction.
So if you need loop with start and step value, you can do:
...
constant FOR_START : natural := 1;
constant FOR_STEP : natural := 2;
variable idx_v : natural; -- Support index variable
...
for idx_pre in 0 to 3 loop
idx_v := FOR_START + FOR_STEP * idx_pre;
z_o(idx_v) <= a_i(idx_v);
end loop;
A while loop can also be used as alternative:
constant FOR_START : natural := 1;
constant FOR_STEP : natural := 2;
constant FOR_MAX : natural := 7;
variable idx_v : natural;
...
idx_v := FOR_START;
while idx_v <= FOR_MAX loop
z_o(idx_v) <= a_i(idx_v);
idx_v := idx_v + FOR_STEP;
end loop;
How about looping over the entire range, but then using an 'if' statement to only act on every 16th value?
for i in start_thing to end_thing loop
if i mod 16 = 0 then
do things(i)
end if;
end loop; -- i
Or alternately use Next:
for i in start_thing to end_thing loop
next when i mod 16 /= 0 ;
do_things(i)
end loop; -- i
My research says no, but you can declare a second variable that acts as a multiple of your variable inside of your loop.
Yes, it is possible to "for loop" with a step size not equal to 1.
for i in range 1 downto 0 loop
foo(i) <= bar(1-i);
end
loop;

how to count leading 0 in vector

back:while (sub1_mantissa(52)='0') loop
sub1_mantissa := sub1_mantissa(51 downto 0) & '0';
count := count + "000000000001";
end loop back;
hi .i want to count leading zeros in vector...like if my result is 0001 so it will show 3 zeros..so my counter will be increment by 3..and when i will get the first 1 in msb then my loop will stop...
i m using the above code..but it is not working...counter value it takes is too large like 1100111...i am not getting where is d problem...guys plz help me...n reply soon
I would use a for loop to count this, something like this:
variable zero_count : natural := 0;
for i in sub1_mantissa'range loop
if sub1_mantissa(i) = '0' then
zero_count := zero_count + 1;
else
exit;
end if;
end loop;
NOTE: this will only count the leading zeros if sub1_mantissa is declared using DOWNTO notation.

Resources