Verilog code motion estimator - debugging

I having trouble with finding the smallest values of X and xfind and Y and yfind in `Costcalculator xfind (X,xcost);
Costcalculator yfind (Y,ycost);
in code below.
can someone comment please. For some reason I couldn't import the whole code. It just recognizes these lines as codes. Sorry if it is not clear.
always #(posedge clk) // sequential circuit
begin
Costcalculator xfind (X,xcost);
Costcalculator yfind (Y,ycost);
if(reset)
begin
i=0;
R<=0;
xcost<=0;
ycost<=0;
mode0<=0;
mode1<=0;
mode2<=0;
mode3<=0;
mode4<=0;
mode5<=0;
mode6<=0;
end //if end
else
begin
for (i=1; i<43; i=i+1)
begin
R<=xcost+ycost;
costholder <= SAD+(lambda*R); // Here we calculate the cost of a sub-blocks As the clock
if (i<17)
mode0<=costholder+mode0;
else if(i>16 && i<25)
mode1<=costholder+mode1;
else if(i>24 && i<33)
mode2<=costholder+mode2;
else if(i==33 || i==34 || i==35 || i==36 )
mode3<=costholder+mode3;
else if(i==37 || i==38)
mode4<=costholder+mode4;
else if(i==39 || i==40)
mode5<=costholder+mode5;
else if(i==41)
mode6<=costholder+mode6;
end //for end
end //else end
end //always end
Module Costcalculator:
//**********************************************************‌​**
module Costcalculator (motionvector, cost); // X AND Y COST CALCULATOR
input [4:0]motionvector;
output [2:0]cost;
reg [2:0]cos;
wire [3:0] vector;
assign vector = {motionvector[3:0] };
always #* begin
case (vector) 0 : cos=0;
1,2 : cos=1;
3,4,5,6 : cos=2;
7,8,9,10,11,12,13,14 : cos=3;
15 : cos=4;
endcase
end
assign cost = cos;
endmodule
//**********************************************************‌​**

After taking the module outside the always block, you are driving xconst and yconst from two places. On the other hand, I don't see drivers of X and Y.
Since Costcalculator is a purely combinational module, you need to just provide the inputs X and Y as zero from the top/wrapper module.
//.. some stuff
if(reset) begin
//... some other signals
X <= 0;
Y <=0;
//...
As the error says about multiple drivers, you are driving xconst and yconst form two modules. On reset, if you provide X and Y as 0 from the wrapping module, then automatically the vector will go to Zero and ultimately the cost which is the output of module will become Zero. Thereby the variables xconst and yconst will become zero.
Refer to this similar forum question for more information.

Related

If-else statement with same conditions as other if-else statement do not produce same output

So I have to do an assigment where I have to write a counter which hase upcount mode = 1 -> increment = 5 and downcount mode = 0 -> decrement = -9. There is an invalid value of -69 which the counter should jump over.
There are also upper and lower bounds: -250 to 248.
To test our counter, a testbench was given.
I used the following if-else statement inside a process with the clk signal as sensitivity list entry.
if((cnt_intern + 5) <= 248) then
cnt_intern <= cnt_intern + 5;
end if;
if(cnt_intern = -69) then
cnt_intern <= cnt_intern + 5;
end if;
this did not work as it set the cnt_intern to -69, which the second if statement should prevent. I rewrote the if statement to the following:
if(cnt_intern <= 243) then#
if(cnt_intern = -73) then
cnt_intern <= cnt_intern + 10;
else
cnt_intern <= cnt_intern + 5;
end if;
end if;
This time it did work and it jumped over the vlaue -69 directly to -64.
Anyone knows why? what is wrong with the first way?
best regards
The reason for the observed behavior is that a signal assignment inside a process does not immediately change the signal value. Instead, a transaction is scheduled on the signal, which will take effect when the process suspends (i.e. when the end of the process or a wait statement is reached).
In your first example, if cnt_intern is -74 at the beginning of the process, the first if statement schedules as transaction, that means a change of the signal's value to -69 will take place at the end of the process if no other assignment schedules a transaction on cnt_intern. However, the actual value of cnt_intern stays -74 until the end of the process. So the second if statement will evaluate to false and do nothing. At the end of the process, the value of -69 is assigned to cnt_intern.
This concept seems confusing if you start working with hardware description languages, but it is essential.
You could use a helper variable to circumvent that issue and keep the code readable:
process(clk)
variable v_cnt_intern : integer;
begin
if rising_edge(clk) then
v_cnt_intern := cnt_intern;
if((v_cnt_intern + 5) <= 248) then
v_cnt_intern := v_cnt_intern + 5;
end if;
if (v_cnt_intern = -69) then
v_cnt_intern := v_cnt_intern + 5;
end if;
cnt_intern <= v_cnt_intern;
end if;
end process;
Other solutions are something like the code in your second example, which looks fine.

Implementing a for loop in systemverilog

I want to generate an automated input stimulus for my DUT. This input is going to different modules at the same time and working on this data. I want my input to be generated in an increasing manner. Like 0000,0001,0010,0011...1111
I tried using a for loop but it only uses the last data from the loop and works on that.
always_comb begin
for (i=0, i<16; i=i+1)
begin
data <= i;
end
end
When I give inputs individually like,
data = 8'd1;
#2;
data = 8'd2;
#2;
It works smoothly with all input values specified.
always_comb cannot have delays. At least per the IEEE1800 standard.
You can do something like this:
bit [3:0] data; // bit so the initial value is 0, not x
bit clk;
always #1 clk++; // or some other clock model
always_ff #(posedge clk) begin
data <= data+1;
end
or something like this:
logic [3:0] data;
initial begin
for (i=0, i<16; i=i+1) begin
data = i;
#2;
end
end
Or some other similar code with time delay.

Random number generator in VHDL

I'm designing a test bench and I need to create a random sequence of bits for one of the system's inputs which is normally controlled by the user.
I also want this sequence of bits not being in the same order every time I run the simulation.
I cannot use a PRNG since its initial state will be predefined meaning it while produce the same numbers every time. I also used the uniform function but I had the same issue.
RAND_GEN : process(clk) is
variable seed1, seed2 : positive := 1;
variable re : real;
begin
if rising_edge(clk) then
uniform(seed1, seed2, re);
if (re < 0.5) then
rand_bit <= '0';
else
rand_bit <= '1';
end if;
end if;
end process;
Is there any alternatives for this problem?
Testing with randomly generated inputs is a powerful tehnique and is the technique commonly used to verify ICs these days. Normally, you would run a test with a known, per-determined seed, whereas you want to be able to generate a varying seed. So, you absolutely MUST record this seed when you run the test and provide a mechanism to run a test using this seed. Otherwise, when you find a bug, you will not be able to test whether you've fixed it. You might find it more useful to a a fixed set of tests with a smaller number of manually-generated seeds.
You could use the linux date command with the %s format specifier, which outputs the number of seconds since 1/1/1970 and redirect that to a file.
date +%s >! seed.txt
Then read the file, eg:
RAND_GEN : process(clk) is
variable seed1, seed2 : positive := 1;
variable re : real;
file F: TEXT;
variable L: LINE;
variable seed_RNG : boolean := false;
begin
if not seed_RNG then
file_open(F, "seed.txt", READ_MODE);
readline (F, L);
read (L, seed1); -- or seed2
file_close(F);
report "seed1 = " & integer'image(seed1);
seed_RNG := true;
end if;
if rising_edge(clk) then
uniform(seed1, seed2, re);
if (re < 0.5) then
rand_bit <= '0';
else
rand_bit <= '1';
end if;
end if;
end process;
I don't know anything of VHDL, but in general I try to avoid randomness in tests. Flaky unit tests, for example, are bad. What's the value of a test that fails only sometimes?
Anyway, supposed you really want to do it, do you have access to a timer? You can initialize the PRNG with the current time as seed. Not cryptographically safe, but probably for this use case good enough.
Just for the record, in case anyone needs something similar, I used the above ideas by creating a do file which first writes the date in a file and then runs the do file of the actual test bench which reads this number as suggested before.
set t [clock seconds]
set outputFile [open date.txt w]
puts $outputFile $t
close $outputFile
do testbench.do

How to use iterate variable in case statement [VHDL]

I want to generate my register interface, because I have several instance (channels) of the same peripheral.
while (I < generic_num_of_instances) loop
case loc_addr is
when 0 + I*256 =>
q_ctrl_reg(I, 31 downto 0) <= s_axi_wdata;
end case;
I := I + 1;
end loop;
And it says: Error: Case choice must be locally static expression.
How can I generate this register interface? Should I use less descriptive if/elseif statements?
Matthew mentioned two important improvements, your case target must be a static expression (whose type is a locally static type) and if you are doing synthesis, you need to use a for loop.
Next, you cannot slice a multi-dimensional array, hence, q_ctrl_reg(I, 31 downto 0) is also invalid. Lets fix that by using an array of an array (shown below):
type q_ctrl_reg_type is array (0 to MAX_REG -1) of std_logic_vector(31 downto 0) ;
signal q_ctrl_reg : q_ctrl_reg_type ;
Now lets put it all together, lets us a for loop instead of the while loop and an if statement instead of your case statement:
for i in 0 to generic_num_of_instances - 1 loop
if loc_addr = 0 + I*256 then
q_ctrl_reg(I) <= s_axi_wdata;
end if;
end loop;
Yes. Or use Verilog.
Case choices is VHDL have to be locally static - that is they have to be literals, constants or generics. That isn't the case with Verilog.
You're also going to find that you need a when others branch, which will negate any improved readability gained using a case statement. (And given such a coding style is rather unusual anyway, I'd question whether it was ever more readable.)
try making that "0 + I*256" value equal to a variable that you name in the loop i.e.
while (I < generic_num_of_instances) loop
variable A : integer;
begin
A := 0 + I*256;
case loc_addr is
when A =>
q_ctrl_reg(I, 31 downto 0) <= s_axi_wdata;
end case;
I := I + 1;
end loop;
hopefully this should work

Initial iterator for generate for-loop

In a generate loop, you often need to connect the first iteration of wires to your inputs (or some unique set of wires) before the array stuff kicks in. Pasted below is a snippet from my parameterizable OR-Reduce module (my assignment requires structural verilog, so oOUt = |adjA is not legal).
for(i=0; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
if(i==0) begin
or2$ reduce [oWidth-1:0]
(tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
end else begin
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
end
I have to put this nasty if-statement to catch the first iteration and connect it to the inputs. The problem is that I can't just change the initial i value to 1 and declare a lvl[0].tmp outside of the for-loop. Here's what I think would look nicer if it were legal.
wire [p2Width-1] lvl[0].tmp;
or2$ reduce [oWidth-1:0]
(lvl[0].tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
for(i=1; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
Is there a way to clean up my generate loop?
You can declare your input array to be one entry wider than required. I find this often results in more readable code:
logic [N_LEVELS:0] block_inputs; // Last entry not used, optimised away
logic [N_LEVELS-1:0] block_outputs;
// Start of pipeline
assign block_inputs[0] = stage1_input;
genvar i;
generate
for (i=0; i<N_LEVELS; i++) begin: levels
some_block i_some_block (
.data (block_inputs[i]),
.result (block_outputs[i])
);
assign block_inputs[i+1] = block_outputs[i];
end
endgenerate
assign final_result = block_outputs[N_LEVELS-1];

Resources