EmbDev.net

Forum: FPGA, VHDL & Verilog Synthesis doesn't match simulation


Author: Kyle G. (kyle_g)
Posted on:

Rate this post
0 useful
not useful
I'm having issues getting the my interface program to work. The 
simulation looks perfect, but when I synthesis and run it, some parts of 
it work and others don't. It kinda seems useless to have a simulator if 
it doesn't tell you what's actually happening, otherwise I'm just 
guessing.

It's supposed to take a button input and send a parallel packet on 
MIOSIO, but when I press the button, all I see on my scope is a little 
blip where CSn goes low for a few nano seconds. If I put start_f <= 0 in 
the "else if (done)" section, it actually works but it just repeats over 
and over like it gets stuck in the loop.

My code is probably very sloppy, but here it is:
module top(pushbutton, MIOSIO_w, CLK_w, CSn_w, dev_clk, LEDS_OUT);
  
  input wire pushbutton;
  output wire [7:0]MIOSIO_w;
  output wire CLK_w;
  output wire CSn_w;
  output wire dev_clk;
  
  wire fpga_clock;
  reg [7:0] tx_data;
  reg [7:0] data_array [0:15];
  wire [3:0] i;
  
  reg [3:0]dat_size;  
  reg start_pulse;
  
  output wire [7:0]  LEDS_OUT;
  wire [7:0] MIOSIO;
  wire CLK;
  wire CSn;
    
//  assign MIOSIO_w = MIOSIO;
  //assign CLK_w = CLK;
  //assign CSn_w = CSn;
  
  always @(posedge fpga_clock)
    begin
      start_pulse <= ~pushbutton;
    end
    
  always @(i)
    begin
      tx_data <= data_array[i];
    end
    
  initial  
  begin
    start_pulse <= 0;
    dat_size <= 1;
    data_array[0] <= 8'h2A;
    data_array[1] <= 8'h3B;
  end

  OSCH #(.NOM_FREQ("133.00")) rc_oscillator(.STDBY(1'b0), .OSC(fpga_clock));
  ft221x_write test(.sys_clk(fpga_clock), .tx_data(tx_data), .dat_size(dat_size), .dat_index(i), .start(start_pulse), .MIOSIO(MIOSIO_w), .CLK(CLK_w), .CSn(CSn_w), .dev_clk(dev_clk), .LEDS(LEDS_OUT));
  
endmodule


module ft221x_write(sys_clk, tx_data, dat_size, dat_index, start, MIOSIO, CLK, CSn, dev_clk, LEDS);
// Set CPOL = 0 in FTPROG

// Input wires from internal regs 
input wire start;
input wire sys_clk;
input wire [3:0] dat_size;  
input wire [7:0] tx_data;
output reg [3:0] dat_index;

output reg [7:0]MIOSIO;    // Wired to MIOSIO - TEST - might not be necessary
output reg CSn;          // Wired to CSn - TEST - might not be necessary
output reg CLK;        // Wired to CLK - TEST - might not be necessary
reg [7:0]leds_r;
output wire [7:0]LEDS;

// Used for clock divider timing
reg [7:0] clk_div;    
reg [7:0] clk_count;    
output reg dev_clk;
reg [1:0] turnaround_counter;
reg [3:0] packet_count;  
reg done;
wire T, C, R;
wire Q, Qn;
reg start_f;

pulse_latch start_l(T, C, R, Q, Qn);
assign LEDS = ~leds_r;

initial
begin    
  start_f <= 1'b0;
  done <= 1'b1;
  dat_index <= 4'h0;
  MIOSIO <= 8'bzzzzzzzz;    
  turnaround_counter <= 2'b10;
  CSn <= 1'b1;
  dev_clk <= 1'b1;
  clk_count <= 8'h0;
  clk_div <= 8'h5;     
  CLK <= 1'b0;
  leds_r <= 8'h0;
end

//*************************** START PULSE ****************************
assign T = start;
assign R = start_f;
assign C = sys_clk;

// ************************** DEV_CLOCK ******************************
always @(posedge sys_clk)
  begin
    if(clk_count < clk_div)
      clk_count <= clk_count + 8'b1;    // For each system clock pulse, increment clock counter by 
    else
      begin
        clk_count <= 8'h0;        // When counter = clock divider, reset clock divider and flip device clock
        dev_clk <= ~dev_clk;
      end
  end
//********************************************************************


