Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

While loop synthetize???

Status
Not open for further replies.

melpeza

Newbie level 4
Joined
Jun 10, 2014
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
41
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:

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.
 

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
 
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!
 

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!
 

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:
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..
 

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.
 
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;
  // Uload the rx data
  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:

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.
 

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.
 

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.
 

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.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top