# While loop synthetize???

Status
Not open for further replies.

#### melpeza

##### Newbie level 4
Hi,

do you know how to correctly implement this:

I would like to do something in while loop.. After that i would like to generate internal signal that the while loop has finished... So, my question is, are these two operations parallel, or while loop first finish, and after that signal generates...

My code is:

Code Verilog - [expand]1
2
3
4
5
6
7
8
9
10
always @ (posedge mem_full) begin

while( br2 < br1)
begin
out = out*mem[br1+1] + mem[br2];
br2 = br2+1;
end

signal = 1;
end

Thanks!!!

Last edited by a moderator:

#### FvM

##### Super Moderator
Staff member
To be synthesizable the loop must have statically computable bounds, which requires br1 to be a constant and br2 initialized with a constant.

The order of loop construct and signal assertion doesn't matter outside the always block, and is meaningless if signal isn't read inside the block.

##### Super Moderator
Staff member
Even if you have a loop with statically computable bounds, you do realize that the while loop you proposed is going to be unrolled for all iterations of br2?
e.g. if you start br2 = 0 and br1 = 3 then you'll end up with
Code:
 out = (((initial_out_value*mem[3+1] + mem[0])*mem[[3+1] + mem[1])*mem[3+1] + mem[2])

As br1 gets larger the more multiplication and addition stages are chained together. This will be extremely slow design for any br1 that is much larger than my example. Given this while loop and the use of:
Code:
//It's a bad idea in an FPGA to use an internal signal as a clock.
// I won't go into the why of it.
always @ (posedge mem_full) begin
Both of these things make me think you might only have experience writing software.

Don't think of Verilog as a software language. It's a hardware description language, so unless you know what you want your hardware to look like I wouldn't even start writing Verilog code.

Regards

Points: 2

Points: 2

### melpeza

Points: 2

#### melpeza

##### Newbie level 4
This is just program for test module... There are many mistakes and i needs to be optimized..

But my question was... Is the while loop parallel with the internal signal...

Or, while loop finish first, than signal generate

Thanks again!

#### melpeza

##### Newbie level 4
Also i have a question about for loop synthesis... I found all kinds of opinions about for loop..

Someone said that for loop can be synthesized only if using @( clk )

My code:

Code:
always @ (posedge mem_full) begin

for( i=0; i<SIZE; i=i+1 )
begin
out = out*mem[SIZE]+mem[i];
end

end

SIZE is fixed parameter.. I would like to do this loop only once

Thanks!

##### Super Moderator
Staff member
Do you understand the difference between blocking (=) and non-blocking (<=) assignments? Do not use blocking assignments when writing edge sensitive always blocks. Edge sensitive always block are for modeling edge sensitive logic like flip-flops.

In regards to the while loop. It takes 0 time to execute. All loops in Verilog behave this way unless you have some sort of time control statements within the loop.

I could go on, but responding by phone is a pain.

Regards

Last edited:
melpeza

### melpeza

Points: 2

#### melpeza

##### Newbie level 4
Yeah i understand these diference... Inside that block is a code i would like to do just once... So i used this posedge thing

I would also like to ask this...

I have a program that receive data over UART... UART i capable to transfer only 8bits of data.. Including 2 stop bits ..

My main output register is 8bit, but i have 16bit temporary register... I count the result inside temporary register

Now if my resut 650.. I need 16bits for this.. How to send this over UART and get the right result on HYPERTERMINAL..

##### Super Moderator
Staff member
Using the posedge infers an edge sensitive piece of logic (i.e. a flip-flop). If you want to do it only once then you should generate an enable pulse from the mem_full signal, that either launches an FSM or pipelined version of the computation or generates a level signal that is used by an level sensitive always block (i.e. always @*) that is the combinational computation.

The UART is sending data a byte at a time. If the result is 650 (binary encoded) then the value is sent as 0x02 followed by 0x8A if sent MSB first. If it's sent as ASCII then you'll receive 0x36, 0x35, 0x30.

Regards

- - - Updated - - -

Oh, and to answer the question about the signal = 1; assignment it would not actually happen after the entire loop is unrolled. In simulation it would, but in actual hardware you will have a mismatch as signal = 1; will be assigned based on the rising edge of mem_full. If there were time control statements in the while loop you would see the signal assignment occurring after the loop finishes however many iterations were requested.

melpeza

### melpeza

Points: 2

#### melpeza

##### Newbie level 4
What's the way to generate the code as ASCII??

I have UART module from asic-world that recives byte and sends a byte... This byte is sent bit at time..

The module:
Code:
//-----------------------------------------------------
// Design Name : uart
// File Name   : uart.v
// Function    : Simple UART
// Coder       : Deepak Kumar Tala
//-----------------------------------------------------
module uart (
reset          ,
txclk          ,
ld_tx_data     ,
tx_data        ,
tx_enable      ,
tx_out         ,
tx_empty       ,
rxclk          ,
uld_rx_data    ,
rx_data        ,
rx_enable      ,
rx_in          ,
rx_empty
);
// Port declarations
input        reset          ;
input        txclk          ;
input        ld_tx_data     ;
input  [7:0] tx_data        ;
input        tx_enable      ;
output       tx_out         ;
output       tx_empty       ;
input        rxclk          ;
input        uld_rx_data    ;
output [7:0] rx_data        ;
input        rx_enable      ;
input        rx_in          ;
output       rx_empty       ;

// Internal Variables
reg [7:0]    tx_reg         ;
reg          tx_empty       ;
reg          tx_over_run    ;
reg [3:0]    tx_cnt         ;
reg          tx_out         ;
reg [7:0]    rx_reg         ;
reg [7:0]    rx_data        ;
reg [3:0]    rx_sample_cnt  ;
reg [3:0]    rx_cnt         ;
reg          rx_frame_err   ;
reg          rx_over_run    ;
reg          rx_empty       ;
reg          rx_d1          ;
reg          rx_d2          ;
reg          rx_busy        ;

// UART RX Logic
always @ (posedge rxclk or posedge reset)
if (reset) begin
rx_reg        <= 0;
rx_data       <= 0;
rx_sample_cnt <= 0;
rx_cnt        <= 0;
rx_frame_err  <= 0;
rx_over_run   <= 0;
rx_empty      <= 1;
rx_d1         <= 1;
rx_d2         <= 1;
rx_busy       <= 0;
end else begin
// Synchronize the asynch signal
rx_d1 <= rx_in;
rx_d2 <= rx_d1;
if (uld_rx_data) begin
rx_data  <= rx_reg;
rx_empty <= 1;
end
// Receive data only when rx is enabled
if (rx_enable) begin
// Check if just received start of frame
if (!rx_busy && !rx_d2) begin
rx_busy       <= 1;
rx_sample_cnt <= 1;
rx_cnt        <= 0;
end
// Start of frame detected, Proceed with rest of data
if (rx_busy) begin
rx_sample_cnt <= rx_sample_cnt + 1;
// Logic to sample at middle of data
if (rx_sample_cnt == 7) begin
if ((rx_d2 == 1) && (rx_cnt == 0)) begin
rx_busy <= 0;
end else begin
rx_cnt <= rx_cnt + 1;
// Start storing the rx data
if (rx_cnt > 0 && rx_cnt < 9) begin
rx_reg[rx_cnt - 1] <= rx_d2;
end
if (rx_cnt == 9) begin
rx_busy <= 0;
// Check if End of frame received correctly
if (rx_d2 == 0) begin
rx_frame_err <= 1;
end else begin
rx_empty     <= 0;
rx_frame_err <= 0;
// Check if last rx data was not unloaded,
rx_over_run  <= (rx_empty) ? 0 : 1;
end
end
end
end
end
end
if (!rx_enable) begin
rx_busy <= 0;
end
end

// UART TX Logic
always @ (posedge txclk or posedge reset)
if (reset) begin
tx_reg        <= 0;
tx_empty      <= 1;
tx_over_run   <= 0;
tx_out        <= 1;
tx_cnt        <= 0;
end else begin
if (ld_tx_data) begin
if (!tx_empty) begin
tx_over_run <= 0;
end else begin
tx_reg   <= tx_data;
tx_empty <= 0;
end
end
if (tx_enable && !tx_empty) begin
tx_cnt <= tx_cnt + 1;
if (tx_cnt == 0) begin
tx_out <= 0;
end
if (tx_cnt > 0 && tx_cnt < 9) begin
tx_out <= tx_reg[tx_cnt -1];
end
if (tx_cnt == 9) begin
tx_out <= 1;
tx_cnt <= 0;
tx_empty <= 1;
end
end
if (!tx_enable) begin
tx_cnt <= 0;
end
end

endmodule

I send data from my module to this module... For this code do i need to tweak something or add some module to do conversion to ASCII

Last edited:

##### Super Moderator
Staff member
The above problem is why you don't want to use blocking (=) assignments in an edge sensitive always block...mismatches between simulation and the hardware synthesized.

#### FvM

##### Super Moderator
Staff member
I don't exactly understand where you see a mismatch between simulation and hardware behaviour. Viewn from the always block outside, only the final assignments to each variable matter, they'll occur simultaneously.

The difference between blocking and non-blocking assignments in the clock sensitive always block (post #1 code) matters, if the results are read in another clock sensitive code on the same clock edge. When using blocking assignments, the result might be read in the present clock cycle if the other block is scheduled later.

##### Super Moderator
Staff member
FvM, You're right, I keep seeing the blocking assignments in the code and think combinational circuit instead of sequential circuit, therefore out is a registered output and so is signal. I keep confusing what I see as the intent of the circuit: compute the value out after the memory is full and then signal when the out calculation is completed, and the way it's coded (which doesn't match the intent).

Thanks for pointing out my mistake.

- - - Updated - - -

What's the way to generate the code as ASCII??
I send data from my module to this module... For this code do i need to tweak something or add some module to do conversion to ASCII
The UART doesn't care what data you send. If you send the data as binary data. 650 => 0x02 & 0x8A, Hyperterminal will display it as ASCII probably according to the following table if it supports the extended character set. https://www.ascii-code.com/

If you want the number 650 (0x028A) to show up as 650 in Hyperterminal then you'll have to convert it to ASCII before sending it. It would be a lot easier to display the hex value instead.

#### FvM

##### Super Moderator
Staff member
I didn't want to critisize your general reservation against mixing blocking assignments with registered logic. We can and probably should avoid it for sake of code clarity.

Status
Not open for further replies.