3

Quick question that I am likely missing an obvious solution for. I have a relatively simple Verilog design which I'll call taco, where the top-level design entity is taco_top (because I'm writing this before lunch).

It's the only module in the design with all relevant logic contained in taco_top. The design targets the ever-popular Lattice iCE40 UltraPlus FPGA. In taco_top, I'm using the iCE40's low-frequency and high-frequency oscillators to generate 10kHz and 6MHz clocks. There are no external clocks in the design; taco_top's ports all correspond to physical I/O pins on the FPGA and the clocks I need are sourced from these internal oscillators.

In simulation, I want to replace these with simple dummy clocks with the appropriate period since I can't simulate the LFOSC and HFOSC primitives. So, I've created the appropriate simulation only clocks and kludged them into my design with `define which is not particularly elegant.

In writing a testbench, I would normally instantiate my taco_top module and feed it the appropriate stimuli, but those sim clocks are buried inside / not exposed at the top-level.

What's an elegant way to structure my design such that I can easily feed those clocks in simulation and maintain their behavior in the synthesized design?

Krunal Desai
  • 6,246
  • 1
  • 21
  • 32

1 Answers1

1

In our designs, we normally divide the design into two layers, like an onion. We call the outer layer the "pad ring" (e.g., taco_io), and it contains everything that's specific to the physical interfaces of the chip — I/O buffers, on-chip clocks, etc.

The inner layer is the "core" layer, and contains all of the actual application functionality. In other words, the functional hierarchy is implemented with taco_core as its top level. The functional simulation testbench instantiates taco_core only, where it has access to drive those clocks you're talking about.

Your taco_top is used for synthesis only. It just instantiates two modules: taco_io and taco_core and connects them together. It also connects taco_io to the actual external pins of the device.

Note that you could put all of those I/O bits right into taco_top, but we find that it's generally cleaner to put them in their own submodule (taco_io).

Dave Tweed
  • 168,369
  • 17
  • 228
  • 393