Tapeout practice labs
Build it. Simulate it. Inspect the signals.
A browser workspace for small Verilog and SystemVerilog designs. Start with a working example, change the design, and follow what happens in a real waveform.
Practice runs do not award course grades or credentials. Simulator support is limited to the qualified features in these examples.
Choose a starter
Counter: RTL to layout
Build a small chip layout from synthesizable Verilog. Use the physical-flow panel with clock clk and period 100 ns. This starter has no simulation testbench.
- Follow synthesis, placement and routing
- Inspect the layout and bundled DRC/LVS results
- Download the generated GDS, DEF and reports
Explore source files
counter.v
module counter (
input wire clk,
input wire rst,
input wire en,
output reg [7:0] q
);
always @(posedge clk) begin
if (rst)
q <= 8'h00;
else if (en)
q <= q + 8'h01;
end
endmodule
Checking sign-in…Clocked counter
Observe reset and count transitions, then change the counter width and check rollover.
- Explain when a sequential output changes
- Read reset and clock edges in a waveform
- Make a self-checking test fail and repair it
Explore source files
counter.v
module counter(input clk, input reset, output reg [3:0] count);
always @(posedge clk) begin
if (reset) count <= 0;
else count <= count + 1;
end
endmodule
tb.v
`timescale 1ns/1ps
module tb;
reg clk = 0;
reg reset = 1;
wire [3:0] count;
counter dut(clk, reset, count);
always #5 clk = ~clk;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb);
#11;
if (count !== 0) $fatal(1, "reset failed");
reset = 0;
#40;
if (count !== 4) $fatal(1, "expected four increments");
$display("Counter checks passed");
$finish;
end
endmodule
Checking sign-in…Two-entry FIFO
Write two values, observe full and empty, and check that reads preserve order.
- Follow FIFO occupancy through writes and reads
- Check full and empty boundaries
- Compare expected data with the waveform
Explore source files
fifo.v
module fifo(input clk, input reset, input wr, input rd,
input [7:0] din, output reg [7:0] dout,
output full, output empty);
reg [7:0] memory [0:1];
reg write_ptr, read_ptr;
reg [1:0] used;
wire push = wr && !full;
wire pop = rd && !empty;
assign full = (used == 2);
assign empty = (used == 0);
always @(posedge clk) begin
if (reset) begin
write_ptr <= 0; read_ptr <= 0; used <= 0; dout <= 0;
end else begin
if (push) begin memory[write_ptr] <= din; write_ptr <= ~write_ptr; end
if (pop) begin dout <= memory[read_ptr]; read_ptr <= ~read_ptr; end
case ({push, pop})
2'b10: used <= used + 1;
2'b01: used <= used - 1;
default: used <= used;
endcase
end
end
endmodule
tb.v
`timescale 1ns/1ps
module tb;
reg clk = 0, reset = 1, wr = 0, rd = 0;
reg [7:0] din = 0;
wire [7:0] dout;
wire full, empty;
fifo dut(clk, reset, wr, rd, din, dout, full, empty);
always #5 clk = ~clk;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb);
#11; if (!empty) $fatal(1, "reset must empty the FIFO");
reset = 0; wr = 1; din = 8'h31;
#10; din = 8'h72;
#10; if (!full) $fatal(1, "two writes must fill FIFO");
wr = 0; rd = 1;
#10; if (dout !== 8'h31) $fatal(1, "first value mismatch");
#10; if (dout !== 8'h72 || !empty) $fatal(1, "second value or empty mismatch");
rd = 0;
$display("FIFO checks passed");
$finish;
end
endmodule
Checking sign-in…