| import os | |
| import subprocess | |
| if not os.path.exists("work_ff"): | |
| os.mkdir("work_ff") | |
| modules = [] | |
| with open("../cells_ff.vh", "r") as f: | |
| with open("work_ff/cells_ff_gate.v", "w") as g: | |
| for line in f: | |
| if not line.startswith("module"): | |
| g.write(line) | |
| continue | |
| else: | |
| spidx = line.find(" ") | |
| bridx = line.find("(") | |
| modname = line[spidx+1 : bridx] | |
| g.write("module %s_gate" % modname) | |
| g.write(line[bridx:]) | |
| inpidx = line.find("input ") | |
| outpidx = line.find(", output") | |
| modules.append((modname, [x.strip() for x in line[inpidx+6:outpidx].split(",")])) | |
| with open("work_ff/testbench.v", "w") as f: | |
| print(""" | |
| `timescale 1ns/ 1ps | |
| module testbench; | |
| reg pur = 0, clk, rst, cen, d; | |
| // Needed for Diamond sim models | |
| GSR GSR_INST (.GSR(1'b1)); | |
| PUR PUR_INST (.PUR(pur)); | |
| initial begin | |
| $dumpfile("work_ff/ffs.vcd"); | |
| $dumpvars(0, testbench); | |
| #5; | |
| pur = 1; | |
| #95; | |
| repeat (2500) begin | |
| {clk, rst, cen, d} = $random; | |
| #10; | |
| check_outputs; | |
| #1; | |
| end | |
| $finish; | |
| end | |
| """, file=f) | |
| for modname, inputs in modules: | |
| print(" wire %s_gold_q, %s_gate_q;" % (modname, modname), file=f) | |
| portconns = [] | |
| for inp in inputs: | |
| if inp in ("SCLK", "CK"): | |
| portconns.append(".%s(clk)" % inp) | |
| elif inp in ("CD", "PD"): | |
| portconns.append(".%s(rst)" % inp) | |
| elif inp == "SP": | |
| portconns.append(".%s(cen)" % inp) | |
| elif inp == "D": | |
| portconns.append(".%s(d)" % inp) | |
| else: | |
| assert False | |
| portconns.append(".Q(%s_gold_q)" % modname) | |
| print(" %s %s_gold_i (%s);" % (modname, modname, ", ".join(portconns)), file=f) | |
| portconns[-1] = (".Q(%s_gate_q)" % modname) | |
| print(" %s_gate %s_gate_i (%s);" % (modname, modname, ", ".join(portconns)), file=f) | |
| print("", file=f) | |
| print(" task check_outputs;", file=f) | |
| print(" begin", file=f) | |
| print(" if (%s_gold_q != %s_gate_q) $display(\"MISMATCH at %%1t: %s_gold_q=%%b, %s_gate_q=%%b\", $time, %s_gold_q, %s_gate_q);" % | |
| (modname, modname, modname, modname, modname, modname), file=f) | |
| print(" end", file=f) | |
| print(" endtask", file=f) | |
| print("endmodule", file=f) | |
| diamond_models = "/usr/local/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u" | |
| subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim.v", "work_ff/testbench.v"]) | |
| subprocess.call(["vvp", "work_ff/testbench"]) |