Jump to content
  • 0

Create a timer in verilog


NGUYENTRUNGHIEU

Question

Dear all,

I'm trying to test a FPGA design using Verilog code. The code is:

This code create a delay from signal input "Trigger - JA2" with a delay time set by "Switches" of Basys3 board

The output wave signal is at JB0!

I've tested the design by simulating the design, everything works correctly in simulation (see the TB in the project attached).

But when I download this design into Basys 3. and try to mesure by oscilloscope, it doesn't work at all. 

You can see the test code is here:

-------------------***************---------------------

module delay_timer  
 (    
      input [15:0] wb, // weighting bits -> variable for delay time taken from switches of Basys3 board
      input clk_100MHz,
      input trigger, // trigger input of timer 
      output reg [15:0] LED, 
      output reg delay_out_n, // delay output, active low  
      output reg trigger_1,   // testpoint, timer start signal active high 
      output reg trigger_2,   // testpoint, reset timer signal active high 
      output reg trigger_3    // testpoint, Waveform signal looped to trigger signal 
 );  
 reg [15:0] CLOCK_CNT = 0;
 reg[15:0] PULSE_WIDTH ;  
 reg [15:0] DELAY;  
 reg [15:0] TIMER=0;  
 reg trigger_sync_1=0,trigger_sync_2=0;  
 wire trigger_rising,trigger_falling;  
 reg timer_start=0,out_low=0;  
 wire timer_clear;  
 reg reset_timer1=0,reset_timer2=0,reset_timer=0;  
 wire reset_timer3;   
 always @(posedge clk_100MHz)  
 begin  
           trigger_sync_1 <= trigger; // the first Flip-Flop  
           trigger_sync_2 <= trigger_sync_1;// the second Flip-Flop  
           reset_timer1 <= reset_timer;  
           reset_timer2 <= reset_timer1;  
 end  
 // Identify the zero to one transitions on trigger signal  
 assign trigger_rising = trigger_sync_1 & (~trigger_sync_2);   
 assign trigger_falling = trigger_sync_2 & (~trigger_sync_1);   
 assign reset_timer3 = reset_timer1 & (~reset_timer2);  
 // sample Mode and wb  
 always @(trigger_rising,trigger_falling,wb)  
 begin  
      if(trigger_falling == 1 || trigger_rising == 1) begin  
           PULSE_WIDTH = wb;  
           DELAY = (2*wb + 1)/2;  
           LED <= DELAY;  // show the delay value in the leds of Basys3
      end  
 end  
 // modes  
 always @(trigger_falling,trigger_rising,TIMER,trigger,DELAY)  
 begin   
                               if(trigger_rising==1) begin  
                                    timer_start <= 1;  
                                    reset_timer <= 0;  
                                    end  
                               else if(trigger_falling==1 || trigger == 0) begin  
                                    out_low <= 0;  
                                    reset_timer <= 1;  
                                    timer_start <= 0;  
                               end  
                               else if(TIMER >= DELAY) begin  
                                    out_low <= 1;  
                                    timer_start <= 0;  
                                    reset_timer <= 1;  
                               end                                                     
 end
    
 always @(posedge clk_100MHz or posedge timer_clear)  
 begin    
      if(timer_clear)   
           TIMER <= 0;  
      else if(timer_start)  
           TIMER <= TIMER + 1;  
 end  
 
 assign timer_clear = reset_timer3 | trigger_rising == 1;  
 //delay output  
 always @(posedge clk_100MHz)  
 begin 
      trigger_1 <= timer_start;
      trigger_2 <= reset_timer;
      trigger_3 <= CLOCK_CNT[9]; // Waveform signal looped to trigger signal
      delay_out_n <= out_low;
      CLOCK_CNT <= CLOCK_CNT + 1;
 end  
 
 endmodule  

-------------------------***************---------------------------------

The .xdc file is here

 

-----------------------XDC-----------------------------------

# Clock signal
set_property PACKAGE_PIN W5 [get_ports clk_100MHz]
set_property IOSTANDARD LVCMOS33 [get_ports clk_100MHz]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk_100MHz]

