Skoll – Xilinx™ Kintex™-7 USB Ready To Go FPGA Module
Ok, we have a module and tools ready now, let’s try to run a simulation on the module and see if it works as expected. In order to simulate the module, we need to give some input to the module, how we do that? The answer is, we need to create a test bench! The test bench will generate the necessary inputs for the module under analysis (Here “myModule”). A test bench is nothing but another Verilog module which generates some signals and feeds it to the module under test. During simulation, the test bench should be a “top module” (top-level module) with no I/O ports. But when it comes to implementation on real FPGA, the “top module” can have I/O ports and test benches won’t be the top modules there (we will talk about this in detail later). So here goes the test bench code.
module myModule_tb(); wire out; reg clock; always begin #1 clock =!clock; end initial begin //Initialize clock clock = 0; //End simulation #10 $finish; end myModule notGate(clock, out); endmodule
Let me break this down for you.
The test bench is just another module, with no I/O ports as I mentioned earlier. I have created a wire named “out” and a reg named “clock”. We will create a clock on reg “clock” by periodically inverting it and feed it to the input (port A) of myModule. The wire “out” is connected to the output port (port B) of myModule. The result should appear on the wire “out” in the simulation.
The “always” block is something worth special mention here. As the name implies, “always” block will keep on executing as long as the simulation is running. In real-world designs, “always” blocks are a little more complicated with sensitivity lists etc…. But for this simulation, the simplest form of “always” should suffice. I’ll discuss this in details in later chapters.
In the “always” block the reg “clock” is inverted after every one-time unit delay. The symbol # is a way to specify a delay in Verilog. So the always block executes always, and inside the block, “clock” is inverted continuously so that the waveform on clock looks like a square wave. Remember that # symbol is not a synthesizable element. We have to find some other way if delay needed in our design when we synthesize the code. But it works just fine for simulation.
The next block is an initial block. As its name suggests, this block will be executed only once at time t = 0. So anything that we need to initialize should go here. Initial block also is usually used only in test benches. Initial blocks are rarely used in synthesizable code, instead, reset logic is created if initialization is required. We initialize the reg “clock” to zero. This is very important. If we don’t initialize a register, its value is considered as unknown and no matter how many times an unknown is inverted, the result will always be unknown. That is, if we leave “clock” uninitialized, “clock” won’t be generated. The last part of the initial block is the $finish directive. The $finish directive is placed after a 10-time unit delay, this means after simulating the design for 10-time units, stimulator will stop running. All functions start with the $ symbol is called tasks. Tasks are merely commands to the simulator, they don’t alter the circuit behavior.
Last but not the least, the module instantiation. The statement “myModule notGate(clock, out)” creates an instance of the module “myModule” with name “notGate”. You can create as many instances as you want from a module. One really important thing here is the wiring. If you look at the code, you can see the reg “clock” placed as the first parameter and the wire “out” is placed as the second...
Read more »