always @(dev_clk)
  begin
    if(Q && !dev_clk)          //Initialize
      begin
        dat_index <= 4'h0;
        MIOSIO <= 8'b0;    
        CSn <= 1'b0;
        CLK <= 1'b0;  
        packet_count[3:0] <= dat_size[3:0];
        turnaround_counter <= 2'b10;
        done <= 1'b0;
        leds_r <= 8'h1;
        start_f <= 1'b1;
      end  
      
    else if(!done)
      begin  
        CSn <= 1'b0;
        leds_r <= 8'h2;
        if(dev_clk)
          begin   
            CLK <= 1'b1;
            if(turnaround_counter == 2'b10)
              begin
                MIOSIO <= 8'b0;        // Load WRITE Command 
                turnaround_counter <= turnaround_counter - 1'b1;                    
              end
              
            else if(turnaround_counter == 2'b01)
              begin
                MIOSIO <= 8'bzzzzzzzz;  
                turnaround_counter <= turnaround_counter - 1'b1;
              end
                
            else if((turnaround_counter == 2'b00) && (packet_count != 1'b0)) 
              begin
                MIOSIO <= tx_data;            // Put data into MIOSIO  
                packet_count <= packet_count - 1'b1;  // Decrement packet_count
                dat_index <= dat_index + 1'b1;      // Index data by 1
              end          
          end
        
        else if(!dev_clk)
          begin  
            if(packet_count == 0)
              begin
                CLK <= 1'b0;
                done <= 1'b1;
              end
              
            else
              CLK <= 1'b0;  
          end
      end
      
    else if(done)
      begin
        leds_r <= 8'h4;
        CSn <= 1'b1;
        MIOSIO <= 8'bzzzzzzzz;
        if(!start)
          start_f <= 1'b0;
      end
  end    
endmodule


module pulse_latch(T, C, R, Q, Qn);

input wire T;
input wire R;
input wire C;
wire set;
wire res;
output wire Q;
output wire Qn;
      
wire sn;
wire rn;
  
assign res = ~set;
assign set = T & ~R; 
nand n1(sn, set, C);
nand n2(rn, res, C);
nand n3(Q, sn, Qn);
nand n4(Qn, Q, rn);
    
endmodule    
    

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Kyle G. wrote:
> some parts of it work and others don't.
Sounds very similar to "I'm using some unsynchronized asynchronous input 
signals in a FSM"....

But beside that its much more tricky. I usually do no Verilog, but this 
here looks badly wrong:
 always @(dev_clk) // some signals are missing here...
                   // and no posedge and no negedge...
                   // where did you find this coding style?
   begin
     if(Q && !dev_clk)    

     else if(!done)
     :
                turnaround_counter <= turnaround_counter - 1'b1; // This seems to be a combinatorial loop
     :
     else if(done)
     :
     :
     end
   end    
endmodule

To keep things short: you cannot control synthesis results with the 
sensitivity list. Instead in this list you MUST add all of the signals 
leading to a change of another signal. That much I know from VHDL. And 
it seems to be much the same with Verilog...
https://www.hdlworks.com/hdl_corner/verilog_ref/items/SensitivityList.htm

So try your simulation again with
 always @*  // this is a combinatoral block, inclue all singals to the sensitivity list
   begin
     if(Q && !dev_clk)    
     :

: Edited by Moderator
Author: Kyle G. (kyle_g)
Posted on:

Rate this post
0 useful
not useful
Yes, but I want the following to be evaluated on 'any' change of 
dev_clk.

Maybe my problems are from triggering on either edge? But this is how I 
was generating the CLK signal to drive the interface chip. I could 
divide this by two and trigger on 'posedge' only.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Kyle G. wrote:
> Yes, but I want the following to be evaluated on 'any' change of dev_clk.
Thats not possible!

> Maybe my problems are from triggering on either edge?
There is no "double edge triggered flipflop" inside an FPGA. You must 
multiply your clock by two with a PLL and work with only one clock edge 
(either rising or falling).

> But this is how I was generating the CLK signal to drive the interface
> chip. I could divide this by two and trigger on 'posedge' only.
Do that. And have a look what flipflops your FPGA contains...

> dev_clk <= ~dev_clk;
This is no good design practice. To get derived clocks (for bigger parts 
of the design) inside a FPGA you must use a clock manager and a clock 
net. Such derived clocks cannot be calculated reliably an they have big 
skew and jitter.

: Edited by Moderator
Author: Kyle G. (kyle_g)
Posted on:

Rate this post
0 useful
not useful
I tried to fix things but now something very strange is happening. If I 
leave
if(!st) st_f <= 1'b0;
 at the end, it evaluates
if (st_f == 1'b1)
 Which doesn't make sense. I'm supposedly setting it to 0 (when it is 
already 0). It does this even if 'st' is high or low. If I remove
if(!st) st_f <= 1'b0;
 it does not do this.


module top(pushbutton, MIOSIO_w, CLK_w, CSn_w, dev_clk, LEDS_OUT, pb, tp);
  output wire tp;
  input wire pushbutton;
  output wire [7:0]MIOSIO_w;
  output wire CLK_w;
  output wire CSn_w;
  output wire dev_clk;
  output wire pb;
  wire fpga_clock;
  reg [7:0] tx_data;
  reg [7:0] data_array [0:15];
  wire [3:0] i;
  
  reg [3:0]dat_size;  
  wire st_pulse;
  
  output wire [7:0]  LEDS_OUT;
    
  assign st_pulse = ~pushbutton;
  assign pb = st_pulse;  
    
  always @(posedge fpga_clock)
    begin
      tx_data <= data_array[i];
    end
    
  initial  
  begin
    dat_size = 2;
    data_array[0] = 8'h2A;
    data_array[1] = 8'h3B;
  end

  OSCH #(.NOM_FREQ("133.00")) rc_oscillator(.STDBY(1'b0), .OSC(fpga_clock));
  ft221x_write test(.sys_clk(fpga_clock), .tx_data(tx_data), .dat_size(dat_size), .dat_index(i), .st(st_pulse), .MIOSIO(MIOSIO_w), .CLK(CLK_w), .CSn(CSn_w), .dev_clk(dev_clk), .LEDS(LEDS_OUT), .test_pulse(tp));
  
endmodule


module ft221x_write(sys_clk, tx_data, dat_size, dat_index, st, MIOSIO, CLK, CSn, dev_clk, LEDS, test_pulse);
// Set CPOL = 0 in FTPROG

// Input wires from internal regs 
input wire st;
input wire sys_clk;
input wire [3:0] dat_size;  
input wire [7:0] tx_data;
output reg [3:0] dat_index;

output reg [7:0]MIOSIO;    // Wired to MIOSIO - TEST - might not be necessary
output reg CSn;          // Wired to CSn - TEST - might not be necessary
output reg CLK;        // Wired to CLK - TEST - might not be necessary


reg [7:0]leds_r;
output wire [7:0]LEDS;
output reg test_pulse;
// Used for clock divider timing
reg [7:0] clk_div;    
reg [7:0] clk_count;    
output reg dev_clk;
reg [1:0] turnaround_counter;
reg [3:0] packet_count;  

reg done;

reg st_f;

assign LEDS = ~leds_r;

initial
begin    
  st_f = 1'b0;
  done = 1'b1;
  dat_index = 4'h0;
  MIOSIO = 8'bzzzzzzzz;    
  turnaround_counter = 2'b10;
  CSn = 1'b1;
  dev_clk = 1'b1;
  clk_count = 8'h0;
  clk_div = 8'h20;     
  CLK = 1'b0;
  leds_r = 8'h0;
  test_pulse = 1'b0;
end

// ************************** DEV_CLOCK ******************************
always @(posedge sys_clk)
  begin
    if(clk_count < clk_div)
      clk_count <= clk_count + 8'b1;    // For each system clock pulse, increment clock counter by 
    else
      begin
        clk_count <= 8'h0;        // When counter = clock divider, reset clock divider and flip device clock
        dev_clk <= ~dev_clk;
      end
  end
//********************************************************************


always @(posedge dev_clk)
  begin
    if (st_f == 1'b1)          //Initialize
      begin
        dat_index <= 4'h0;
        MIOSIO <= 8'b0;    
        CSn <= 1'b0;
        CLK <= 1'b0;  
        packet_count[3:0] <= dat_size[3:0];
        turnaround_counter <= 2'b10;
        done <= 1'b0;
        leds_r <= 8'h1;
        st_f <= 1'b1;
        test_pulse <= 1'b1;
      end  
      
    else if (!done)
      begin  
        CSn <= 1'b0;
        leds_r <= 8'h2;
        
        if (dev_clk && (packet_count != 4'b0))
          begin  
            
            CLK <= ~CLK;
            
            if (!CLK && (turnaround_counter == 2'b10))
              begin
                MIOSIO <= 8'b0;        // Load WRITE Command 
                turnaround_counter <= turnaround_counter - 1'b1;                    
              end
              
            else if (!CLK && (turnaround_counter == 2'b01))
              begin
                MIOSIO <= 8'bzzzzzzzz;  
                turnaround_counter <= turnaround_counter - 1'b1;
              end
                
            else if (!CLK && (turnaround_counter == 2'b00) && (packet_count != 4'b0)) 
              begin
                MIOSIO <= tx_data;            // Put data into MIOSIO  
                packet_count <= packet_count - 4'b1;  // Decrement packet_count
                dat_index <= dat_index + 1'b1;      // Index data by 1
              end          
          end
        
        else if (CLK && packet_count == 4'h0)
          begin
            CLK <= 1'b0;
            done <= 1'b1;
          end
      end
      
    else if (done)
      begin
        leds_r <= 8'h4;
        CSn <= 1'b1;
        MIOSIO <= 8'bzzzzzzzz;
        if(!st)
            st_f <= 1'b0;
      end
  end    

endmodule
    

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.