# Switches
set_property PACKAGE_PIN V17 [get_ports {wb[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[0]}]
set_property PACKAGE_PIN V16 [get_ports {wb[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[1]}]
set_property PACKAGE_PIN W16 [get_ports {wb[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[2]}]
set_property PACKAGE_PIN W17 [get_ports {wb[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[3]}]
set_property PACKAGE_PIN W15 [get_ports {wb[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[4]}]
set_property PACKAGE_PIN V15 [get_ports {wb[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[5]}]
set_property PACKAGE_PIN W14 [get_ports {wb[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[6]}]
set_property PACKAGE_PIN W13 [get_ports {wb[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[7]}]
set_property PACKAGE_PIN V2 [get_ports {wb[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[8]}]
set_property PACKAGE_PIN T3 [get_ports {wb[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[9]}]
set_property PACKAGE_PIN T2 [get_ports {wb[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[10]}]
set_property PACKAGE_PIN R3 [get_ports {wb[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[11]}]
set_property PACKAGE_PIN W2 [get_ports {wb[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[12]}]
set_property PACKAGE_PIN U1 [get_ports {wb[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[13]}]
set_property PACKAGE_PIN T1 [get_ports {wb[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[14]}]
set_property PACKAGE_PIN R2 [get_ports {wb[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {wb[15]}]


# leds
set_property PACKAGE_PIN U16 [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]
set_property PACKAGE_PIN E19 [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]
set_property PACKAGE_PIN U19 [get_ports {LED[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]
set_property PACKAGE_PIN V19 [get_ports {LED[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]
set_property PACKAGE_PIN W18 [get_ports {LED[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[4]}]
set_property PACKAGE_PIN U15 [get_ports {LED[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[5]}]
set_property PACKAGE_PIN U14 [get_ports {LED[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[6]}]
set_property PACKAGE_PIN V14 [get_ports {LED[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[7]}]
set_property PACKAGE_PIN V13 [get_ports {LED[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[8]}]
set_property PACKAGE_PIN V3 [get_ports {LED[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[9]}]
set_property PACKAGE_PIN W3 [get_ports {LED[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[10]}]
set_property PACKAGE_PIN U3 [get_ports {LED[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[11]}]
set_property PACKAGE_PIN P3 [get_ports {LED[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[12]}]
set_property PACKAGE_PIN N3 [get_ports {LED[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[13]}]
set_property PACKAGE_PIN P1 [get_ports {LED[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[14]}]
set_property PACKAGE_PIN L1 [get_ports {LED[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[15]}]


# JA output
set_property PACKAGE_PIN J2 [get_ports trigger]
set_property IOSTANDARD LVCMOS33 [get_ports trigger]

# JB input
set_property PACKAGE_PIN A14 [get_ports delay_out_n]
set_property IOSTANDARD LVCMOS33 [get_ports delay_out_n]
set_property PACKAGE_PIN A16 [get_ports trigger_1]
set_property IOSTANDARD LVCMOS33 [get_ports trigger_1]
set_property PACKAGE_PIN B15 [get_ports trigger_2]
set_property IOSTANDARD LVCMOS33 [get_ports trigger_2]

 

----------------end XDC-----------------------------------------

 

The test bench is here:

------------TB-------------------------------------------------------

module delay_timer_tb;
    
// Inputs  
      reg clk_100MHz; 
      reg [15:0] wb;    
      reg trigger;   
      // Outputs  
      wire [15:0] LED; 
      wire delay_out_n; 
      wire trigger_1;
      wire trigger_2;
      wire trigger_3; 
      //fpga4student.com: FPga projects, Verilog projects, VHDL projects
      // Instantiate the Unit Under Test (UUT)  
      
      
      delay_timer uut (  
           .wb(wb),   
           .clk_100MHz(clk_100MHz),      
           .trigger(trigger),   
           .LED(LED),      
           .delay_out_n(delay_out_n),  
           .trigger_1(trigger_1),  
           .trigger_2(trigger_2),  
           .trigger_3(trigger_3)  
      );  
      initial begin  
           // Initialize Inputs  
           wb = 50;    
           trigger = 0;  
           #500;  
           trigger = 1;  
           #15000;  
           trigger = 0;  
           #15000;  
           trigger = 1;  
           #2000;  
           trigger = 0;  
           #2000;  
           trigger = 1;       
           #2000;  
           trigger = 0;       
           #20000;  
           trigger = 1;            
           #30000;  
           trigger = 0;  
           #2000;  
           trigger = 1;  
           #2000;  
           trigger = 0;       
           #4000;  
           trigger = 1;       
           #10000;  
           trigger = 0;  
           #500;  
           trigger = 1;  
           #15000;  
           trigger = 0;  
           #15000;  
           trigger = 1;  
           #2000;  
           trigger = 0;  
           #2000;  
           trigger = 1;       
           #2000;  
           trigger = 0;       
           #20000;  
           trigger = 1;            
           #30000;  
           trigger = 0;  
           #2000;  
           trigger = 1;  
           #2000;  
           trigger = 0;       
           #4000;  
           trigger = 1;       
           #10000;  
           // Delay Operate  
           // Add stimulus here  
      end  
   initial begin   
   clk_100MHz = 0;  
   forever #5 clk_100MHz = ~clk_100MHz;  
      end      
endmodule

 

-------------End TB-----------------------------------------

image.thumb.png.83dc97328f6fa252097580f85a8bcade.png

 

image.png.45979571c8ae415490e425f2730b3cbf.png

 

Please help me to know why?

image.thumb.png.83dc97328f6fa252097580f85a8bcade.png

 

Edited by NGUYENTRUNGHIEU
Link to comment
Share on other sites

7 answers to this question

Recommended Posts

  • 0

@NGUYENTRUNGHIEU

Please help me to know why?

That is why you should write a test-ebnch and simulate your design.

Have you done that? If yes, where are the simulation results? Do you see problems in simulation?

Never ever try to test a design on the board without simulating a design!

 

Edited by dpaul
Link to comment
Share on other sites

  • 0
4 hours ago, dpaul said:

@NGUYENTRUNGHIEU

Please help me to know why?

That is why you should write a test-ebnch and simulate your design.

Have you done that? If yes, where are the simulation results? Do you see problems in simulation?

Never ever try to test a design on the board without simulating a design!

 

Hi Dpaul,

Yes, I've simulated the design. All works correctly. But when I've tested in the board, it hasn't worked!

Link to comment
Share on other sites

  • 0
On 7/12/2024 at 6:58 PM, artvvb said:

Hi @NGUYENTRUNGHIEU

What are your location constraints, and what do you expect this design to do when it's programmed into the physical board?

Thanks,

Arthur

Hi,

Thank Arthur for reply. 

I've remodified the code, now it's very simple!

The goal of my design is that:

I have a input signal (1 or 0). The output signal must be delayed from Rising edge of input for X µs (X can be set by user, for example, via the switches of Basys 3 board)!

I'm new in the FPGA design, so please help me in detail.

Thank you very much!

Link to comment
Share on other sites

  • 0

Hey @NGUYENTRUNGHIEU

Your location constraints are missing the trigger_3 port - please review your warnings, critical warnings, and errors in Vivado, there might be something about an unconstrained port. In general, you should review these messages regardless.

I haven't built your sources myself to check errors (just takes time...), but some assorted comments on your code:

On 7/12/2024 at 8:33 AM, NGUYENTRUNGHIEU said:


 always @(trigger_rising,trigger_falling,wb)  
 begin  
      if(trigger_falling == 1 || trigger_rising == 1) begin  
           PULSE_WIDTH = wb;  
           DELAY = (2*wb + 1)/2;  
           LED <= DELAY;  // show the delay value in the leds of Basys3
      end  
 end  

The tools may or may not optimize the multiply and divide here, but if they don't, I might be concerned about meeting timing, which would generate critical warnings if failed. The same operation can be done using bit shifting and concatenation - "{wb, 1'b0}" is equivalent to "2 * wb" for example. You might also want to simulate the differences in results when replacing "(2*wb+1)/2" with "wb" - they ought to be the same results...

Also, mixing "LED <= DELAY" in here alongside blocking assignments is a potential issue. Mixing them is just best avoided: https://nandland.com/blocking-vs-nonblocking-in-verilog/. There's probably an inferred latch in this block - combinatorial blocks should usually cover all edge cases - edit: this can be spotted at a glance from these always blocks missing "else" statements.

On 7/12/2024 at 8:33 AM, NGUYENTRUNGHIEU said:


 always @(trigger_falling,trigger_rising,TIMER,trigger,DELAY)  
 begin   
                               if(trigger_rising==1) begin  
                                    timer_start <= 1;  
                                    reset_timer <= 0;  
                                    end  
                               else if(trigger_falling==1 || trigger == 0) begin  
                                    out_low <= 0;  
                                    reset_timer <= 1;  
                                    timer_start <= 0;  
                               end  
                               else if(TIMER >= DELAY) begin  
                                    out_low <= 1;  
                                    timer_start <= 0;  
                                    reset_timer <= 1;  
                               end                                                     
 end

Similarly, using nonblocking assignments in a combinatorial block could be an issue, due to inferred latches - based on trigger_start being used as an enable pin later down in the source, it seems you intend its "1" state to be held for more than one clock cycle. It potentially does in simulation, because of the implied latch, but that's not good practice in synthesis - if something needs to hold a value for more than a clock cycle, without something else its derived from to hold that value for it, it needs to be clocked. In this case, neither timer_start nor trigger_rising are clocked, and trigger_rising only holds its value for a single cycle. Things working in simulation are probably due to issues with the coding style that lead to the aforementioned latches...

Looking into both the differences between combinatorial and sequential logic (and therefore the underlying digital circuits you're describing through your HDL) and the differences between blocking and nonblocking assignment in Verilog would be recommended.

Hope this helps,

Arthur

 

Link to comment
Share on other sites

  • 0
On 7/16/2024 at 12:07 AM, artvvb said:

Hey @NGUYENTRUNGHIEU

Your location constraints are missing the trigger_3 port - please review your warnings, critical warnings, and errors in Vivado, there might be something about an unconstrained port. In general, you should review these messages regardless.

I haven't built your sources myself to check errors (just takes time...), but some assorted comments on your code:

The tools may or may not optimize the multiply and divide here, but if they don't, I might be concerned about meeting timing, which would generate critical warnings if failed. The same operation can be done using bit shifting and concatenation - "{wb, 1'b0}" is equivalent to "2 * wb" for example. You might also want to simulate the differences in results when replacing "(2*wb+1)/2" with "wb" - they ought to be the same results...

Also, mixing "LED <= DELAY" in here alongside blocking assignments is a potential issue. Mixing them is just best avoided: https://nandland.com/blocking-vs-nonblocking-in-verilog/. There's probably an inferred latch in this block - combinatorial blocks should usually cover all edge cases, meaning you would still provide these 

Similarly, using nonblocking assignments in a combinatorial block could be an issue, due to inferred latches - based on trigger_start being used as an enable pin later down in the source, it seems you intend its "1" state to be held for more than one clock cycle. It potentially does in simulation, because of the implied latch, but that's not good practice in synthesis - if something needs to hold a value for more than a clock cycle, without something else its derived from to hold that value for it, it needs to be clocked. In this case, neither timer_start nor trigger_rising are clocked, and trigger_rising only holds its value for a single cycle. Things working in simulation are probably due to issues with the coding style that lead to the aforementioned latches...

Looking into both the differences between combinatorial and sequential logic (and therefore the underlying digital circuits you're describing through your HDL) and the differences between blocking and nonblocking assignment in Verilog would be recommended.

Hope this helps,

Arthur

 

Dear Arthur,

I would like to thank you having spent your time to reply my question and your great comments. Because of people like you, beginers as me can progress! Your comments are very helpful!

Have a good day and many thanks again!

Trung Hieu

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...