element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
FPGA
  • Technologies
  • More
FPGA
Forum Connecting Verilog to Synthesis
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join FPGA to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Verified Answer
  • Replies 12 replies
  • Answers 2 answers
  • Subscribers 546 subscribers
  • Views 2845 views
  • Users 0 members are here
Related

Connecting Verilog to Synthesis

mraureliusr
mraureliusr over 11 years ago

Hey everyone! Wish I had seen this group earlier.

 

I'm hoping there's a few here who are familiar with the Xilinx ISE. I'm finally making a concerted effort to learn Verilog and this time around I'm doing well. I'm grasping the language concepts well, and am enjoying the book I picked up from the local University library (public library is a bit short on HDL books!) called "Verilog for Digital Design" written by Frank Vahid and Roman Lysecky. Make sure to check for the 2002 edition, there are older versions as well. This book is the perfect blend of theory and practical code writing.

 

Anyway, I wanted to try implementing a simple design of my own, essentially recreating the functionality of four 74193 up/down binary counters. The inputs are four buttons, up, down, load and store. The load and store buttons control signals for a later stage of the design.

 

I wrote the counter module, then created a top level module and instantiated the     counter module. I simulated it with a simple test bench and it worked!! Amazing!

 

However, now I'm trying to implement it in my Spartan-3E FPGA and I'm having trouble figuring out the hierarchy of a typical design. Clearly the top level module interfaces with the actual pins, and then passes these states to the instantiated module. But how do I pick which pins connect to the top level module? I see that PlanAhead seems to implement this stage of the design but I'm confused on how to put it all together. I'm also having trouble connecting the counter module ports to the top level module. It keeps giving me errors for the output bus, saying something like it's not a proper lvalue? The counter module has the counter output declared as an output reg[15:0] ... is that incorrect? The top level module also has the actual output declared as an output reg, is it improper to commect these types together? I figured within the counter module that the output should be a reg ad not a wire, because it needs to hold its value. Plus the output needs to be manipulated directly and it seems a reg was the easiest way to do this


Perhaps these questions will be answered later in the book but the ISE/Xilinx specific problems won't be addressed as the author uses different software and never directly talks about specific brands. He does focus on both simulation and synthesis though, which is what I was looking for. Most books on Verilog place a heavy focus on simulation, and while I've discovered how useful simulation is, I have this Xilinx dev board that I want to play/learn with!


Thanks everyone for reading all that. image Will be happy to share more as I learn more. If it helps I can post my code here.

  • Sign in to reply
  • Cancel

