I've gotten in the habit of developing a lot testbenches and use for() and while() loops for testing purpose. Thats fine. The problem is that I've taken this habit over to coding for circuits which should be synthesizable. XST and others refuse to synthesize code (without additional modification to synthesis parameters) such as:
while (num < test_number)
begin
.
.
.
num = num+1;
end
This is bad coding style because to the synthesizer test_num is an int with value 2^32! or it sees it as unbounded parameter. Either way, its a bad coding habit. But I'm so used to doing this in C and testbenches. What would be the equivalent synthesizable of code of the above code segment?
Thanks!
Synthesis tools vary but generally a loop can be synthesized so long as the number of iterations is known a to the synthesis tool. So,
for ( i = 0; i < 10; i = i + 1 )
is OK because the tool knows there are 10 loop iterations. But
reg [10:0] r;
for ( i = 0; i < r; i = i + 1 )
is not OK because r is a variable r's value is unknown at synthesis time.
Think of loops in RTL code as creating a known fixed number of copies of a piece of logic.
You need to have a clock to control it to start.
always #(posedge clk or negedge rst_n)
if (!rst_n)
num <= 32'b0; // or whatever your width is.
else
if (num < test_number)
num <= num + 1'b1;
If your synthesis tool does not support while or for loops, then don't use a loop. Just expand your code out.
wire [1:0] addr;
reg [3:0] wren;
always #(posedge clk) begin
wren[0] <= (addr == 2'd0);
wren[1] <= (addr == 2'd1);
wren[2] <= (addr == 2'd2);
wren[3] <= (addr == 2'd3);
end
I am unfamiliar with XST, but some synthesis tools do support loops (Synopsys, for example).
Related
I have the following code:
/* some calculation */
do {
/* data acquire and calculation */
} while (CONDITION);
My condition looks like one of the following:
(( A || B ) && C )
( A && C )
Note that I use these conditions with different statements for A, B and C. However the pre-calculation and everything inside the loop is always the same. I use this block several times in my code and wondered if there is a possibility to put it in a define or in a function to let the code look cleaner.
Is there a nice and reasonable way to achieve the loop with different statements?
I already thought about a function call in a while loop like
while (DoMyLoop( CONDITION, calculationParams ));
But with this solution I wouldn't have the pre-calculation in my one-liner.
How can I get my code block in a nice one-liner (or more if necessary, as long as it's easy to understand and maintain)?
Some additional (maybe irrelevant) information:
In my loop I receive a byte array and depending on the situation I have to loop until a specific bit changes, therefore the A or B.
C is a timeout condition.
Here is some code with variables
unsigned char data[10] = { 0 };
long intervalMS = 0;
/* precalc */
gettimeofday( &stopTimeout, NULL );
gettimeofday( &startTimeout, NULL );
do {
receiveCall( data );
gettimeofday( &stopTimeout, NULL );
intervalMS = (stopTimeout.tv_sec - startTimeout.tv_sec) * 1000 +
(stopTimeout.tv_usec - startTimeout.tv_usec) / 1000;
} while ( (data[0] & 0x01) && intervalMS < 200);
The A part of the condition can also look like ((data[2] & 0x02) || data[3] == 0x12).
What about next solution?
for (precalculation (); CONDITION; somethingWith (calculationParams));
precalculation () is executed once, the CONDITION is evaluated at every iteration and somethingWith (calculationParams) take the place in of the incrementation. The body of the for loop is empty.
Pure C beauty.
Obviously, precalculation and somethingWith (calculationParams) must become a new function.
First of all, please note that do {} while(something) is equivalent to something=true; while something{}. The former saves a bit of extra execution in case you don't want the initialization part.
How can I get my code block in a nice one-liner
There is nothing wrong with your code. } while ( (data[0] & 0x01) && intervalMS < 200); is perfectly clear to me - another C programmer.
You check if the lsb is set and you check a timer interval. The only way this code could be improved would be to explain why you check the lsb - which you can do with a comment (do you check if a number is odd or do you read a bit in bit-field etc).
Now what you can and should do, is to put the whole snippet inside a function and give it a meaningful name. There's the nice one-liner.
I'm trying to create a simple loop in assembly to perform an instruction until a certain condition is met. For example, I want to implement this C code in assembly:
int compute_sum(int n)
{
i = 2;
sum = 0;
while(i <= n)
{
sum = sum + i;
i = i + 4;
}
}
The outline I made for myself is this:
/ ADD (compute sum)
/ Increment to keep track of # times passed through loop
/ SNA (skip if difference between user input and number is < 0)
/ BUN xxx (repeat)
I read in user input and have the decimal representation, but do not know the address that should follow BUN so that the instructions are repeated. These are all done in simple computer instructions
You might want to practice getting into the correct mindset by using C without structured conditions (ie using labels and gotos):
i = 2;
sum = 0;
loop:
if (i > n) goto finished;
sum = sum + i;
i = i + 4;
goto loop;
finished:
This is perfectly valid C (albeit archaic) but shows what you need to do at the simplest level. Compare i with n and branch to finished if greater and branch unconditionally to the loop level.
If the assembler language you are using does not have an unconditional branch then you can set the flag and branch (eg SEC, BCS loop) or count on the idea that i will not overflow and when you add 4, branch on no overflow - just make sure it doesn't fail catastrophically if this is not the case.
So, in assembler (which shares the label syntax), you would have:
loop:
cmp i, n ; Or register equivelents
bgt finished
....
add i, 4
bvc loop
finished:
I want to convert several tests to an int which bits are the results of a test:
int i=0;
if (m>speed0) i|=0B00001;
if (m>speed1) i|=0B00010;
if (m>speed2) i|=0B00100;
if (m>speed3) i|=0B01000;
That seems very slow. Are there a better way ? Speed is very important (i'm on arduino)
One thing you could try is to build an "if-ladder" to only make one write to i; by rolling the lower bits into each the higher test's value, and reversing the order of the tests.
int i;
if (m > speed3) i = B00001111;
else if(m > speed2) i = B00000111;
else if(m > speed1) i = B00000011;
else if(m > speed0) i = B00000001;
else
i = 0;
This also cuts away the read-modify-write, since it always does a single write to i. You're still going to have to profile this, I really can't say if it's going to be faster.
Oh, and the thing that looks like a binary prefix (the B) is an Arduino-ism, not standard in C. I think it's just 256 preprocessor macros.
What about this one:
int i = (m>speed0) |
((m>speed1)<<1) |
((m>speed2)<<2) |
((m>speed3)<<3)
This will remove the branches so you will not suffer from branch mispredictions. This code should be very fast. However, note that a very good optimizing compiler might be able to transform your code to equivalent code and elide the branches. But with my solution, you can be sure that you will not suffer branch misses even with a poor optimizer.
Edit:
However, since you are on Arduino, branch misses are not an issue. Then, your code should be fine as well. Simply benchmark it. If yours is too slow try mine. But I guess, both should be fine.
I would go with an "if binary tree" since it is scalable and should have a performance of log2(n):
int i = 0; // Default m < speed 0
if(m > speed2)
if (m > speed3)
i = B00001111; // m > speed 3
else
i = B00000111; // m > speed 2
else
if(m > speed1)
i = B00000011; // m > speed 1
else if(m > speed0)
i = B00000001; // m > speed 0
Do profile this since jumps and memory access times are highly dependent on hardware architecture.
To start off, I have a very limited knowledge of C, just basic functions. I have been set a task in VHDL of which i have no experience.
The task is to write a program in VHDL that will use a loop to add a list of 10 numbers (13,8,6,5,19,21,7,1,12,3).
I was thinking of a way of doing this even in C to see if i could somewhat mimic the method. so far i have only came up with
int start = 0;
int add = start;
int increment = 5;
for (int i=0; i<10; i++) {
add = add + increment;
}
now i know that is VERY basic but it's the best i can do. that loop will only increment it by 5 as apposed to the list that i have.
Any help is very appreciated and it's my first question so apologies i if i am breaking any 'unwritten laws'
You mention that this is a part of a study on parwan processors, So the way to think about it depends a lot on how you are studying them.
If you are building up an implementation of the processor than just learning the syntax for logical operations is the important part, and you should focus on the types
unsigned range 0 to 255 and signed range -128 to 127. By making use of the package ieee.numeric_std.all you get the addition operation defined for those types.
If however the processor is already defined for you take a good look at the processor interfaces. The code you will write for this will be much more of an explicit state machine.
Either way I find the best way to start is to write a test bench. This is the part that will feed in the list of inputs, because ultimately you wont want it to be a for (int i=0; i<10; i++), but rather a while(1) style of processing.
That's all theory stuff, so here's some pseudo code for a simple accumulator process:
signal acc : unsigned range 0 to 255 := 0; --accumulator register
signal b : unsigned range 0 to 255 := 5; --value to be added
--each cycle you would change b
accumulator :process (clk)
begin
if rising_edge(clk)
acc <= acc + b;
end if;
end process;
or maybe better yet take a look here: Accumulator
The solution below could help you get started with your problem in VHDL:
For the implementation in a FPGA, better solutions could be figured out. So, just consider it as a start...
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add is
port (
clk : in std_logic;
rst : in std_logic;
add : in std_logic;
sum : out std_logic_vector(31 downto 0));
end entity add;
architecture RTL of add is
constant rom_size : integer := 10;
type t_rom is array (0 to rom_size-1) of unsigned(31 downto 0);
constant rom : t_rom := (
to_unsigned(13, sum'length),
to_unsigned(8, sum'length),
to_unsigned(6, sum'length),
to_unsigned(5, sum'length),
to_unsigned(19, sum'length),
to_unsigned(21, sum'length),
to_unsigned(7, sum'length),
to_unsigned(1, sum'length),
to_unsigned(12, sum'length),
to_unsigned(3, sum'length));
signal add_d : std_logic;
signal index : integer range 0 to rom_size;
signal sum_i : unsigned(sum'range);
begin
p_add : process (clk) is
begin
if rising_edge(clk) then -- rising clock edge
if rst = '1' then -- synchronous reset (active high)
sum_i <= (others => '0');
add_d <= '0';
index <= 0;
else
add_d <= add; -- rising edge detection
if add_d = '0' and add = '1' then -- rising_edge -> add next item to sum
sum_i <= sum_i + rom(index);
index <= index + 1;
end if;
end if;
end if;
end process p_add;
-- output
sum <= std_logic_vector(sum_i);
end architecture RTL;
First, I'll point out there's no need to add the complexity of std_logic_vectors or vector arithmetic with signed and unsigned. This works fine with simple integers:
So, you have some numbers coming in and a sum going out:
entity summer
port (
inputs : integer_vector := (13,8,6,5,19,21,7,1,12,3);
sum_out : integer);
end entity summer;
Note, I've initialise the inputs port with your values - normally you'd write to that port in your testbench.
Now to add them up, you need a process:
process(inputs)
variable sum : integer;
begin
sum := 0;
for i in inputs'range loop
sum := sum + inputs(i);
end for;
sum_out <= sum;
end process;
That's a simplistic solution - to create a "best" solution you need a more detailed specification. For example: how often will the inputs change? How soon do you need the answer after the inputs change? Is there a clock?
I am having difficulties with the below code;
int i = 0;
int x = 0;
int ch ;
int n;
while((i < sizeof(buffer) - 1) && (x < (TIMER_FREQ*30)))
{
//getkey_serial0 returns either a (int)character or 0 if nothing on
//UART0
if((ch = getkey_serial0) == 0)
{
x++; //Increment X as there is nothing being received.
}
else
{
if(ch == '\n')
{
n++;
}
if(n < 8){ //Yes I can simplify this but for some reason
} //I only just noticed this :/ Anyway, it is
else{ //just here to avoid saving info I don't need
buffer[i] = ch ;
i++;
}
}
}
As the input it is reading in is the results of a wireless scan the number of entries scanned can vary greatly, and so I need to be able to avoid infinitely looping.
Originally I just read up to 11 \n's but this was rubbish as I kept missing SSID's which I needed, so I decided I needed some sort of timer or method to help me break after X amount of time.
TIMER_FREQ is defined as 10.
Clearly I am doing something stupid so any suggestions or tips would be greatly appreciated.
I generally prefer suggestions to help me try and think out the problem as opposed to fixed code posts :) I always seem to miss something simple despite my best efforts!
Thanks
EDIT: I should mention, this is on an embedded system (ARM7)
You should have access to a general purpose timer interrupt -- commonly called sys_tick().
The general practice in such "bare metal" applications is to configure the interrupt to fire every n milliseconds (10 ms is frequently used on my Cortex M3). Then, have the ISR update a counter. You'll want to ensure the counter update is atomic, so use a 32-bit, properly-aligned variable. (I'm assuming your processor is 32-bit, I can't recall for certain). Then your "application" code can poll the elapsed time as needed.
BUT - this timer discussion might be moot. In my ARM9 applications, we tie an interrupt to the UART's receive buffer. The associated ISR captures the keystroke and then performs any buffer management. Is that an option for you?
Do you really mean:
if((ch = getkey_serial0) == 0) { ...
Or do you actually mean:
if((ch = getkey_serial0()) == 0) { ...
If the latter, this is why your program never returns zero as you are giving it a function pointer. Does your program have many warnings at build?
If you want to time things, look into time(). It will let you see the system's wall clock, so you can determine if too many seconds have elapsed.