Top Replies

  • johnbeetem
    johnbeetem over 11 years ago +1 suggested
    I've never used PlanAhead. I always use a User Constraint File (.ucf) to define the pinout. The easiest way is to start with a working .ucf as a template, and then modify it. For example, here is the UCF…
  • johnbeetem
    0 johnbeetem over 11 years ago

    I've never used PlanAhead.  I always use a User Constraint File (.ucf) to define the pinout.  The easiest way is to start with a working .ucf as a template, and then modify it.  For example, here is the UCF file for the Papilio One FPGA board from Gadget Factory: http://forum.gadgetfactory.net/index.php?/files/file/2-papilio-one-generic-ucf/

     

    Here's a simple 4-bit up-counter:

    module UpCounter(Pclk, K);

    input    Pclk;            // 32 MHz Papilio clock.

    output    [3:0] K;        // 4-bit counter;

    reg        [3:0] K;

     

    always @(posedge Pclk)

            K <= K + 1;

    endmodule 

     

    This is the root module, and the pins Pclk and K[3:0] are the external pins.

     

    Once I have this in a .v file, I create a UCF with the same module name, UpCounter.ucf.

    Here are the relevant lines:

     

    NET Pclk  LOC="P89"  | IOSTANDARD=LVCMOS33 | PERIOD=31.25ns;

    NET K<0> LOC="P58" | IOSTANDARD=LVTTL;

    NET K<1> LOC="P41" | IOSTANDARD=LVTTL;

    NET K<2> LOC="P34" | IOSTANDARD=LVTTL;

    NET K<3> LOC="P25" | IOSTANDARD=LVTTL;

     

    I use the notation K<i> to reference bit i of bus K.

     

    I typically use ISE Webpack 12.4, with XST for synthesis.

     

    ISE has a tool for interactively editing the pinout, but I find .ucf quicker since you can use standard text editor copy/paste and replacement operations.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • mraureliusr
    0 mraureliusr over 11 years ago in reply to johnbeetem

    Awesome -- thanks for the info on the .ucf file. I found that the dev board I have came with .ucf files so I can import those and find what pins are connected to what.

     

    Here's the real problem I'm having, I'll paste my code below. I have a main.v, which does nothing else (at this point) but instantiate the counter, which is a module from counter.v. When trying to connect the ports, I keep getting the errors:

    ERROR:HDLCompilers:246 - "main.v" line 32 Reference to vector reg 'addr_Out' is not a legal net lvalue

    ERROR:HDLCompilers:102 - "main.v" line 32 Connection to output port 'count_Out' must be a net lvalue

     

    Here's the main.v:

     

    module main(

      input button_Up,

        input button_Down,

        input button_Reset,

        input button_Load,

        input button_Store,

        output reg [15:0] addr_Out,

        output reg [7:0] data_Out,

      input output_Enable

      );

     

    counter TestCount(button_Up, button_Down, button_Reset, output_Enable, addr_Out);

     

    endmodule

     

    And here's the counter.v:

     

    module counter(

        input b_Up,

        input b_Down,

        input Rst,

        input OE,

        output reg[15:0] count_Out

        );

     

     

    always @(posedge Rst)

      count_Out = 16'h0000;

     

    always @(posedge b_Up) begin

      if(count_Out == 16'hFFFF)

      count_Out <= 16'h0000;

      else

      count_Out <= count_Out + 1'b1;

      end

     

    always @(posedge b_Down) begin

      if(count_Out == 16'h0000)

      count_Out <= 16'hFFFF;

      else

      count_Out <= count_Out - 1'b1;

     

    end

    endmodule

     

    Sorry if the formatting got messed up a little. I know the counter module works correctly (at least in simulation) because I did a basic testbench with it. The main.v is declared as the 'top module'. I'm just wondering how I pass the connections to the outside world through the main.v into the instance of the counter. Or is there a more 'proper' way to do this? The examples I've seen so far seem to hint that you write all your module in a separate file, then instantiate them in the main module, and do all the connections between them as instances. This seems the 'neatest' way to do it (at least in my mind) however this might be completely wrong. I haven't gotten through the whole book yet, so there's a decent chance I'll find more information about this, but I'm just curious how you normally implement a design with multiple modules (which this will eventually have -- there will be a 7-segment display driver, and a couple other small glue logic modules).

     

    Thanks again John! I really appreciate the help!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • mraureliusr
    0 mraureliusr over 11 years ago in reply to mraureliusr

    Oops, the

     

    always @(posedge Rst)

      count_Out <= 16'h0000;

     

    should have been a non-blocking assignment, like I just put above.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • mraureliusr
    0 mraureliusr over 11 years ago in reply to mraureliusr

    I think I may have solved it. I should have caught that the addr_Out can't be a reg, as it is being driven by a port, so it has to be a wire. Also, the errors I was getting after changing it to a wire was because the count_Out in counter.v was being driven by multiple always statements (that's me thinking sequentially instead of parallel, years of C...)

     

    So I changed the counter to have a Clk, and did all the logic on posedge Clk like so:

     

    module counter(

      input Clk,

        input b_Up,

        input b_Down,

        input Rst,

      input OE,

        output reg[15:0] count_Out

        );

     

     

    always @(posedge Clk) begin

     

     

       if(Rst == 1)

      count_Out[15:0] <= 16'h0000;

     

      if(b_Up == 1) begin

      if(count_Out[15:0] == 16'hFFFF)

      count_Out[15:0] <= 16'h0000;

      else

      count_Out[15:0] <= count_Out[15:0] + 1'b1;

      end

     

      if(b_Down == 1) begin

      if(count_Out[15:0] == 16'h0000)

      count_Out[15:0] <= 16'hFFFF;

      else

      count_Out[15:0] <= count_Out[15:0] - 1'b1;

      end

     

    end

    endmodule

     

     

    Now I no longer get errors, but I do get a PILE of warnings... Clearly I'm doing something wrong at the hierarchical level, things aren't acting the way I think they are... I'll keep reading and/or wait for expert advice!

     

    I also tried adding the [15:0] to every count_Out as I was getting:

     

    WARNING:Xst:1306 - Output <addr_Out<15:1>> is never assigned.

    WARNING:Xst:1305 - Output <addr_Out<0>> is never assigned. Tied to value 0.

    WARNING:Xst:1290 - Hierarchical block <TestCount> is unconnected in block <main>.

       It will be removed from the design.

    WARNING:Xst:2677 - Node <TestCount/count_Out_15> of sequential type is unconnected in block <main>.

     

    Oh man... transitioning to Verilog is harder than I thought. Gotta love it though, at least I'm learning a lot, and fast!

    Thanks for a third time John! Hope I'm not driving you crazy.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • michaelkellett
    0 michaelkellett over 11 years ago in reply to johnbeetem

    @ Alexander - good advice from John - I'm going to add some lateral comments.

     

    I haven't used Xilinx tools for years having moved to Lattice (mainly because I see them as being long term interested in low cost FPGAs and smaller users) - Lattice do have quite a few low cost (and low power) parts in resaonable packages (and some really nice low power parts in difficult-to-use-at-home BGA packages.)

    The Lattice toolset includes Aldec HDL with a nice block diagram editor which takes care of all the awful tedium of connecting inputs and outputs of blocks.

     

    Finally - before you invest too much time in Verilog at least take a look at VHDL - I won't say that one is better than the other but I certainly find that VHDL suits my way of working far better than Verilog does. (I think John finds the opposite image)

     

    MK

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • johnbeetem
    0 johnbeetem over 11 years ago in reply to mraureliusr

    A few things:

     

    1.  Since count_Out is declared "reg" in module "counter", the bus it connects to in the root module should be declared as a wire.  Otherwise you're going through two regs, at least that's how I understand it.

     

    2.  I've never used included "input", "output", and "reg" in a "module" declaration, e.g., module counter(input Clk, input b_Up, input b_Down, input Rst, input OE, output reg[15:0] count_Out);  I've always listed the I/Os on separate lines, like the examples at Wikipedia's Verilog page: http://en.wikipedia.org/wiki/Verilog#Example

     

    This is probably because I learned Verilog in 2000 so I pre-date the 2001 and 2005 improvements.

     

    3.  From your warnings, it looks like module main's connections to "counter" aren't compatible, so XST is tossing everything away.  Make sure the connections are in the correct order and that directions and bus widths are compatible.

     

    4.  Follow the correct template for registers.  These are cleverly hidden in ISE.  In ISE 12.4, go to the Edit menu and select Language Templates.  Then click your way down the hierarchy to Synthesis Constructs / Always / Posedge Clocked and ISE shows you the templates for various types of flip-flops and latches, all of which can be multiple bit.  For example, here's a positive edge-triggered register with active-high async reset and active-high clock enable:

     

    always @(posedge <clock> or posedge <reset>)

          if (<reset>) begin

             <signal> <= 0;

          end else if (<clock_enable>) begin

             <signal> <= <clocked_value>;

          end

     

    If you follow this template, XST will recognize that you want that kind of register and generate the correct logic.  This is how I design with Verilog: I imagine the logic I want, and then write the code that XST recognizes for generating that logic.  It's very much like the early days of C compilers when you could get much better code if you first imagined the assembly language and then wrote code that would help the compiler get there.

     

    In your case, I think your Rst is confusing XST since it's not following the if-then-else structure of the template.

     

    5.  There's no need to specify count_Out[15:0] each time.  If you say count_Out by itself, it's the whole 16-bit register.

     

    6.  If you increment the value of count_Out, you don't need to worry about wrapping the value.  Just write count_Out+1 and it will produce a 17-bit value, which if you assign back to count_Out XST will drop the carry out.

     

    7.  Now that you have a common clock, here's an easy way to update the up/down counter:

     

    count_Out <= count_Out + b_Up - b_Down;

     

    So now you can do the async reset and counter update like this:

     

    always @(posedge Clk or posedge Rst)

      if (Rst) count_Out <= 0;

      else count_Out <= count_Out + b_Up - b_Down;

     

    This is a fine example of how Verilog can create compact source code.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Reject Answer
    • Cancel
  • mraureliusr
    0 mraureliusr over 11 years ago

    Dear God, this is driving me insane.

     

    John -- your advice is excellent! Thanks for the tips. I'm trying to implement your suggestion but I keep getting the same error:

    The logic for <count_Out> does not match a known FF or Latch template. The description style you are using to describe a register or latch is not supported in the current software release.

     

    ARGH!!! I really do not understand what I'm doing wrong. I'm having a hard time wrapping my head around certain concepts. Here's the block it's having trouble with. I want to note that I've tried implementing this a few different ways, for example creating an 'internal' clock that gets flipped on the negedge of b_Up, b_Down, Rst, and then having a separate always block for that 'internal' clock to handle the actual changes to count_Out. This made sense to me, but apparently not to XST. Clearly I'm doing something wrong...

    Anyway, here's what I'm back to now: (I've modified the ports to have the inputs/outputs declared afterward, though I think that's just a style choice as it's never caused any problems)

     

    module counter16(Clk, b_Up, b_Down, Rst, count_Out);

      input Clk, b_Up, b_Down, Rst;

      output reg[15:0] count_Out;

     

    always @(negedge b_Up or negedge b_Down or negedge Rst) begin

      if(Rst == 0) begin

      count_Out <= 16'h0000;

      end else begin

      count_Out <= count_Out + b_Up - b_Down;

      end

    end

    endmodule

     

    (EDIT: I've also used just if(!Rst) begin ... doesn't seem to make any difference, and I suspect !Rst is proper)

    I mean, what could be simpler? On the falling edge of any of those three signals, do that very simple thing. That's it! But apparently count_Out[15:0] <= 16'h0000; does not match a known flip flop or latch template.............. WHAT? Isn't that the whole point of Verilog, that you can describe circuits that don't use templates all the time? Man, this one has my head spinning. I think I should ignore what the error actually means and just try and figure out how to fix it. I've read and re-read the chapters that deal with the above concepts, but I don't see what I'm doing wrong....

     

    Sorry to burden you all with my problems, hopefully I'm not too much of a pain! image In a lot of ways, Verilog is a lot easier than I thought (though I won't say it's easy!!). However, it's the little syntactical things (like with any language) that really get me at first. Once you learn it, it's all second nature, which is how I am with C now that I've used it for so long. But this is taking a bit longer to sink in than I would have liked.

     

    Even if you can't describe the problem, perhaps you can just give me a few keywords to search and I can Google/check the index of the multiple Verilog books I currently have to see if the concept is covered well. I'm understanding the difference between structural and behavioural code well, but the difference between behavioural and combinational is escaping me, and I have a feeling this is at the root of my above errors.

     

    Thanks again for your patience everyone. Soon enough hopefully I'll be answering the newbie questions!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • johnbeetem
    0 johnbeetem over 11 years ago in reply to mraureliusr

    Alexander Rowsell wrote:

     

    Anyway, here's what I'm back to now: (I've modified the ports to have the inputs/outputs declared afterward, though I think that's just a style choice as it's never caused any problems)

     

    module counter16(Clk, b_Up, b_Down, Rst, count_Out);

      input Clk, b_Up, b_Down, Rst;

      output reg[15:0] count_Out;

     

    always @(negedge b_Up or negedge b_Down or negedge Rst) begin

      if(Rst == 0) begin

      count_Out <= 16'h0000;

      end else begin

      count_Out <= count_Out + b_Up - b_Down;

      end

    end

    endmodule

     

    I think the problem is that XST wants each register to have a single clock.  It doesn't know what to do with multiple clocks, since if you look at the Xilinx cell structure each FF has only one clock.

     

    So you need something like:

     

    always @(posedge Clk or negedge Rst) begin

      if(Rst == 0) begin  // If Rst = 0, asynchronously reset count_Out.

      count_Out <= 16'h0000;

      end else begin  // If Rst = 1, update count_Out on the rising edge of Clk.

      count_Out <= count_Out + b_Up - b_Down;

      end

     

    When you use counter16, connect Clk to a fixed clock source.  Connect b_Up and b_Down to combinational inputs.  Alternatively, you can create logic that detects changes to b_Up and b_Down to create clock pulses, but this gets into asynchronous sequential logic which is not usually what you want to do with FPGAs.  FPGAs work best with a single clock that is distributed throughout the chip, with all combinational inputs synchronized to that clock so they have clean inputs and don't cause metastability.  This is particularly true with push-button inputs, which usually need to be debounced. 

     

    Regarding Verilog in general:  If I remember my history correctly, Verilog began as a language for producing test vectors and expected results for testing ICs.  Using Verilog as a synthesis language came later.  If you don't know how XST or other synthesizers work, it's easy to write Verilog that simulates fine but can't be synthesized.  I restrict myself to a subset of Verilog that works for the way I do design.  I don't know a reference book for this -- I have the advantage that I came to FPGAs from an electronic computer-aided design background, so I already had a good idea of what was possible and practical, and then added experience.

     

    Marketing would like you to think that you can write any Verilog you like and XST will magically create a wonderful FPGA.  This has not been my experience.  You must copy the templates carefully.  As I think I said above, my approach is to visualize the logic I want to produce, and then write the Verilog accordingly.  This creates the overall register-transfer structure.  XST does a great job of logic minimization given this structure.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • mraureliusr
    0 mraureliusr over 11 years ago in reply to johnbeetem

    Okay, thanks again John -- that helped clarify a few things. The book I'm reading emphasizes the difference between synthesizable and simulatable code quite strongly, so I understand that many things can't be synthesized. I just wasn't understanding that each always statement usually expects just one clock and an async reset.

    The problem is, if I make the block always @(posedge Clk) then any time you push the button it counts up hundreds of thousands of times in the space of milliseconds -- I just want it to increment once for each push. I was looking at the switches and yes, they do have some bounce on them, which is a pain but I'm going to be using debounced switches in the final design.

    I was thinking of doing what you mentioned, creating an artificial clock pulse from the buttons and then feeding that to the module. I guess this has to be done outside of the module (otherwise it doesn't synthesize for me), and that makes sense.

     

    Thank you so much for your advice! I'm going to keep at it and see what happens.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • johnbeetem
    0 johnbeetem over 11 years ago in reply to mraureliusr

    Alexander Rowsell wrote:

     

    The problem is, if I make the block always @(posedge Clk) then any time you push the button it counts up hundreds of thousands of times in the space of milliseconds -- I just want it to increment once for each push. I was looking at the switches and yes, they do have some bounce on them, which is a pain but I'm going to be using debounced switches in the final design.

    One way to handle the Up and Down inputs is to sample them every 10 msec or so and compare the new sample to the previous sample, which you stored in a flip-flop.  If the new value is ON and the old value is OFF, then update your 16-bit counter.

     

    Yes, you need a lot of counter bits to take your master clock (typically 30 MHz on most dev boards) down to 100 Hz, but in a serious design you often need those lower-frequency clocks for activity LEDs and other human-speed I/O.  Now when I say "lower-frequency clock", I really mean a low-duty-cycle logic signal clocked by the master clock.  The logic signal enables register updates, also clocked by the same master clock.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube