Compare commits
6
Commits
e71d8eb717
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15985de500 | ||
|
|
28af588549 | ||
|
|
b3637d6d76 | ||
|
|
6a96af7ad2 | ||
|
|
a0491ca1c6 | ||
|
|
c08ef2102f |
No files matched your search
@@ -1,3 +0,0 @@
|
||||
[submodule "7Segment_Lattice_ice40_UltraPlus"]
|
||||
path = 7Segment_Lattice_ice40_UltraPlus
|
||||
url = https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/7Segment_Lattice_ice40_UltraPlus
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
module counter_assertion(clk, rst, data, updown, load, count);
|
||||
|
||||
input logic clk, rst;
|
||||
input logic updown, load;
|
||||
input logic [3:0] data, count;
|
||||
|
||||
|
||||
property reset_prpty;
|
||||
@(posedge clk) rst |=> (count == 4'b0);
|
||||
endproperty
|
||||
|
||||
sequence up_seq;
|
||||
!load && updown;
|
||||
endsequence
|
||||
|
||||
sequence down_seq;
|
||||
!load && !updown;
|
||||
endsequence
|
||||
|
||||
property up_count_prpty;
|
||||
@(posedge clk) disable iff(rst)
|
||||
up_seq |=> (count == ($past(count, 1) + 1'b1));
|
||||
endproperty
|
||||
|
||||
property down_count_prpty;
|
||||
@(posedge clk) disable iff(rst)
|
||||
down_seq |=> (count == ($past(count, 1) - 1'b1));
|
||||
endproperty
|
||||
|
||||
property count_Fto0_prpty;
|
||||
@(posedge clk) disable iff(rst)
|
||||
(!load && updown) && (count == 4'hF) |=> (count == 4'b0);
|
||||
endproperty
|
||||
|
||||
property count_0toF_prpty;
|
||||
@(posedge clk) disable iff(rst)
|
||||
(!load && !updown) && (count == 4'b0) |=> (count == 4'hF);
|
||||
endproperty
|
||||
|
||||
property load_prpty;
|
||||
@(posedge clk) disable iff(rst)
|
||||
load |=> (count == $past(data, 1));
|
||||
endproperty
|
||||
|
||||
|
||||
|
||||
|
||||
RST: assert property (reset_prpty);
|
||||
UP_COUNT: assert property (up_count_prpty);
|
||||
DOWN_COUNT: assert property (down_count_prpty);
|
||||
F2O: assert property (count_Fto0_prpty);
|
||||
O2F: assert property (count_0toF_prpty);
|
||||
LOAD: assert property (load_prpty);
|
||||
|
||||
endmodule
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
class counter_env;
|
||||
|
||||
virtual counter_if.WR_BFM wr_if;
|
||||
virtual counter_if.WR_MON wrmon_if;
|
||||
virtual counter_if.RD_MON rdmon_if;
|
||||
|
||||
mailbox #(counter_trans) gen2wr = new;
|
||||
mailbox #(counter_trans) wrmon2rm = new;
|
||||
mailbox #(counter_trans) rm2sb = new;
|
||||
mailbox #(counter_trans) rdmon2sb = new;
|
||||
|
||||
counter_gen gen_h;
|
||||
counter_wr_bfm wr_h;
|
||||
counter_wr_mon wrmon_h;
|
||||
counter_rd_mon rdmon_h;
|
||||
counter_rm rm_h;
|
||||
counter_sb sb_h;
|
||||
|
||||
function new( virtual counter_if.WR_BFM wr_if,
|
||||
virtual counter_if.WR_MON wrmon_if,
|
||||
virtual counter_if.RD_MON rdmon_if);
|
||||
this.wr_if = wr_if;
|
||||
this.wrmon_if = wrmon_if;
|
||||
this.rdmon_if = rdmon_if;
|
||||
endfunction
|
||||
|
||||
|
||||
task build();
|
||||
gen_h = new(gen2wr);
|
||||
wr_h = new(wr_if, gen2wr);
|
||||
wrmon_h = new(wrmon_if, wrmon2rm);
|
||||
rdmon_h = new(rdmon_if, rdmon2sb);
|
||||
rm_h = new(wrmon2rm, rm2sb);
|
||||
sb_h = new(rm2sb, rdmon2sb);
|
||||
endtask
|
||||
|
||||
task reset();
|
||||
@(wr_if.wr_cb);
|
||||
wr_if.wr_cb.rst <= 1;
|
||||
@(wr_if.wr_cb);
|
||||
@(wr_if.wr_cb);
|
||||
@(wr_if.wr_cb);
|
||||
@(wr_if.wr_cb);
|
||||
@(wr_if.wr_cb);
|
||||
wr_if.wr_cb.rst <= 0;
|
||||
|
||||
endtask
|
||||
|
||||
task start();
|
||||
gen_h.start();
|
||||
wr_h.start();
|
||||
wrmon_h.start();
|
||||
rdmon_h.start();
|
||||
rm_h.start();
|
||||
sb_h.start();
|
||||
endtask
|
||||
|
||||
task stop();
|
||||
wait(sb_h.DONE.triggered);
|
||||
endtask
|
||||
|
||||
task run();
|
||||
reset();
|
||||
start();
|
||||
stop();
|
||||
sb_h.report();
|
||||
endtask
|
||||
|
||||
endclass: counter_env
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
class counter_gen;
|
||||
|
||||
counter_trans trans_h;
|
||||
counter_trans trans2wr_h;
|
||||
|
||||
mailbox #(counter_trans) gen2wr;
|
||||
|
||||
function new(mailbox #(counter_trans) gen2wr);
|
||||
this.gen2wr = gen2wr;
|
||||
trans_h = new;
|
||||
endfunction
|
||||
|
||||
virtual task start();
|
||||
fork
|
||||
begin
|
||||
trans_h.trans_id++;
|
||||
trans_h.load = 1;
|
||||
trans_h.data = 0;
|
||||
trans2wr_h = new trans_h;
|
||||
gen2wr.put(trans2wr_h);
|
||||
|
||||
for(int i = 0; i < (no_of_transaction - 1); i++)
|
||||
begin
|
||||
trans_h.trans_id++;
|
||||
assert(trans_h.randomize());
|
||||
trans2wr_h = new trans_h;
|
||||
gen2wr.put(trans2wr_h);
|
||||
end
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass: counter_gen
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
interface counter_if(input logic clk);
|
||||
|
||||
logic rst, updown, load;
|
||||
logic [3:0] data;
|
||||
logic [3:0] data_out;
|
||||
|
||||
clocking wr_cb@(posedge clk);
|
||||
output load, updown, rst;
|
||||
output data;
|
||||
endclocking
|
||||
|
||||
clocking wrmon_cb@(posedge clk);
|
||||
input data;
|
||||
input load, rst, updown;
|
||||
endclocking
|
||||
|
||||
clocking rdmon_cb@(posedge clk);
|
||||
input data_out;
|
||||
endclocking
|
||||
|
||||
modport WR_BFM(clocking wr_cb);
|
||||
modport WR_MON(clocking wrmon_cb);
|
||||
modport RD_MON(clocking rdmon_cb);
|
||||
|
||||
endinterface: counter_if
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package counter_pkg;
|
||||
|
||||
int no_of_transaction;
|
||||
|
||||
`include "counter_trans.sv"
|
||||
`include "counter_gen.sv"
|
||||
`include "counter_wr_bfm.sv"
|
||||
`include "counter_wr_mon.sv"
|
||||
`include "counter_rd_mon.sv"
|
||||
`include "counter_rm.sv"
|
||||
`include "counter_sb.sv"
|
||||
`include "counter_env.sv"
|
||||
|
||||
endpackage
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
class counter_rd_mon;
|
||||
|
||||
virtual counter_if.RD_MON rdmon_if;
|
||||
|
||||
mailbox #(counter_trans) rdmon2sb;
|
||||
|
||||
counter_trans trans_h;
|
||||
counter_trans rd2sb_h;
|
||||
|
||||
function new( virtual counter_if.RD_MON rdmon_if,
|
||||
mailbox #(counter_trans) rdmon2sb);
|
||||
this.rdmon_if = rdmon_if;
|
||||
this.rdmon2sb = rdmon2sb;
|
||||
trans_h = new;
|
||||
endfunction
|
||||
|
||||
task monitor();
|
||||
@(rdmon_if.rdmon_cb)
|
||||
trans_h.data_out = rdmon_if.rdmon_cb.data_out;
|
||||
if($isunknown(rdmon_if.rdmon_cb.data_out))
|
||||
trans_h.data_out = 0;
|
||||
endtask
|
||||
|
||||
task start();
|
||||
fork
|
||||
forever
|
||||
begin
|
||||
monitor();
|
||||
trans_h.display("DATA FROM READ MONITOR");
|
||||
rd2sb_h = new trans_h;
|
||||
rdmon2sb.put(rd2sb_h);
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass: counter_rd_mon
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
class counter_rm;
|
||||
|
||||
mailbox #(counter_trans) rm2sb, wrmon2rm;
|
||||
|
||||
counter_trans wrmon2rm_h, temp_h;
|
||||
|
||||
int count;
|
||||
|
||||
function new(mailbox #(counter_trans) wrmon2rm, mailbox #(counter_trans) rm2sb);
|
||||
this.rm2sb = rm2sb;
|
||||
this.wrmon2rm = wrmon2rm;
|
||||
temp_h = new();
|
||||
endfunction
|
||||
|
||||
task model();
|
||||
++count;
|
||||
if(count > 1)
|
||||
begin
|
||||
temp_h.rst = wrmon2rm_h.rst;
|
||||
temp_h.load = wrmon2rm_h.load;
|
||||
temp_h.updown = wrmon2rm_h.updown;
|
||||
temp_h.data = wrmon2rm_h.data;
|
||||
if(wrmon2rm_h.rst)
|
||||
temp_h.data_out = 0;
|
||||
else if(wrmon2rm_h.load)
|
||||
temp_h.data_out = wrmon2rm_h.data;
|
||||
else if(wrmon2rm_h.updown)
|
||||
temp_h.data_out = ++temp_h.data_out;
|
||||
else if(!wrmon2rm_h.updown)
|
||||
temp_h.data_out = --temp_h.data_out;
|
||||
end
|
||||
endtask
|
||||
|
||||
task start();
|
||||
fork
|
||||
forever
|
||||
begin
|
||||
wrmon2rm.get(wrmon2rm_h);
|
||||
rm2sb.put(temp_h);
|
||||
temp_h = new temp_h;
|
||||
model();
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass :counter_rm
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
class counter_sb;
|
||||
|
||||
mailbox #(counter_trans) rm2sb, rdmon2sb;
|
||||
|
||||
event DONE;
|
||||
|
||||
int count_transaction, data_verified;
|
||||
|
||||
counter_trans cov_h, rcvd_h;
|
||||
|
||||
covergroup counter_cov;
|
||||
option.per_instance = 1;
|
||||
RST: coverpoint cov_h.rst {bins r[] = {0,1};}
|
||||
LD: coverpoint cov_h.load {bins l[] = {0,1};}
|
||||
UD: coverpoint cov_h.updown {bins ud[] = {0,1};}
|
||||
DATA: coverpoint cov_h.data {bins d[] = {[0:15]};}
|
||||
DOUT: coverpoint cov_h.data_out {bins dout[] = {[0:15]};}
|
||||
|
||||
LDxDATA: cross LD, DATA;
|
||||
UDxDOUT: cross UD, DOUT;
|
||||
RSTxLDxDATA: cross RST, LD, DATA;
|
||||
RSTxLDxUD: cross RST, LD, UD;
|
||||
endgroup
|
||||
|
||||
function new(mailbox #(counter_trans) rm2sb, mailbox #(counter_trans) rdmon2sb);
|
||||
this.rm2sb = rm2sb;
|
||||
this.rdmon2sb = rdmon2sb;
|
||||
counter_cov = new();
|
||||
endfunction
|
||||
|
||||
task start;
|
||||
fork
|
||||
forever
|
||||
begin
|
||||
rm2sb.get(rcvd_h);
|
||||
cov_h = rcvd_h;
|
||||
counter_cov.sample();
|
||||
//--------------------//
|
||||
rdmon2sb.get(cov_h);
|
||||
check(rcvd_h);
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
task check(counter_trans rcvd_h);
|
||||
|
||||
count_transaction++;
|
||||
|
||||
if(cov_h.compare(rcvd_h))
|
||||
begin
|
||||
counter_cov.sample();
|
||||
data_verified++;
|
||||
end
|
||||
|
||||
if(count_transaction >= no_of_transaction)
|
||||
->DONE;
|
||||
endtask
|
||||
|
||||
function void report;
|
||||
$display("--------------SCOREBOARD REPORT----------------");
|
||||
$display("Number of transactions received : %0d", count_transaction);
|
||||
$display("Number of transactions verified : %0d", data_verified);
|
||||
$display("-----------------------------------------------");
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
|
||||
endclass :counter_sb
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
class counter_trans;
|
||||
|
||||
rand bit [3:0] data;
|
||||
rand bit rst;
|
||||
rand bit load;
|
||||
rand bit updown;
|
||||
|
||||
bit [3:0] data_out;
|
||||
|
||||
static int trans_id;
|
||||
|
||||
|
||||
//Constraints to control frequency of reset and load
|
||||
constraint r1{rst dist {0:=50, 1:=1};}
|
||||
constraint l1{load dist {0:=20, 1:=1};}
|
||||
|
||||
function void post_randomize();
|
||||
this.display("RANDOMIZED DATA");
|
||||
endfunction
|
||||
|
||||
function void display(string message);
|
||||
$display("-------------------------------------------------");
|
||||
$display("%s",message);
|
||||
$display("\tTransaction ID: %d", trans_id);
|
||||
$display("\tRESET = %d\n\tLOAD = %d\n\tUP-DOWN = %d\n\tDATA = %d", rst, load, updown, data);
|
||||
$display("-------------------------------------------------");
|
||||
endfunction
|
||||
|
||||
function bit compare(counter_trans rcvd);
|
||||
compare = 1'b1;
|
||||
if(this.data_out != rcvd.data_out)
|
||||
begin
|
||||
compare = 1'b0;
|
||||
$display("DATA MISMATCH");
|
||||
$display(this.data_out, " != ", rcvd.data_out);
|
||||
$stop;
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass: counter_trans
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
class counter_wr_bfm;
|
||||
|
||||
virtual counter_if.WR_BFM wr_if;
|
||||
|
||||
mailbox #(counter_trans) gen2wr;
|
||||
|
||||
counter_trans trans_h;
|
||||
|
||||
function new( virtual counter_if.WR_BFM wr_if,
|
||||
mailbox #(counter_trans) gen2wr);
|
||||
this.wr_if = wr_if;
|
||||
this.gen2wr = gen2wr;
|
||||
this.trans_h = new;
|
||||
endfunction
|
||||
|
||||
task drive();
|
||||
@(wr_if.wr_cb);
|
||||
wr_if.wr_cb.rst <= trans_h.rst;
|
||||
wr_if.wr_cb.load <= trans_h.load;
|
||||
wr_if.wr_cb.updown <= trans_h.updown;
|
||||
wr_if.wr_cb.data <= trans_h.data;
|
||||
endtask
|
||||
|
||||
task start();
|
||||
fork
|
||||
forever
|
||||
begin
|
||||
gen2wr.get(trans_h);
|
||||
drive();
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass: counter_wr_bfm
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
class counter_wr_mon;
|
||||
|
||||
virtual counter_if.WR_MON wrmon_if;
|
||||
|
||||
mailbox #(counter_trans) wrmon2rm;
|
||||
|
||||
counter_trans trans_h, wrmon2rm_h;
|
||||
|
||||
function new( virtual counter_if.WR_MON wrmon_if,
|
||||
mailbox #(counter_trans) wrmon2rm);
|
||||
this.wrmon_if = wrmon_if;
|
||||
this.wrmon2rm = wrmon2rm;
|
||||
this.trans_h = new;
|
||||
endfunction
|
||||
|
||||
task monitor();
|
||||
@(wrmon_if.wrmon_cb)
|
||||
begin
|
||||
trans_h.rst = wrmon_if.wrmon_cb.rst;
|
||||
trans_h.load = wrmon_if.wrmon_cb.load;
|
||||
trans_h.updown = wrmon_if.wrmon_cb.updown;
|
||||
trans_h.data = wrmon_if.wrmon_cb.data;
|
||||
trans_h.display("DATA FROM WRITE MONITOR");
|
||||
end
|
||||
endtask
|
||||
|
||||
task start();
|
||||
fork
|
||||
forever
|
||||
begin
|
||||
monitor();
|
||||
wrmon2rm_h = new trans_h;
|
||||
wrmon2rm.put(wrmon2rm_h);
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass: counter_wr_mon
|
||||
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
`include "test.sv"
|
||||
|
||||
module top;
|
||||
|
||||
reg clk;
|
||||
|
||||
counter_if intf(clk);
|
||||
|
||||
counter DUV( .clk(clk),
|
||||
.rst(intf.rst),
|
||||
.load(intf.load),
|
||||
.updown(intf.updown),
|
||||
.data(intf.data),
|
||||
.data_out(intf.data_out));
|
||||
|
||||
bind DUV counter_assertion C_A( .clk(clk),
|
||||
.rst(intf.rst),
|
||||
.load(intf.load),
|
||||
.updown(intf.updown),
|
||||
.data(intf.data),
|
||||
.count(intf.data_out));
|
||||
|
||||
test test_h;
|
||||
|
||||
initial
|
||||
begin
|
||||
test_h = new(intf, intf, intf);
|
||||
test_h.build_and_run();
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
clk = 0;
|
||||
forever #10 clk = ~clk;
|
||||
end
|
||||
|
||||
endmodule: top
|
||||
@@ -0,0 +1,25 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// 4-bit loadable up-down counter //////
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
module counter(clk, rst, data, updown, load, data_out);
|
||||
|
||||
input clk, rst, load;
|
||||
input updown;
|
||||
input [3:0] data;
|
||||
|
||||
output reg [3:0] data_out;
|
||||
|
||||
|
||||
always@(posedge clk)
|
||||
begin
|
||||
if(rst)
|
||||
data_out <= 4'b0;
|
||||
else if(load)
|
||||
data_out <= data;
|
||||
else
|
||||
data_out <= ((updown)?(data_out + 1'b1):(data_out -1'b1));
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
modelsim.*
|
||||
transcript*
|
||||
vlog.*
|
||||
work/
|
||||
counter_cov*
|
||||
fcover*
|
||||
covhtml*
|
||||
vcover*
|
||||
*.log
|
||||
*.wlf
|
||||
@@ -0,0 +1,81 @@
|
||||
# Makefile for Memory - Regression Testing
|
||||
RTL= ../rtl/counter.v
|
||||
work= work #library name
|
||||
COVOP= -coveropt 3 +cover +acc
|
||||
SVTB1= ../env/counter_if.sv ../env/counter_assertion.sv ../env/top.sv
|
||||
INC = +incdir+../env +incdir+../test
|
||||
SVTB2 = ../env/counter_pkg.sv
|
||||
TEST = ../test/test.sv
|
||||
#TEST1 = ../test/test1.sv
|
||||
#TEST2 = ../test/test2.sv
|
||||
VSIMOPT= -coverage -novopt -sva -sv_seed 2475652473 work.top
|
||||
VSIMCOV= coverage save -onexit -assert -directive -cvg -codeAll counter_cov
|
||||
VSIMBATCH= -c -do "$(VSIMCOV); run -all; exit"
|
||||
VSIMBATCH1 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov1;run -all;exit"
|
||||
VSIMBATCH2 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov2;run -all;exit"
|
||||
VSIMBATCH3 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov3;run -all;exit"
|
||||
VSIMBATCH4 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov4;run -all;exit"
|
||||
VSIMBATCH5 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov5;run -all;exit"
|
||||
VSIMBATCH6 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov6;run -all;exit"
|
||||
VSIMBATCH7 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov7;run -all;exit"
|
||||
VSIMBATCH8 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov8;run -all;exit"
|
||||
VSIMBATCH9 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov9;run -all;exit"
|
||||
|
||||
|
||||
html:
|
||||
firefox covhtmlreport/menu.html
|
||||
|
||||
sv_cmp:
|
||||
vlib $(work)
|
||||
vmap work $(work)
|
||||
vlog -work $(work) $(COVOP) $(RTL) $(SVTB2) $(SVTB1) $(INC) #$(TEST)
|
||||
|
||||
run_sim:
|
||||
vsim $(VSIMBATCH1) $(VSIMOPT) -l test1_sim.log +TEST1 +nowarn3829
|
||||
|
||||
run_testg:
|
||||
vsim -novopt -sva -sv_seed random work.top +TEST1
|
||||
clear
|
||||
|
||||
clean:
|
||||
rm -rf modelsim.* transcript* vlog.* work vsim.wlf counter_cov* fcover* covhtml* vcover* *.log
|
||||
clear
|
||||
|
||||
TC2:
|
||||
vsim $(VSIMBATCH2) -coverage -novopt -sva -sv_seed 598761566 -l test2_sim.log work.top +TEST2
|
||||
|
||||
TC3:
|
||||
vsim $(VSIMBATCH3) -coverage -novopt -sva -sv_seed 74473697 -l test3_sim.log work.top +TEST3
|
||||
|
||||
TC4:
|
||||
vsim $(VSIMBATCH4) -coverage -novopt -sva -sv_seed 4275076933 -l test4_sim.log work.top +TEST4
|
||||
|
||||
TC5:
|
||||
vsim $(VSIMBATCH5) -coverage -novopt -sva -sv_seed 3868229417 -l test5_sim.log work.top +TEST5
|
||||
|
||||
TC6:
|
||||
vsim $(VSIMBATCH6) -coverage -novopt -sva -sv_seed 749764269 -l test6_sim.log work.top +TEST6
|
||||
|
||||
TC7:
|
||||
vsim $(VSIMBATCH7) -coverage -novopt -sva -sv_seed 1982889551 -l test7_sim.log work.top +TEST7
|
||||
|
||||
TC8:
|
||||
vsim $(VSIMBATCH8) -coverage -novopt -sva -sv_seed 1987083824 -l test8_sim.log work.top +TEST8
|
||||
|
||||
TC9:
|
||||
vsim $(VSIMBATCH9) -coverage -novopt -sva -sv_seed 1987083824 -l test8_sim.log work.top +TEST9
|
||||
|
||||
report:
|
||||
vcover merge counter_cov counter_cov1 counter_cov2 #counter_cov3 counter_cov4 counter_cov5 counter_cov6 counter_cov7
|
||||
vcover report -html counter_cov
|
||||
|
||||
regress: clean run_test TC2 report html # TC3 TC4 TC5 TC6 TC7 report html
|
||||
|
||||
gui:
|
||||
vsim $(VSIMOPT) -l test1_sim.log +TEST1 +nowarn3829
|
||||
|
||||
run_gui: clean sv_cmp gui
|
||||
|
||||
run_test: clean sv_cmp run_sim
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import counter_pkg::*;
|
||||
|
||||
|
||||
class counter_trans_load extends counter_trans;
|
||||
|
||||
randc logic [3:0] data;
|
||||
|
||||
constraint r1 {rst inside {0, 1};}
|
||||
constraint l1 {load inside {0, 1};}
|
||||
constraint d1{super.data == data;}
|
||||
|
||||
endclass
|
||||
|
||||
|
||||
class test;
|
||||
|
||||
virtual counter_if.WR_BFM wr_if;
|
||||
virtual counter_if.WR_MON wrmon_if;
|
||||
virtual counter_if.RD_MON rdmon_if;
|
||||
|
||||
counter_env env;
|
||||
|
||||
counter_trans_load trans_ld_h;
|
||||
|
||||
function new( virtual counter_if.WR_BFM wr_if,
|
||||
virtual counter_if.WR_MON wrmon_if,
|
||||
virtual counter_if.RD_MON rdmon_if);
|
||||
|
||||
this.wr_if = wr_if;
|
||||
this.wrmon_if = wrmon_if;
|
||||
this.rdmon_if = rdmon_if;
|
||||
|
||||
env = new(wr_if, wrmon_if, rdmon_if);
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
task build_and_run;
|
||||
if($test$plusargs("TEST1"))
|
||||
begin
|
||||
no_of_transaction = 250;
|
||||
env.build();
|
||||
env.run();
|
||||
$finish;
|
||||
end
|
||||
if($test$plusargs("TEST2"))
|
||||
begin
|
||||
trans_ld_h = new();
|
||||
no_of_transaction = 250;
|
||||
env.build();
|
||||
env.gen_h.trans_h = trans_ld_h;
|
||||
env.run();
|
||||
$finish;
|
||||
end
|
||||
endtask
|
||||
|
||||
endclass :test
|
||||
|
||||
|
||||
|
||||
Submodule 7Segment_Lattice_ice40_UltraPlus deleted from d567bd258c.
@@ -0,0 +1,3 @@
|
||||
*.blif
|
||||
*.asc
|
||||
*.bin
|
||||
@@ -0,0 +1,24 @@
|
||||
filename = top
|
||||
pcf_file = io.pcf
|
||||
|
||||
RPI_USER=pi
|
||||
RPI_IP=192.168.10.90
|
||||
RPI_DIR=/home/pi/ice40/build2
|
||||
|
||||
build:
|
||||
yosys -p "synth_ice40 -blif $(filename).blif" $(filename).v
|
||||
arachne-pnr -d 5k -P sg48 -p $(pcf_file) $(filename).blif -o $(filename).asc
|
||||
icepack $(filename).asc $(filename).bin
|
||||
|
||||
prog: #for sram
|
||||
iceprog -S $(filename).bin
|
||||
|
||||
prog_flash:
|
||||
iceprog $(filename).bin
|
||||
|
||||
rpi_prog: build
|
||||
scp $(filename).bin $(RPI_USER)@$(RPI_IP):$(RPI_DIR)
|
||||
ssh $(RPI_USER)@$(RPI_IP) "cd $(RPI_DIR); iceprog $(filename).bin"
|
||||
|
||||
clean:
|
||||
rm -rf $(filename).blif $(filename).asc $(filename).bin
|
||||
@@ -0,0 +1,9 @@
|
||||
# 7-Segment-Display to show Counter Value
|
||||
|
||||
The goal of this example is to display a counter output on a 7-segment connected to the fpga.
|
||||
|
||||
For used IOs check out io.pcf.
|
||||
|
||||
To Upload use Makefile, Project IceStorm is needed for this to work.
|
||||
|
||||
I uploaded with RPI4, look at make rpi_prog
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
//transforms 4bits numbers to a 7seg display
|
||||
//
|
||||
// --a--
|
||||
// | |
|
||||
// f b
|
||||
// | |
|
||||
// --g--
|
||||
// | |
|
||||
// e c
|
||||
// | |
|
||||
// --d-- DP
|
||||
//
|
||||
// 7'gfedcba (a = LSB)
|
||||
module bcd_to_7seg(input [3:0] bcd_in, output [6:0] seg_out);
|
||||
|
||||
assign seg_out = (bcd_in==4'h0) ? 7'b0111111 :
|
||||
(bcd_in==4'h1) ? 7'b0000110 :
|
||||
(bcd_in==4'h2) ? 7'b1011011 :
|
||||
(bcd_in==4'h3) ? 7'b1001111 :
|
||||
(bcd_in==4'h4) ? 7'b1100110 :
|
||||
(bcd_in==4'h5) ? 7'b1101101 :
|
||||
(bcd_in==4'h6) ? 7'b1111101 :
|
||||
(bcd_in==4'h7) ? 7'b0000111 :
|
||||
(bcd_in==4'h8) ? 7'b1111111 :
|
||||
(bcd_in==4'h9) ? 7'b1101111 :
|
||||
(bcd_in==4'ha) ? 7'b1110111 :
|
||||
(bcd_in==4'hb) ? 7'b1111100 :
|
||||
(bcd_in==4'hc) ? 7'b0111001 :
|
||||
(bcd_in==4'hd) ? 7'b1011110 :
|
||||
(bcd_in==4'he) ? 7'b1111001 :
|
||||
(bcd_in==4'hf) ? 7'b1110001 :
|
||||
7'b0110110; //does a H, default shouldn't happen
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,43 @@
|
||||
// generate clocks
|
||||
|
||||
module clocks
|
||||
#(
|
||||
parameter PRE_PWM = 28'd12,
|
||||
parameter PRE_7SEG = 28'd12,
|
||||
parameter PRE_COUNTER = 28'd12
|
||||
)
|
||||
(
|
||||
input clk, output clk_pwm, output clk_7seg, output clk_counter
|
||||
);
|
||||
|
||||
reg [27:0] counter = 28'd0;
|
||||
reg [27:0] counter_7seg = 28'd0;
|
||||
reg [27:0] counter_counter = 28'd0;
|
||||
reg clk_pwm;
|
||||
reg clk_7seg;
|
||||
reg clk_counter;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
counter <= counter + 28'd1;
|
||||
if(counter >= (PRE_PWM-1))
|
||||
counter <= 28'd0;
|
||||
clk_pwm <= ( counter < PRE_PWM/2) ? 1'b1 : 1'b0;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
counter_7seg <= counter_7seg + 28'd1;
|
||||
if(counter_7seg >= (PRE_7SEG-1))
|
||||
counter_7seg <= 28'd0;
|
||||
clk_7seg <= ( counter_7seg < PRE_7SEG/2) ? 1'b1 : 1'b0;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
counter_counter <= counter_counter + 28'd1;
|
||||
if(counter_counter >= (PRE_COUNTER-1))
|
||||
counter_counter <= 28'd0;
|
||||
clk_counter <= ( counter_counter < PRE_COUNTER/2) ? 1'b1 : 1'b0;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,23 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// 20-bit loadable up-down counter //////
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
module counter(clk, rst, data, updown, load, data_out);
|
||||
|
||||
input clk, rst, load;
|
||||
input updown;
|
||||
input [19:0] data;
|
||||
|
||||
output reg [19:0] data_out;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if(rst)
|
||||
data_out <= 20'b0;
|
||||
else if(load)
|
||||
data_out <= data;
|
||||
else
|
||||
data_out <= ((updown)?(data_out + 1'b1):(data_out -1'b1));
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,48 @@
|
||||
`include "bcd_to_7seg.v"
|
||||
|
||||
|
||||
module digit_driver
|
||||
#(
|
||||
parameter D = 28'd0
|
||||
)
|
||||
(
|
||||
input clk, input [19:0] number, input dot, output [7:0] segs, output [4:0] digs
|
||||
);
|
||||
|
||||
// io for 7seg
|
||||
reg [2:0] active_digit;
|
||||
wire [4:0] buf_digs;
|
||||
|
||||
wire [19:0] number;
|
||||
wire [3:0] a_number;
|
||||
wire [6:0] seg_out;
|
||||
|
||||
bcd_to_7seg bcd_to_7seg_inst(
|
||||
.bcd_in(a_number),
|
||||
.seg_out(seg_out)
|
||||
);
|
||||
|
||||
// see bcd_to_7seg.v for segments placement
|
||||
// common anode ~seg_out[], common cathode seg_out[]
|
||||
|
||||
assign segs = { dot, seg_out };
|
||||
|
||||
assign buf_digs = (number > 20'hFFFF) ? 5'b11111 :
|
||||
(number > 20'hFFF) ? 5'b01111 :
|
||||
(number > 20'hFF) ? 5'b00111 :
|
||||
(number > 20'hF) ? 5'b00011 :
|
||||
5'b00001; // default shouldn't happen
|
||||
|
||||
assign digs = buf_digs & (1'b1 << active_digit);
|
||||
assign a_number = (number & (4'b1111 << (active_digit*4))) >> (active_digit*4);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
active_digit <= active_digit + 1'b1;
|
||||
if(active_digit > 3'd3)
|
||||
active_digit <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
# For the iCE40 UltraPlus (iCE40UP5K-QFN) Breakout Board
|
||||
# 12 MHz Clock
|
||||
set_io clk 35
|
||||
|
||||
set_io LED_R 41
|
||||
set_io LED_G 40
|
||||
set_io LED_B 39
|
||||
set_io SW[0] 23
|
||||
set_io SW[1] 25
|
||||
set_io SW[2] 34
|
||||
set_io SW[3] 43
|
||||
|
||||
# bank 0,segments
|
||||
set_io seg_b 26 # IOT_39A
|
||||
set_io seg_a 27 # IOT_38B
|
||||
set_io seg_p 28 # IOT_41A
|
||||
set_io seg_f 31 # IOT_42B
|
||||
set_io seg_g 32 # IOT_43A
|
||||
set_io seg_e 37 # IOT_45A_G1
|
||||
set_io seg_d 42 # IOT_51A
|
||||
set_io seg_c 38 # IOT_50B
|
||||
# bank1 digit
|
||||
set_io dig_1 21 # IOT_23B
|
||||
set_io dig_2 20 # IOT_25B_G3
|
||||
set_io dig_3 19 # IOT_29B
|
||||
set_io dig_4 18 # IOT_31B
|
||||
set_io dig_5 11 # IOT_20A
|
||||
|
||||
#spi
|
||||
set_io SPI_SS 16
|
||||
set_io SPI_SCK 15
|
||||
set_io SPI_MOSI 17
|
||||
set_io SPI_MISO 14
|
||||
@@ -0,0 +1,24 @@
|
||||
//pwm module, outputs a pulse width according to the value written
|
||||
//max width 255 cycles
|
||||
|
||||
module pwm(input clk, input en, input [7:0] value_input, output out);
|
||||
reg [7:0] counter;
|
||||
reg [7:0] value; //max 255
|
||||
|
||||
assign out = (counter < value);
|
||||
|
||||
initial begin
|
||||
counter = 0;
|
||||
value = 255;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
counter <= counter + 1;
|
||||
|
||||
if(en == 1'b1)
|
||||
value <= value_input;
|
||||
else
|
||||
value <= 0;
|
||||
end
|
||||
endmodule
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
`include "digit_driver.v"
|
||||
`include "pwm.v"
|
||||
`include "clocks.v"
|
||||
`include "counter.v"
|
||||
|
||||
// A verilog module transforms a 4-bit number into a displayable 7-bit value.
|
||||
// This number is incremented every ~0.25sec.
|
||||
module top( input clk,
|
||||
output LED_R, output LED_G, output LED_B,
|
||||
output seg_b, output seg_a, output seg_f,
|
||||
output seg_g, output seg_d, output seg_e,
|
||||
output seg_c, output seg_p, input [3:0] SW,
|
||||
output dig_1, output dig_2, output dig_3, output dig_4, output dig_5
|
||||
);
|
||||
|
||||
wire clk_pwm;
|
||||
wire clk_7seg;
|
||||
wire clk_counter;
|
||||
|
||||
clocks #(.PRE_PWM(28'd12), .PRE_7SEG(28'd12000), .PRE_COUNTER(28'd12000)) clocks_inst
|
||||
(
|
||||
.clk(clk),
|
||||
.clk_pwm(clk_pwm),
|
||||
.clk_7seg(clk_7seg),
|
||||
.clk_counter(clk_counter)
|
||||
);
|
||||
|
||||
wire rst;
|
||||
wire updown;
|
||||
wire load;
|
||||
reg [19:0] data = 20'h1337;
|
||||
wire [19:0] data_out;
|
||||
|
||||
assign rst = SW[0];
|
||||
assign updown = SW[1];
|
||||
assign load = SW[2];
|
||||
|
||||
counter TIM1 (
|
||||
.clk(clk_counter),
|
||||
.rst(rst),
|
||||
.data(data),
|
||||
.updown(updown),
|
||||
.load(load),
|
||||
.data_out(data_out)
|
||||
);
|
||||
|
||||
wire pwm_en_write;
|
||||
assign pwm_en_write = SW[3];
|
||||
wire [7:0] pwm_brightness;
|
||||
reg [7:0] led_brightness;
|
||||
assign pwm_brightness = led_brightness;
|
||||
|
||||
wire pwm_out;
|
||||
pwm pwm_inst(.clk(clk_pwm), .en(pwm_en_write), .value_input(pwm_brightness), .out(pwm_out));
|
||||
|
||||
// active low, color white
|
||||
assign LED_R = ~pwm_out;
|
||||
assign LED_G = ~pwm_out;
|
||||
assign LED_B = ~pwm_out;
|
||||
|
||||
wire [19:0] number;
|
||||
assign number = data_out;
|
||||
assign dot = rst;
|
||||
|
||||
wire [7:0] segs;
|
||||
assign seg_a = segs[0];
|
||||
assign seg_b = segs[1];
|
||||
assign seg_c = segs[2];
|
||||
assign seg_d = segs[3];
|
||||
assign seg_e = segs[4];
|
||||
assign seg_f = segs[5];
|
||||
assign seg_g = segs[6];
|
||||
assign seg_p = segs[7];
|
||||
|
||||
wire [4:0] digs;
|
||||
assign dig_1 = digs[0];
|
||||
assign dig_2 = digs[1];
|
||||
assign dig_3 = digs[2];
|
||||
assign dig_4 = digs[3];
|
||||
assign dig_5 = digs[4];
|
||||
digit_driver dig_inst(.clk(clk_7seg), .number(number), .dot(dot), .segs(segs), .digs(digs));
|
||||
|
||||
initial begin
|
||||
led_brightness = 10;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,44 @@
|
||||
// Simulation EPaper Cell
|
||||
|
||||
`include "disciplines.vams"
|
||||
`include "constants.vams"
|
||||
`include "otft.va"
|
||||
|
||||
module am_epd_pixel(gate, source, n);
|
||||
electrical gate, source, n;
|
||||
ground n;
|
||||
electrical v_cell;
|
||||
|
||||
// v_cell ist am drain vom oTFT
|
||||
oTFT tft1(gate, source, v_cell);
|
||||
resistor #(.r(67.445e9)) EPDload(v_cell, n);
|
||||
capacitor #(.c(8.6e-12)) CS(v_cell, n);
|
||||
endmodule // am_epd_pixel
|
||||
|
||||
module demo;
|
||||
electrical v_gate, v_source, gnd;
|
||||
ground gnd;
|
||||
|
||||
parameter real on_V = 0.0;
|
||||
parameter real off_V = 7.5;
|
||||
|
||||
parameter real on_T = 0.5m;
|
||||
parameter real off_T = 16.7m-on_T;
|
||||
parameter real startDelay = 1m;
|
||||
|
||||
// Puls-Quelle
|
||||
/*prameters expected for 'pulse' are '[dc] [mag [phase]] val0 val1 [td [rise [fall [width [period]]]]] */
|
||||
vpulse #(.val0(off_V), .val1(on_V), .td(startDelay), .rise(1n), .fall(1n), .width(on_T), .period(on_T + off_T)) PL(v_gate, gnd);
|
||||
|
||||
parameter real on_V2 = 5.0;
|
||||
parameter real off_V2 = 0.0;
|
||||
|
||||
parameter real on_T2 = 3m;
|
||||
parameter real off_T2 = 16.7m-on_T2;
|
||||
parameter real startDelay2 = 0;
|
||||
|
||||
vpulse #(.val0(off_V2), .val1(on_V2), .td(startDelay2), .rise(1n), .fall(1n), .width(on_T2), .period(on_T2 + off_T2)) PL2(v_source, gnd);
|
||||
|
||||
// Pixel
|
||||
am_epd_pixel pixel1(v_gate, v_source, gnd);
|
||||
endmodule // demo
|
||||
@@ -0,0 +1,23 @@
|
||||
VA_FILE = demo.va
|
||||
TOP_LEVEL_MODULE = demo
|
||||
|
||||
CMD_FILE = demo.cmd
|
||||
DO_FILE = run.do
|
||||
OUT_FILE = demo.wdb
|
||||
|
||||
|
||||
|
||||
sim:
|
||||
valog $(VA_FILE)
|
||||
vasim -c -cmd $(CMD_FILE) -do $(DO_FILE) $(TOP_LEVEL_MODULE)
|
||||
|
||||
ezwave:
|
||||
ezwave -now -loc 10 10 -width 2400 -height 1200 -tcl create_plots.tcl
|
||||
|
||||
clean:
|
||||
rm DefaultVlogALib -rf
|
||||
rm *.chi *.log *.id *.reuse *.wdb -rf
|
||||
rm simcommand transcript* dok_code* -rf
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
############################################################
|
||||
## EZwave - Saved Window File
|
||||
## Tuesday, June 15, 2021 at 1:05:13 AM CEST
|
||||
##
|
||||
## Note: This is an auto-generated file.
|
||||
##
|
||||
## In case of modification, Do not remove this comment
|
||||
############################################################
|
||||
|
||||
onerror {resume}
|
||||
|
||||
# ===== Open required Database =====
|
||||
dataset open /users/ads1/schmidtsi76327/linux/esy1a/LCD_EPD_Simulation_VerilogA/epaper/4_1_model/demo.wdb demo
|
||||
|
||||
# ===== Open the window =====
|
||||
wave addwindow -x 0 -y 0 -width 767 -height 581 -divider 0.85
|
||||
|
||||
# ===== Create row #1 =====
|
||||
add wave -show TRAN.v -color -16711936 -separator : -terminals :demo:v_gate
|
||||
|
||||
|
||||
# ===== Create row #2 =====
|
||||
add wave -show TRAN.v -color -256 -separator : -terminals :demo:v_source
|
||||
|
||||
|
||||
# ===== Create row #3 =====
|
||||
add wave -show TRAN.v -color -16744193 -separator : -terminals :demo:pixel1:v_cell
|
||||
|
||||
|
||||
# ====== Create the cursors, markers and measurements =====
|
||||
@@ -0,0 +1,3 @@
|
||||
* tran_x.cmd
|
||||
|
||||
.tran 1u 100m
|
||||
@@ -0,0 +1,44 @@
|
||||
// Simulation EPaper Cell
|
||||
|
||||
`include "disciplines.vams"
|
||||
`include "constants.vams"
|
||||
`include "otft.va"
|
||||
|
||||
module am_epd_pixel(gate, source, n);
|
||||
electrical gate, source, n;
|
||||
ground n;
|
||||
electrical v_cell;
|
||||
|
||||
// v_cell ist am drain vom oTFT
|
||||
oTFT #(.selectQS(0), .LOV(0), .eBov(0)) tft1(gate, source, v_cell);
|
||||
resistor #(.r(67.445e9)) EPDload(v_cell, n);
|
||||
capacitor #(.c(8.6e-12)) CS(v_cell, n);
|
||||
endmodule // am_epd_pixel
|
||||
|
||||
module demo;
|
||||
electrical v_gate, v_source, gnd;
|
||||
ground gnd;
|
||||
|
||||
parameter real on_V = 0.0;
|
||||
parameter real off_V = 7.5;
|
||||
|
||||
parameter real on_T = 0.5m;
|
||||
parameter real off_T = 16.7m-on_T;
|
||||
parameter real startDelay = 1m;
|
||||
|
||||
// Puls-Quelle
|
||||
/*prameters expected for 'pulse' are '[dc] [mag [phase]] val0 val1 [td [rise [fall [width [period]]]]] */
|
||||
vpulse #(.val0(off_V), .val1(on_V), .td(startDelay), .rise(1n), .fall(1n), .width(on_T), .period(on_T + off_T)) PL(v_gate, gnd);
|
||||
|
||||
parameter real on_V2 = 5.0;
|
||||
parameter real off_V2 = 0.0;
|
||||
|
||||
parameter real on_T2 = 3m;
|
||||
parameter real off_T2 = 16.7m-on_T2;
|
||||
parameter real startDelay2 = 0;
|
||||
|
||||
vpulse #(.val0(off_V2), .val1(on_V2), .td(startDelay2), .rise(1n), .fall(1n), .width(on_T2), .period(on_T2 + off_T2)) PL2(v_source, gnd);
|
||||
|
||||
// Pixel
|
||||
am_epd_pixel pixel1(v_gate, v_source, gnd);
|
||||
endmodule // demo
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,285 @@
|
||||
// VerilogA for oTFT 2.04.01, veriloga
|
||||
// Citation/Acknowledgment text:
|
||||
// O. Marinov, "Verilog-A Implementation of the Compact Model 'oTFT' for Organic Thin-Film Transistors", Nano-Engineered Electronic Device Simulation Node (NEEDS), oTFT ver. 2.04.01, May 2015
|
||||
// https://nanohub.org/groups/needs/compact_models
|
||||
// Revision history:
|
||||
// Implemented on 24 April 2015 by O. Marinov
|
||||
// Modified on 7 May 2015 by O. Marinov (comments in code enhanced, monitor voltage drop on both contacts added)
|
||||
// Modified on 14 May 2015 by O. Marinov (monitor commented, to prepare the code for release)
|
||||
// Modified on 14 June 2015 by O. Marinov (redundant electrical nodes GTS and GTD are removed, since the effective overdrive voltages are in variables VGTS and VGTD)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------------
|
||||
Copyright @ 2015 Ognian Marinov.
|
||||
|
||||
The terms under which the software and associated documentation (the Software) is provided are as the following:
|
||||
|
||||
The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
|
||||
|
||||
Ognian Marinov grants, free of charge, to any users the right to modify, copy, and redistribute the Software, both within the user's organization and externally, subject to the following restrictions:
|
||||
|
||||
1. The users agree not to charge for the code itself but may charge for additions, extensions, or support.
|
||||
|
||||
2. In any product based on the Software, the users agree to acknowledge the Research Group that developed the software. This acknowledgment shall appear in the product documentation.
|
||||
|
||||
3. The users agree to obey all U.S. Government restrictions governing redistribution or export of the software.
|
||||
|
||||
4. The users agree to reproduce any copyright notice which appears on the software on any copy or modification of such made available to others.
|
||||
|
||||
Agreed to by
|
||||
Ognian Marinov
|
||||
25 April 2015
|
||||
-------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Summary
|
||||
The oTFT compact models are aimed to support the bias enhancement of the charge carrier mobility and the significant contact effect in organic thin-film transistors (OTFTs).
|
||||
|
||||
The current version 2.04.01 of the oTFT compact model level 2 also supports other effects, such as channel conductance modulation (analogous to the channel length modulation in MOS transistors) and Ohmic and non-linear leakages. Quasi-static charge sub-model supports frequency and temporal response by AC and transient simulations.
|
||||
|
||||
The model is with default values of parameters for organic thin-film transistors, but otherwise, the oTFT models are also applicable to other thin-film transistors (TFTs). Just the model parameters are with other values.
|
||||
|
||||
The oTFT models are ?mirror? of the TFT structure. In the TFT structure and oTFT model, one distinguishes an intrinsic TFT between intrinsic nodes GI, SI, DI, and the intrinsic TFT is connected to the device terminals (gate G, source S, drain D) by contacts of significant impacts. Conceptually, the oTFT models are arranged so that the sub-model components can be changed, replaced, removed or upgraded, as the needs evolve.
|
||||
|
||||
The oTFT models are hierarchical. The top hierarchical level is module oTFT, in which there are ?rails? for interconnection of the sub-models and instantiations of the sub-models between the rails. One rail is with the device terminals G,S,D and another rail is with the internal nodes GI,SI,DI. There is also a control rail with overdrive voltages VGTS=(VG-VT-VS) and VGTD=(VG-VT-VD) at the channel ends of the intrinsic TFT. In the current Verilog-A code, there is a rail with nodes testGND, testSIGNAL for monitoring of internal quantities.
|
||||
|
||||
The advantages of the hierarchical structure are several, but perhaps the most practical advantage is that the sub-models are simple, and well tied to diverse physical interpretations. Therefore, the oTFT model can be managed by researches far from the field of compact modeling and semiconductors, e.g., researchers in chemistry.
|
||||
The oTFT model is arranged so that the different effects can be suppressed by setting model parameters to specific values, usually, equal to zero.
|
||||
|
||||
The current version "oTFT 2.04.01" of the oTFT compact models is based on the following publications:
|
||||
[1] O. Marinov, M. J. Deen, U. Zschieschang, H. Klauk, "Organic Thin-Film Transistors: Part I-Compact DC Modeling", IEEE Trans. Electron Devices, 56(12), 2952-2961, 2009 ; DOI: 10.1109/TED.2009.2033308
|
||||
[2] M. J. Deen, O. Marinov, U. Zschieschang, H. Klauk, "Organic Thin-Film Transistors: Part II-Parameter Extraction", IEEE Trans. Electron Devices, 56(12), 2962-2968, 2009 ; DOI: 10.1109/TED.2009.2033309
|
||||
[3] O. Marinov, M. J. Deen, J. Tejada, B. Iniguez, "Impact of the Fringing Capacitance at the Back of Thin-Film Transistors", Organic Electronics, 12(6), 936-949, 2011 ; DOI: 10.1016/j.orgel.2011.02.020
|
||||
[4] O. Marinov, M. J. Deen, "Quasistatic Compact Modelling of Organic Thin-Film Transistors", Organic Electronics, 14(1), 295-311, 2013 ; DOI: 10.1016/j.orgel.2012.10.031
|
||||
[5] O. Marinov, M. J. Deen, C. Feng, Y. Wu, "Precise Parameter Extraction Technique for Organic Thin-Film Transistors Operating in the Linear Regime", Journal of Applied Physics, 115(3), 034506, 2014 ; DOI: 10.1063/1.4862043
|
||||
[6] O. Marinov, "Compact Models for Organic Thin-Film Transistors: Similarities, Differences, and Principles and Philosophy behind the Models", unpublished reviews and derivations, 127 pages, 2010
|
||||
|
||||
Several adjustments in the equations from these publications have been made to ensure wide range of bias voltages and to avoid numerical problems, such as division by zero and discontinuity of derivatives.
|
||||
|
||||
The suppression of the sub-models is by the following settings, which can be made by instantiation of the oTFT model in circuits:
|
||||
|
||||
Set gamma = 0 to suppress bias enhancement of mobility
|
||||
Set eB=0 to suppress channel modulation model
|
||||
Set eBleak=0 and RBS=10.0e30 (or larger) to suppress the leakage sub-model
|
||||
Set RC=1 and RCmax=0 to suppress the contact resistance model
|
||||
Set selectQS=0 to suppress quasi-static capacitances
|
||||
Set LOV=0 to suppress overlap capacitances between gate conductor and drain/source terminals
|
||||
Set eBov=0 to suppress the geometric capacitance between drain and source terminals
|
||||
|
||||
If only the G,S,D terminals of the TFT are desired (e.g., for circuit simulation), then shorten the list of terminals by the definition of the oTFT module - see below
|
||||
*/
|
||||
|
||||
|
||||
/* =================== Begin of the Verilog-A code of compact model "oTFT" ========================================= */
|
||||
`include "constants.vams"
|
||||
`include "disciplines.vams"
|
||||
|
||||
|
||||
// Uncomment one of the following three lines, in order to have the oTFT model with reduced access nodes by instantiation.
|
||||
|
||||
module oTFT(G,S,D); //The simplest 3-terminal oTFT model, only with nodes G,S,D for gate, source and drain terminals, respectively (use for circuit simulations)
|
||||
// module oTFT(G,S,D,GI,SI,DI); // oTFT model with terminal and intrinsic nodes available (no test terminals for inspection of internal quantities of the model)
|
||||
// module oTFT(G,S,D,testGND,testSIGNAL); //oTFT model with terminal and test nodes available (change the end of the code to select and route quantity to the test terminals)
|
||||
// module oTFT(G,S,D,GI,SI,DI,testGND,testSIGNAL); // oTFT model with all nodes available (for research and troubleshooting). Comment this line, if one of the above three lines is uncommented.
|
||||
parameter real version_oTFT = 2.0401; // oTFT model version = 2.04.01
|
||||
|
||||
electrical G,D,S; // terminals of the TFT for connection in circuits
|
||||
electrical GI,DI,SI; // internal terminals of the TFT channel, for inspection only
|
||||
electrical virtualNode; // virtual node for summing capacitive currents of the quasi-static model. The node is grounded, since the sum of currents to this node is zero +/- numerical errors
|
||||
|
||||
// electrical testGND, testSIGNAL; // test nodes for monitoring, isolated from the oTFT model. See and modify end of the code to select and route quantity to the test terminals
|
||||
|
||||
parameter integer np=-1 from [-1:1] exclude 0; //TFT polarity, np=+1 for n-type TFT, np=-1 for p-type TFT
|
||||
parameter real W=100.0e-6 from (0:inf); // channel width in [m] (default W=100um)
|
||||
parameter real L=10.00e-6 from (0:inf); // channel length in [m] (default L=10um)
|
||||
parameter real CI=0.00035 from [0:inf); // unit-area capacitance of the gate dielectric in [F/m^2]; 0.00035F/m^2 = 35nF/cm^2 (default, 100nm SiO2)
|
||||
parameter real VT=0 from (-inf:inf); // threshold voltage in [V] with its polarity (default VT=0 V)
|
||||
parameter real uo=0.1e-4 from (0:inf); // (low-field) mobility in [m^2/Vs] at gate overdrive Vgamma=1V=np*(VGgamma-VT). Default uo=0.1e-4 m^2/Vs=0.1 cm^2/Vs.
|
||||
parameter real Vgamma=1.0 from (0:inf); // Gate overdrive voltage in [V] for uo. Default, Vgamma = 1.0 V.
|
||||
parameter real gamma=0.6 from [0:inf); // Mobility enhancement factor [numerical exponent]. Default, gamma=max(0,2*To/T-2)=0.6, for To~400K and T~300K.
|
||||
|
||||
parameter real VSS=1.0 from (0:inf); // sub-threshold slope voltage in [V], VSS[V/Np]=dV/d(ln(ID))= 0.43(gamma+2)V/dec = V/dec for gamma=0.33.
|
||||
|
||||
|
||||
// parameters for terminal to channel contacts
|
||||
parameter real RC=100.0e3 from (0:inf); // minimum contact resistance at one contact (to the channel)
|
||||
parameter real RCmax=300.0e3 from [0:inf); // elevation of contact resistance at low currents. Typically, RCmax=3*RC. RCmax=0 for constant resistance=RC.
|
||||
parameter real ICmax=1e-9 from (0:inf); // max current for max contact resistance of value=(RC+RCmax). Typically, ICmax is in nA-range.
|
||||
parameter real nIC=0.75 from [0.125:4]; // reduction exponent for RCmax. Meaningful values: nIC=0.5=SCLC; nIC=1=constant voltage drop.
|
||||
|
||||
parameter real RGmin=1.0 from (0:inf); // negligible gate contact resistance.
|
||||
// Unlikely necessary, but one can increase RGmin in kOhm-MOhm range to introduce a pole in the frequency response of the transconductance gm=dIDS/dVGS
|
||||
|
||||
|
||||
// parameters for channel modulation
|
||||
parameter integer nSCLC=4 from [4:5] exclude 5; // Selector for channel modulation model. nSCLC=4 is only implemented: gamma model with CL=eB*eo/pi/L
|
||||
parameter real eB=2 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film, eB~2, for channel modulation.
|
||||
`define CL eB * `P_EPS0 / `M_PI / L
|
||||
//CL=eB*eo/pi/L, fringing capacitance in the back of the semiconducting film, eB~2
|
||||
|
||||
// parameters for leakage
|
||||
parameter real eBleak=0.5 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film, eBleak~0.5 ~ (eB~2)/4, for leakage.
|
||||
// eBleak is used to calculate fringing capacitance CLL=eBleak*eo/pi/L in the back of the semiconducting film for leakage.
|
||||
`define CLL eBleak * `P_EPS0 / `M_PI / L
|
||||
parameter real VTL=0 from (-inf:inf); // threshold voltage in [V] with its polarity for leakage, ideally VTL=VT (default VTL=0 V)
|
||||
parameter real RBS=10.0e12 from (0:inf); // [Ohm/square] Sheet resistance of the bulk of the semiconducting film, for Ohmic leakage
|
||||
`define Vmin 10.0e-6
|
||||
//Vmin [V] should be about 2-4 times the absolute tolerance for voltage of the simulator
|
||||
|
||||
|
||||
// Quasi-static model parameters.
|
||||
// The quasi-static model is for static charges, not for capacitances. Geometrical (overlap) capacitances are added.
|
||||
// In principle, DC parameters should fully determine the quasi-static model. For convenience, constants are defined
|
||||
`define CG0 W*L*CI
|
||||
// CG0 [F] is the gate dielectric capacitance over the entire channel area of the TFT. CG0="CG zero"
|
||||
parameter integer selectQS=1 from [0:1]; // selectQS=0 suppresses the quasi-static capacitances. The quasi-static charges are still calculated.
|
||||
|
||||
// Overlap capacitances (usually dominate over quasi-static and other capacitances in TFT)
|
||||
parameter real LOV=30.0e-6 from [0:inf); // Geometrical overlap of gate conductor with drain/source contact pad. LOV is approximately the length of the pads perpendicular to channel width W
|
||||
`define COV CI*W*LOV
|
||||
// COV=CI*W*LOV [F] = Overlap capacitance between gate conductor and drain/source contact pad. These COV are the dominant capacitances in TFT, since LOV>(2-3)L.
|
||||
parameter real eBov=1 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film for geometrical capacitance between drain and source terminals, eBov~1 ~ (eB~2)/2.
|
||||
`define CDSOV W * 2 * eBov * `P_EPS0 / `M_PI
|
||||
// CDSOV [F] is geometrical capacitance between drain and source contact pads. It is small, not exceeding twice the fringing capacitance at the "back" of the semiconducting film
|
||||
|
||||
// variables
|
||||
real VGTS, VGTD; // for generic TFT charge drift DC model, etc. VGTS~np*(VG-VT-VS) and VGTD~np*(VG-VT-VD) are overdrive voltages at source and drain ends of the intrinsic channel of the TFT
|
||||
real VSSS, VSSD; // sub-threshold slope voltage for VGTS and VGTD. In sub-threshold regime VSSS=VSSD=VSS. Above threshold, VSSS=VSS+VGTS/32 and VSSD=VSS+VGTD/32, to ensure no overflow of exp(VGT_/VSS_), _=S or D
|
||||
real IDSgen; // Channel current per the generic TFT charge drift DC model
|
||||
real numerator, denominator, fDeltaID; // for channel modulation
|
||||
real VSSSLF, VGTSLF, VSSDLF, VGTDLF; // VSS_ and VGT_for forward leakage diode. (See above VGTS, VGTD, VSSS and VSSD)
|
||||
real VSSSLR, VGTSLR, VSSDLR, VGTDLR; // VSS_ and VGT_for reverse leakage diode. (See above VGTS, VGTD, VSSS and VSSD)
|
||||
real contactIC, contactVC; // current and voltage across one contact of drain/source terminals
|
||||
real QG,QS,QD; // quasi-static charges of gate, source and drain terminals
|
||||
real ksiS, ksiD, ksiG; // normalized overdrive voltages for quasi-static charges
|
||||
real den, numS, numD; // denominator and numerators of the normalized functions of QS and QD
|
||||
|
||||
analog begin
|
||||
|
||||
/* ============ Generic TFT charge drift DC model ============ */
|
||||
|
||||
// Source overdrive voltage
|
||||
VSSS = sqrt(pow(VSS,2) + pow((np*(V(GI) - VT - V(SI)) + abs(V(GI) - VT - V(SI)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTS = VSSS * ln(1+exp(np*(V(GI) - VT - V(SI))/VSSS)); // Source overdrive voltage
|
||||
|
||||
// Drain overdrive voltage
|
||||
VSSD = sqrt(pow(VSS,2) + pow((np*(V(GI) - VT - V(DI)) + abs(V(GI) - VT - V(DI)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTD = VSSD * ln(1+exp(np*(V(GI) - VT - V(DI))/VSSD)); // Drain overdrive voltage
|
||||
|
||||
// Generic TFT charge drift DC model
|
||||
I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*CI*(pow(VGTS,gamma+2)-pow(VGTD,gamma+2))/(gamma+2); // Generic TFT charge drift DC model
|
||||
|
||||
|
||||
/* ============ Contact model ============ */
|
||||
// Connect TFT terminals to intrinsic nodes through contact resistances. The model for contact resistance is R(I)=RC+Rmax*(ICmax/(ICmax+|I|))^nIC
|
||||
V(G,GI) <+ RGmin*I(G,GI); // negligible gate contact resistance
|
||||
V(G,GI) <+ 0 *I(G,GI) * pow(ICmax/(ICmax + abs(I(G,GI))),nIC); // non-linear gate contact resistance is set to zero (ignored)
|
||||
V(S,SI) <+ RC * I(S,SI); // constant (minimum) source contact resistance
|
||||
V(S,SI) <+ RCmax*I(S,SI) * pow(ICmax/(ICmax + abs(I(S,SI))),nIC); // non-linear source contact resistance
|
||||
V(D,DI) <+ RC * I(D,DI); // constant (minimum) drain contact resistance
|
||||
V(D,DI) <+ RCmax*I(D,DI) * pow(ICmax/(ICmax + abs(I(D,DI))),nIC); // non-linear drain contact resistance
|
||||
|
||||
/* ============ Channel modulation ============ */
|
||||
I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CL*(pow(VGTS,gamma+2)-pow(VGTD,gamma+2))/(gamma+2); // first component of channel modulation current
|
||||
I(DI,SI) <+ W/L*uo/pow(Vgamma,gamma)*6*`CL*(V(DI)/2+V(SI)/2-V(GI)+VT)*(pow(VGTS,gamma+1)-pow(VGTD,gamma+1))/(gamma+1); // second component of channel modulation current
|
||||
numerator = abs(pow(VGTS,3+2*gamma)-(3+2*gamma)*pow(VGTS,2+gamma)*pow(VGTD,1+gamma)+(3+2*gamma)*pow(VGTS,1+gamma)*pow(VGTD,2+gamma)-pow(VGTD,3+2*gamma));
|
||||
denominator = abs(pow(VGTS,2+gamma)-pow(VGTD,2+gamma)) + pow((1+3)*`Vmin,2+gamma); // small voltage (1+3)*`Vmin~40uV added to avoid division on zero
|
||||
fDeltaID = numerator/denominator;
|
||||
I(DI,SI) <+ W/L*uo/pow(Vgamma,gamma)*6*`CL*(V(DI)-V(SI))*fDeltaID/2/(gamma+1)/(3+2*gamma); // third component of channel modulation current
|
||||
|
||||
/* ============ Channel leakage ============ */
|
||||
// The leakage and off currents between drain and source terminals are defined as currents independent of gate bias
|
||||
// The leakage model is based on back-film capacitance CLL=eBleak*eo/pi/L, eBleak~0.5 ~ (eB~2)/4
|
||||
// resulting in anti-parallel connection of two TFT diodes for leakage due to CLL. The "gate" capacitance of these two leakage TFT is CI=6CLL
|
||||
// Resistor RBS*L/W is also added for Ohmic leakage between drain and source, due to conductance of the bulk of the semiconducting film.
|
||||
|
||||
// Ohmic (linear) leakage
|
||||
I(D,S) <+ V(D,S) * W / L / RBS; // Ohmic leakage in the bulk of the semiconducting film, between D and S
|
||||
//I(DI,SI) <+ V(DI,SI) * W / L / RBS; // Ohmic leakage in the bulk of the semiconducting film, between DI and SI
|
||||
|
||||
// Forward leakage diode
|
||||
VSSSLF = sqrt(pow(VSS,2) + pow((np*(V(D) - VTL - V(S)) + abs(V(D) - VTL - V(S)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTSLF = VSSSLF * ln(1+exp(np*(V(D) - VTL - V(S))/VSSSLF)); // Source overdrive voltage for forward leakage diode
|
||||
VSSDLF = sqrt(pow(VSS,2) + pow((np*(V(D) - VTL - V(D)) + abs(V(D) - VTL - V(D)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTDLF = VSSDLF * ln(1+exp(np*(V(D) - VTL - V(D))/VSSDLF)); // Drain overdrive voltage for forward leakage diode
|
||||
I(D,S) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLF,gamma+2)-pow(VGTDLF,gamma+2))/(gamma+2); // TFT generic for forward leakage diode, between D and S
|
||||
//I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLF,gamma+2)-pow(VGTDLF,gamma+2))/(gamma+2); // TFT generic for forward leakage diode, between DI and SI
|
||||
|
||||
// Reverse leakage diode
|
||||
VSSSLR = sqrt(pow(VSS,2) + pow((np*(V(S) - VTL - V(S)) + abs(V(S) - VTL - V(S)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTSLR = VSSSLR * ln(1+exp(np*(V(S) - VTL - V(S))/VSSSLR)); // Source overdrive voltage for reverse leakage diode
|
||||
VSSDLR = sqrt(pow(VSS,2) + pow((np*(V(S) - VTL - V(D)) + abs(V(S) - VTL - V(D)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTDLR = VSSDLR * ln(1+exp(np*(V(S) - VTL - V(D))/VSSDLR)); // Drain overdrive voltage for reverse leakage diode
|
||||
I(D,S) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLR,gamma+2)-pow(VGTDLR,gamma+2))/(gamma+2); // TFT generic for reverse leakage diode, between D and S
|
||||
//I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLR,gamma+2)-pow(VGTDLR,gamma+2))/(gamma+2); // TFT generic for reverse leakage diode, between DI and SI
|
||||
|
||||
|
||||
/* ============ Quasi-static charge model ============ */
|
||||
//Generic quasi-static charge model of the TFT for computer simulators. QG, QS and QD are the quasi-static charges of gate, source and drain terminals
|
||||
|
||||
// normalized overdrive voltages: ksiS = VGTS/(VGTS+VGTD); ksiD = VGTD/(VGTS+VGTD);
|
||||
ksiS = sqrt(pow(VGTS,2)+pow(`Vmin,2)) / (sqrt(pow(VGTS,2)+pow(`Vmin,2))+sqrt(pow(VGTD,2)+pow(`Vmin,2))); // normalized overdrive voltages for source
|
||||
ksiD = sqrt(pow(VGTD,2)+pow(`Vmin,2)) / (sqrt(pow(VGTS,2)+pow(`Vmin,2))+sqrt(pow(VGTD,2)+pow(`Vmin,2))); // normalized overdrive voltages for drain
|
||||
ksiG = ksiS + ksiD; // this quantity should be always equal to unity. Not used, therefore
|
||||
|
||||
// den, numS, numD; // denominator and numerators of the normalized functions of QS and QD
|
||||
den = pow((pow(ksiS,(2+gamma))/(2+gamma)-pow(ksiD,(2+gamma))/(2+gamma)),2); // denominator of the normalized functions of QS and QD
|
||||
numS = (pow(ksiS,5+2*gamma)/(5+2*gamma))/(2+gamma)-(pow(ksiS,3+gamma)/(3+gamma))*(pow(ksiD,2+gamma)/(2+gamma))+(pow(ksiD,5+2*gamma)/(5+2*gamma))/(3+gamma); // numerator of the normalized function of QS
|
||||
numD = (pow(ksiS,5+2*gamma)/(5+2*gamma))/(3+gamma)-(pow(ksiS,2+gamma)/(2+gamma))*(pow(ksiD,3+gamma)/(3+gamma))+(pow(ksiD,5+2*gamma)/(5+2*gamma))/(2+gamma); // numerator of the normalized function of QD
|
||||
|
||||
// real QG,QS,QD; // quasi-static charges of gate, source and drain terminals
|
||||
QS = np*(-`CG0)*(VGTS+VGTD)*sqrt((pow(numS,2)+pow(((1+ksiS)*`Vmin/6),2))/(pow(den,2)+pow(`Vmin,2))); // quasi-static charge of source terminal
|
||||
QD = np*(-`CG0)*(VGTS+VGTD)*sqrt((pow(numD,2)+pow(((1+ksiD)*`Vmin/6),2))/(pow(den,2)+pow(`Vmin,2))); // quasi-static charge of drain terminal
|
||||
QG = -(QS+QD); // The quasi-static charge of gate terminal is inverted sum of the quasi-static charges of source and drain terminals (charge conservation)
|
||||
|
||||
// (capacitive) currents due to variation of quasi-static charges.
|
||||
// Currents are summed to virtual node "virtualNode".
|
||||
// The sum of currents is zero, but numerical rounding can cause non-zero net flow of currents into the virtualNode. Therefore, the virtualNode is grounded.
|
||||
I(G,virtualNode) <+ ddt(QG)*min(1,selectQS); // (capacitive) current in gate terminal due to variation of the gate quasi-static charge
|
||||
I(S,virtualNode) <+ ddt(QS)*min(1,selectQS); // (capacitive) current in source terminal due to variation of the source quasi-static charge
|
||||
I(D,virtualNode) <+ ddt(QD)*min(1,selectQS); // (capacitive) current in drain terminal due to variation of the drain quasi-static charge
|
||||
V(virtualNode) <+ 0; // ground the virtual node
|
||||
|
||||
/* ============ Overlap capacitances ============ */
|
||||
// Overlap capacitances usually dominate over quasi-static and other capacitances in TFT
|
||||
// COV=CI*W*LOV [F] = Overlap capacitance between gate conductor and drain/source contact pad. These COV are the dominant capacitances in TFT, since LOV>(2-3)L.
|
||||
I(G,S) <+ `COV * ddt(V(G)-V(S)); // Gate-source overlap capacitance
|
||||
I(G,D) <+ `COV * ddt(V(G)-V(D)); // Gate-grain overlap capacitance
|
||||
// CDSOV=W*2*eBov*eo/pi ~ 2*`CL*W*L [F] is geometrical capacitance between drain and source contact pads. It is small, not exceeding twice the fringing capacitance at the "back" of the semiconducting film
|
||||
I(D,S) <+ `CDSOV * ddt(V(D)-V(S)); // Drain-source overlap capacitance (usually negligible)
|
||||
|
||||
|
||||
/* ============ Monitor of quantities ============ */
|
||||
// If you wish monitoring internal quantities in the oTFT model, then use test nodes testGND and testSIGNAL. Examples are given below.
|
||||
// The test terminals are available, if instantiating the oTFT model with the test nodes, e.g.
|
||||
// module oTFT(G,S,D,GI,SI,DI,testGND,testSIGNAL); // oTFT model with all nodes available
|
||||
// module oTFT(G,S,D,testGND,testSIGNAL); // oTFT model with terminal and test nodes available
|
||||
// The test terminals can be used pushing current from testGND to testSIGNAL. Connect testGND to circuit ground.
|
||||
// Connect 1 Ohm resistor between testSIGNAL and ground and monitor the current through the resistor.
|
||||
// (Missing to connect testGND and testSIGNAL to a circuit, it will possibly force the simulator to place gmin to these nodes, or ground the nodes. Do not care, because
|
||||
// the test nodes are isolated from the model, and the oTFT model will properly operate.)
|
||||
|
||||
// I(testGND, testSIGNAL) <+ 0; // The default is monitoring nothing. Uncomment one of the following lines to monitor one of the quantities in the oTFT model.
|
||||
|
||||
// monitor contact voltage drop
|
||||
//I(testGND, testSIGNAL) <+ (+np*(V(SI)-V(S))); // monitor voltage magnitude on source contact, converted to current, 1A=1V. It duplicates monitoring of potentials by all-node instantiation oTFT(G,S,D,GI,SI,DI...)
|
||||
//I(testGND, testSIGNAL) <+ (-np*(V(DI)-V(D))); // monitor voltage magnitude on drain contact, converted to current, 1A=1V. It duplicates monitoring of potentials by all-node instantiation oTFT(G,S,D,GI,SI,DI...)
|
||||
//I(testGND, testSIGNAL) <+ (V(SI)-V(S))-(V(DI)-V(D)); // monitor sum of voltage drops on both source and train contacts, converted to current, 1A=1V.
|
||||
|
||||
|
||||
// monitor quasi-static charges
|
||||
// I(testGND, testSIGNAL) <+ np*(+QG/(`CG0*VGTS)); // = (2+gamma)/(3+gamma) = 0.72222 for gamma=0.6 in saturation regime
|
||||
// I(testGND, testSIGNAL) <+ np*(-QS/(`CG0*VGTS)); // = (2+gamma)/(5+2gamma) = 0.41935 for gamma=0.6 in saturation regime
|
||||
// I(testGND, testSIGNAL) <+ np*(-QD/(`CG0*VGTS)); // = (2+gamma)^2/[(2+gamma)*(5+2gamma)] = 0.30287 for gamma=0.6 in saturation regime
|
||||
|
||||
|
||||
// monitor quasi-static capacitances. Connect an AC source with unit amplitude (A=1) and frequency (f, as set by AC simulation) at one (x) of the TFT terminals, x=gate, drain or source.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QG)/(`CG0 * `M_TWO_PI); // normalized CGx/CG0 * f : gate capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QS)/(`CG0 * `M_TWO_PI); // normalized CSx/CG0 * f : source capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QD)/(`CG0 * `M_TWO_PI); // normalized CDx/CG0 * f : drain capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
|
||||
// I(testGND, testSIGNAL) <+ I(virtualNode); // monitor numerical error for (capacitive) currents in the quasi-static model. Ideally, I(virtualNode) = ddt(QG) + ddt(QS) + ddt(QD) = 0.
|
||||
|
||||
|
||||
end // of "analog begin"
|
||||
|
||||
endmodule // module oTFT;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# run.do
|
||||
|
||||
add wave -r *
|
||||
run -all
|
||||
quit
|
||||
@@ -0,0 +1,23 @@
|
||||
VA_FILE = demo.va
|
||||
TOP_LEVEL_MODULE = tb_rdot
|
||||
|
||||
CMD_FILE = demo.cmd
|
||||
DO_FILE = run.do
|
||||
OUT_FILE = demo.wdb
|
||||
|
||||
|
||||
|
||||
sim:
|
||||
valog $(VA_FILE)
|
||||
vasim -c -cmd $(CMD_FILE) -do $(DO_FILE) $(TOP_LEVEL_MODULE)
|
||||
|
||||
ezwave:
|
||||
ezwave -now -loc 10 10 -width 2400 -height 1200 -tcl create_plots.tcl
|
||||
|
||||
clean:
|
||||
rm DefaultVlogALib -rf
|
||||
rm *.chi *.log *.id *.reuse *.wdb -rf
|
||||
rm simcommand transcript* dok_code* -rf
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ausführen des Simulators
|
||||
vasim -c -cmd <Name_CMD>.cmd -do run.do <Name_Testbench>
|
||||
# Kompilieren der Testbench
|
||||
valog <quellcode-name>
|
||||
@@ -0,0 +1,34 @@
|
||||
############################################################
|
||||
## EZwave - Saved Window File
|
||||
## Tuesday, June 15, 2021 at 1:09:57 AM CEST
|
||||
##
|
||||
## Note: This is an auto-generated file.
|
||||
##
|
||||
## In case of modification, Do not remove this comment
|
||||
############################################################
|
||||
|
||||
onerror {resume}
|
||||
|
||||
# ===== Open required Database =====
|
||||
dataset open /users/ads1/schmidtsi76327/linux/esy1a/LCD_EPD_Simulation_VerilogA/epaper/4_2_rdot_pixel/demo.wdb demo
|
||||
|
||||
# ====== Create the expressions =====
|
||||
wfc {wf0=wf(":tb_rdot:pixel1:Rppy:p", " -show TRAN.v -terminals ")-wf(":tb_rdot:pixel1:Rppy:n", " -show TRAN.v -terminals ")}
|
||||
|
||||
|
||||
# ===== Open the window =====
|
||||
wave addwindow -x 0 -y 0 -width 1167 -height 581 -divider 0.67
|
||||
|
||||
# ===== Create row #1 =====
|
||||
add wave -show TRAN.v -color -16711936 -separator : -terminals :tb_rdot:pixel1:con
|
||||
|
||||
|
||||
# ===== Create row #2 =====
|
||||
add wave -show TRAN.v -color -256 -separator : -terminals :tb_rdot:pixel1:gate
|
||||
|
||||
|
||||
# ===== Create row #3 =====
|
||||
add wave -show none.v -notop -color -65281 -label V(Rddy) -signals wf0
|
||||
|
||||
|
||||
# ====== Create the cursors, markers and measurements =====
|
||||
@@ -0,0 +1,3 @@
|
||||
* tran_x.cmd
|
||||
|
||||
.tran 1u 10
|
||||
@@ -0,0 +1,57 @@
|
||||
// Simulation EPaper Cell
|
||||
|
||||
`include "disciplines.vams"
|
||||
`include "constants.vams"
|
||||
`include "otft.va"
|
||||
|
||||
|
||||
module myfet(d, g, s);
|
||||
inout electrical d, g, s;
|
||||
parameter real kp = 1m;
|
||||
parameter real vt = 1;
|
||||
real vgst;
|
||||
real cur;
|
||||
analog begin
|
||||
vgst = V(g,s)-vt;
|
||||
cur = 0.0;
|
||||
if (vgst > 0)
|
||||
if (vgst > V(d,s))
|
||||
cur = (vgst-0.5*V(d,s))*V(d,s);
|
||||
else
|
||||
cur = 0.5*pow(vgst, 2);
|
||||
I(d,s) <+ kp*cur;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
module rdot_pixel(vs, gate, gnd);
|
||||
electrical vs, gate, gnd;
|
||||
electrical con;
|
||||
|
||||
myfet FET1(con, gate, gnd);
|
||||
|
||||
resistor #(.r(2075)) Rppy(vs, con);
|
||||
capacitor #(.c(500u)) Cppy(vs, con);
|
||||
|
||||
endmodule
|
||||
|
||||
module tb_rdot;
|
||||
electrical src_gate, src_vs, gnd;
|
||||
ground gnd;
|
||||
|
||||
parameter real on_V = 10.0;
|
||||
parameter real off_V = 0;
|
||||
|
||||
parameter real on_T = 2; // 2s on after 1s delay
|
||||
parameter real off_T = 0;
|
||||
parameter real startDelay = 1;
|
||||
|
||||
// Puls-Quelle
|
||||
/*prameters expected for 'pulse' are '[dc] [mag [phase]] val0 val1 [td [rise [fall [width [period]]]]] */
|
||||
vpulse #(.val0(off_V), .val1(on_V), .td(startDelay), .rise(1n), .fall(1n), .width(on_T)) PL(src_gate, gnd);
|
||||
|
||||
vdc #(.dc(1.0)) VDC1 (src_vs, gnd);
|
||||
// Pixel
|
||||
rdot_pixel pixel1(src_vs, src_gate, gnd);
|
||||
endmodule
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,286 @@
|
||||
// VerilogA for oTFT 2.04.01, veriloga
|
||||
// Citation/Acknowledgment text:
|
||||
// O. Marinov, "Verilog-A Implementation of the Compact Model 'oTFT' for Organic Thin-Film Transistors", Nano-Engineered Electronic Device Simulation Node (NEEDS), oTFT ver. 2.04.01, May 2015
|
||||
// https://nanohub.org/groups/needs/compact_models
|
||||
// Revision history:
|
||||
// Implemented on 24 April 2015 by O. Marinov
|
||||
// Modified on 7 May 2015 by O. Marinov (comments in code enhanced, monitor voltage drop on both contacts added)
|
||||
// Modified on 14 May 2015 by O. Marinov (monitor commented, to prepare the code for release)
|
||||
// Modified on 14 June 2015 by O. Marinov (redundant electrical nodes GTS and GTD are removed, since the effective overdrive voltages are in variables VGTS and VGTD)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------------
|
||||
Copyright @ 2015 Ognian Marinov.
|
||||
|
||||
The terms under which the software and associated documentation (the Software) is provided are as the following:
|
||||
|
||||
The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
|
||||
|
||||
Ognian Marinov grants, free of charge, to any users the right to modify, copy, and redistribute the Software, both within the user's organization and externally, subject to the following restrictions:
|
||||
|
||||
1. The users agree not to charge for the code itself but may charge for additions, extensions, or support.
|
||||
|
||||
2. In any product based on the Software, the users agree to acknowledge the Research Group that developed the software. This acknowledgment shall appear in the product documentation.
|
||||
|
||||
3. The users agree to obey all U.S. Government restrictions governing redistribution or export of the software.
|
||||
|
||||
4. The users agree to reproduce any copyright notice which appears on the software on any copy or modification of such made available to others.
|
||||
|
||||
Agreed to by
|
||||
Ognian Marinov
|
||||
25 April 2015
|
||||
-------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Summary
|
||||
The oTFT compact models are aimed to support the bias enhancement of the charge carrier mobility and the significant contact effect in organic thin-film transistors (OTFTs).
|
||||
|
||||
The current version 2.04.01 of the oTFT compact model level 2 also supports other effects, such as channel conductance modulation (analogous to the channel length modulation in MOS transistors) and Ohmic and non-linear leakages. Quasi-static charge sub-model supports frequency and temporal response by AC and transient simulations.
|
||||
|
||||
The model is with default values of parameters for organic thin-film transistors, but otherwise, the oTFT models are also applicable to other thin-film transistors (TFTs). Just the model parameters are with other values.
|
||||
|
||||
The oTFT models are ?mirror? of the TFT structure. In the TFT structure and oTFT model, one distinguishes an intrinsic TFT between intrinsic nodes GI, SI, DI, and the intrinsic TFT is connected to the device terminals (gate G, source S, drain D) by contacts of significant impacts. Conceptually, the oTFT models are arranged so that the sub-model components can be changed, replaced, removed or upgraded, as the needs evolve.
|
||||
|
||||
The oTFT models are hierarchical. The top hierarchical level is module oTFT, in which there are ?rails? for interconnection of the sub-models and instantiations of the sub-models between the rails. One rail is with the device terminals G,S,D and another rail is with the internal nodes GI,SI,DI. There is also a control rail with overdrive voltages VGTS=(VG-VT-VS) and VGTD=(VG-VT-VD) at the channel ends of the intrinsic TFT. In the current Verilog-A code, there is a rail with nodes testGND, testSIGNAL for monitoring of internal quantities.
|
||||
|
||||
The advantages of the hierarchical structure are several, but perhaps the most practical advantage is that the sub-models are simple, and well tied to diverse physical interpretations. Therefore, the oTFT model can be managed by researches far from the field of compact modeling and semiconductors, e.g., researchers in chemistry.
|
||||
The oTFT model is arranged so that the different effects can be suppressed by setting model parameters to specific values, usually, equal to zero.
|
||||
|
||||
The current version "oTFT 2.04.01" of the oTFT compact models is based on the following publications:
|
||||
[1] O. Marinov, M. J. Deen, U. Zschieschang, H. Klauk, "Organic Thin-Film Transistors: Part I-Compact DC Modeling", IEEE Trans. Electron Devices, 56(12), 2952-2961, 2009 ; DOI: 10.1109/TED.2009.2033308
|
||||
[2] M. J. Deen, O. Marinov, U. Zschieschang, H. Klauk, "Organic Thin-Film Transistors: Part II-Parameter Extraction", IEEE Trans. Electron Devices, 56(12), 2962-2968, 2009 ; DOI: 10.1109/TED.2009.2033309
|
||||
[3] O. Marinov, M. J. Deen, J. Tejada, B. Iniguez, "Impact of the Fringing Capacitance at the Back of Thin-Film Transistors", Organic Electronics, 12(6), 936-949, 2011 ; DOI: 10.1016/j.orgel.2011.02.020
|
||||
[4] O. Marinov, M. J. Deen, "Quasistatic Compact Modelling of Organic Thin-Film Transistors", Organic Electronics, 14(1), 295-311, 2013 ; DOI: 10.1016/j.orgel.2012.10.031
|
||||
[5] O. Marinov, M. J. Deen, C. Feng, Y. Wu, "Precise Parameter Extraction Technique for Organic Thin-Film Transistors Operating in the Linear Regime", Journal of Applied Physics, 115(3), 034506, 2014 ; DOI: 10.1063/1.4862043
|
||||
[6] O. Marinov, "Compact Models for Organic Thin-Film Transistors: Similarities, Differences, and Principles and Philosophy behind the Models", unpublished reviews and derivations, 127 pages, 2010
|
||||
|
||||
Several adjustments in the equations from these publications have been made to ensure wide range of bias voltages and to avoid numerical problems, such as division by zero and discontinuity of derivatives.
|
||||
|
||||
The suppression of the sub-models is by the following settings, which can be made by instantiation of the oTFT model in circuits:
|
||||
|
||||
Set gamma = 0 to suppress bias enhancement of mobility
|
||||
Set eB=0 to suppress channel modulation model
|
||||
Set eBleak=0 and RBS=10.0e30 (or larger) to suppress the leakage sub-model
|
||||
Set RC=1 and RCmax=0 to suppress the contact resistance model
|
||||
Set selectQS=0 to suppress quasi-static capacitances
|
||||
Set LOV=0 to suppress overlap capacitances between gate conductor and drain/source terminals
|
||||
Set eBov=0 to suppress the geometric capacitance between drain and source terminals
|
||||
|
||||
If only the G,S,D terminals of the TFT are desired (e.g., for circuit simulation), then shorten the list of terminals by the definition of the oTFT module - see below
|
||||
*/
|
||||
|
||||
|
||||
/* =================== Begin of the Verilog-A code of compact model "oTFT" ========================================= */
|
||||
`include "constants.vams"
|
||||
`include "disciplines.vams"
|
||||
|
||||
|
||||
// Uncomment one of the following three lines, in order to have the oTFT model with reduced access nodes by instantiation.
|
||||
|
||||
module oTFT(G,S,D); //The simplest 3-terminal oTFT model, only with nodes G,S,D for gate, source and drain terminals, respectively (use for circuit simulations)
|
||||
// module oTFT(G,S,D,GI,SI,DI); // oTFT model with terminal and intrinsic nodes available (no test terminals for inspection of internal quantities of the model)
|
||||
// module oTFT(G,S,D,testGND,testSIGNAL); //oTFT model with terminal and test nodes available (change the end of the code to select and route quantity to the test terminals)
|
||||
|
||||
//module oTFT(G,S,D,GI,SI,DI,testGND,testSIGNAL); // oTFT model with all nodes available (for research and troubleshooting). Comment this line, if one of the above three lines is uncommented.
|
||||
parameter real version_oTFT = 2.0401; // oTFT model version = 2.04.01
|
||||
|
||||
electrical G,D,S; // terminals of the TFT for connection in circuits
|
||||
electrical GI,DI,SI; // internal terminals of the TFT channel, for inspection only
|
||||
electrical virtualNode; // virtual node for summing capacitive currents of the quasi-static model. The node is grounded, since the sum of currents to this node is zero +/- numerical errors
|
||||
|
||||
// electrical testGND, testSIGNAL; // test nodes for monitoring, isolated from the oTFT model. See and modify end of the code to select and route quantity to the test terminals
|
||||
|
||||
parameter integer np=+1 from [-1:1] exclude 0; //TFT polarity, np=+1 for n-type TFT, np=-1 for p-type TFT
|
||||
parameter real W=100.0e-6 from (0:inf); // channel width in [m] (default W=100um)
|
||||
parameter real L=10.00e-6 from (0:inf); // channel length in [m] (default L=10um)
|
||||
parameter real CI=0.00035 from [0:inf); // unit-area capacitance of the gate dielectric in [F/m^2]; 0.00035F/m^2 = 35nF/cm^2 (default, 100nm SiO2)
|
||||
parameter real VT=0 from (-inf:inf); // threshold voltage in [V] with its polarity (default VT=0 V)
|
||||
parameter real uo=0.1e-4 from (0:inf); // (low-field) mobility in [m^2/Vs] at gate overdrive Vgamma=1V=np*(VGgamma-VT). Default uo=0.1e-4 m^2/Vs=0.1 cm^2/Vs.
|
||||
parameter real Vgamma=1.0 from (0:inf); // Gate overdrive voltage in [V] for uo. Default, Vgamma = 1.0 V.
|
||||
parameter real gamma=0.6 from [0:inf); // Mobility enhancement factor [numerical exponent]. Default, gamma=max(0,2*To/T-2)=0.6, for To~400K and T~300K.
|
||||
|
||||
parameter real VSS=1.0 from (0:inf); // sub-threshold slope voltage in [V], VSS[V/Np]=dV/d(ln(ID))= 0.43(gamma+2)V/dec = V/dec for gamma=0.33.
|
||||
|
||||
|
||||
// parameters for terminal to channel contacts
|
||||
parameter real RC=100.0e3 from (0:inf); // minimum contact resistance at one contact (to the channel)
|
||||
parameter real RCmax=300.0e3 from [0:inf); // elevation of contact resistance at low currents. Typically, RCmax=3*RC. RCmax=0 for constant resistance=RC.
|
||||
parameter real ICmax=1e-9 from (0:inf); // max current for max contact resistance of value=(RC+RCmax). Typically, ICmax is in nA-range.
|
||||
parameter real nIC=0.75 from [0.125:4]; // reduction exponent for RCmax. Meaningful values: nIC=0.5=SCLC; nIC=1=constant voltage drop.
|
||||
|
||||
parameter real RGmin=1.0 from (0:inf); // negligible gate contact resistance.
|
||||
// Unlikely necessary, but one can increase RGmin in kOhm-MOhm range to introduce a pole in the frequency response of the transconductance gm=dIDS/dVGS
|
||||
|
||||
|
||||
// parameters for channel modulation
|
||||
parameter integer nSCLC=4 from [4:5] exclude 5; // Selector for channel modulation model. nSCLC=4 is only implemented: gamma model with CL=eB*eo/pi/L
|
||||
parameter real eB=2 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film, eB~2, for channel modulation.
|
||||
`define CL eB * `P_EPS0 / `M_PI / L
|
||||
//CL=eB*eo/pi/L, fringing capacitance in the back of the semiconducting film, eB~2
|
||||
|
||||
// parameters for leakage
|
||||
parameter real eBleak=0.5 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film, eBleak~0.5 ~ (eB~2)/4, for leakage.
|
||||
// eBleak is used to calculate fringing capacitance CLL=eBleak*eo/pi/L in the back of the semiconducting film for leakage.
|
||||
`define CLL eBleak * `P_EPS0 / `M_PI / L
|
||||
parameter real VTL=0 from (-inf:inf); // threshold voltage in [V] with its polarity for leakage, ideally VTL=VT (default VTL=0 V)
|
||||
parameter real RBS=10.0e12 from (0:inf); // [Ohm/square] Sheet resistance of the bulk of the semiconducting film, for Ohmic leakage
|
||||
`define Vmin 10.0e-6
|
||||
//Vmin [V] should be about 2-4 times the absolute tolerance for voltage of the simulator
|
||||
|
||||
|
||||
// Quasi-static model parameters.
|
||||
// The quasi-static model is for static charges, not for capacitances. Geometrical (overlap) capacitances are added.
|
||||
// In principle, DC parameters should fully determine the quasi-static model. For convenience, constants are defined
|
||||
`define CG0 W*L*CI
|
||||
// CG0 [F] is the gate dielectric capacitance over the entire channel area of the TFT. CG0="CG zero"
|
||||
parameter integer selectQS=1 from [0:1]; // selectQS=0 suppresses the quasi-static capacitances. The quasi-static charges are still calculated.
|
||||
|
||||
// Overlap capacitances (usually dominate over quasi-static and other capacitances in TFT)
|
||||
parameter real LOV=30.0e-6 from [0:inf); // Geometrical overlap of gate conductor with drain/source contact pad. LOV is approximately the length of the pads perpendicular to channel width W
|
||||
`define COV CI*W*LOV
|
||||
// COV=CI*W*LOV [F] = Overlap capacitance between gate conductor and drain/source contact pad. These COV are the dominant capacitances in TFT, since LOV>(2-3)L.
|
||||
parameter real eBov=1 from [0:inf); //relative permittivity of the medium in the back of the semiconducting film for geometrical capacitance between drain and source terminals, eBov~1 ~ (eB~2)/2.
|
||||
`define CDSOV W * 2 * eBov * `P_EPS0 / `M_PI
|
||||
// CDSOV [F] is geometrical capacitance between drain and source contact pads. It is small, not exceeding twice the fringing capacitance at the "back" of the semiconducting film
|
||||
|
||||
// variables
|
||||
real VGTS, VGTD; // for generic TFT charge drift DC model, etc. VGTS~np*(VG-VT-VS) and VGTD~np*(VG-VT-VD) are overdrive voltages at source and drain ends of the intrinsic channel of the TFT
|
||||
real VSSS, VSSD; // sub-threshold slope voltage for VGTS and VGTD. In sub-threshold regime VSSS=VSSD=VSS. Above threshold, VSSS=VSS+VGTS/32 and VSSD=VSS+VGTD/32, to ensure no overflow of exp(VGT_/VSS_), _=S or D
|
||||
real IDSgen; // Channel current per the generic TFT charge drift DC model
|
||||
real numerator, denominator, fDeltaID; // for channel modulation
|
||||
real VSSSLF, VGTSLF, VSSDLF, VGTDLF; // VSS_ and VGT_for forward leakage diode. (See above VGTS, VGTD, VSSS and VSSD)
|
||||
real VSSSLR, VGTSLR, VSSDLR, VGTDLR; // VSS_ and VGT_for reverse leakage diode. (See above VGTS, VGTD, VSSS and VSSD)
|
||||
real contactIC, contactVC; // current and voltage across one contact of drain/source terminals
|
||||
real QG,QS,QD; // quasi-static charges of gate, source and drain terminals
|
||||
real ksiS, ksiD, ksiG; // normalized overdrive voltages for quasi-static charges
|
||||
real den, numS, numD; // denominator and numerators of the normalized functions of QS and QD
|
||||
|
||||
analog begin
|
||||
|
||||
/* ============ Generic TFT charge drift DC model ============ */
|
||||
|
||||
// Source overdrive voltage
|
||||
VSSS = sqrt(pow(VSS,2) + pow((np*(V(GI) - VT - V(SI)) + abs(V(GI) - VT - V(SI)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTS = VSSS * ln(1+exp(np*(V(GI) - VT - V(SI))/VSSS)); // Source overdrive voltage
|
||||
|
||||
// Drain overdrive voltage
|
||||
VSSD = sqrt(pow(VSS,2) + pow((np*(V(GI) - VT - V(DI)) + abs(V(GI) - VT - V(DI)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTD = VSSD * ln(1+exp(np*(V(GI) - VT - V(DI))/VSSD)); // Drain overdrive voltage
|
||||
|
||||
// Generic TFT charge drift DC model
|
||||
I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*CI*(pow(VGTS,gamma+2)-pow(VGTD,gamma+2))/(gamma+2); // Generic TFT charge drift DC model
|
||||
|
||||
|
||||
/* ============ Contact model ============ */
|
||||
// Connect TFT terminals to intrinsic nodes through contact resistances. The model for contact resistance is R(I)=RC+Rmax*(ICmax/(ICmax+|I|))^nIC
|
||||
V(G,GI) <+ RGmin*I(G,GI); // negligible gate contact resistance
|
||||
V(G,GI) <+ 0 *I(G,GI) * pow(ICmax/(ICmax + abs(I(G,GI))),nIC); // non-linear gate contact resistance is set to zero (ignored)
|
||||
V(S,SI) <+ RC * I(S,SI); // constant (minimum) source contact resistance
|
||||
V(S,SI) <+ RCmax*I(S,SI) * pow(ICmax/(ICmax + abs(I(S,SI))),nIC); // non-linear source contact resistance
|
||||
V(D,DI) <+ RC * I(D,DI); // constant (minimum) drain contact resistance
|
||||
V(D,DI) <+ RCmax*I(D,DI) * pow(ICmax/(ICmax + abs(I(D,DI))),nIC); // non-linear drain contact resistance
|
||||
|
||||
/* ============ Channel modulation ============ */
|
||||
I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CL*(pow(VGTS,gamma+2)-pow(VGTD,gamma+2))/(gamma+2); // first component of channel modulation current
|
||||
I(DI,SI) <+ W/L*uo/pow(Vgamma,gamma)*6*`CL*(V(DI)/2+V(SI)/2-V(GI)+VT)*(pow(VGTS,gamma+1)-pow(VGTD,gamma+1))/(gamma+1); // second component of channel modulation current
|
||||
numerator = abs(pow(VGTS,3+2*gamma)-(3+2*gamma)*pow(VGTS,2+gamma)*pow(VGTD,1+gamma)+(3+2*gamma)*pow(VGTS,1+gamma)*pow(VGTD,2+gamma)-pow(VGTD,3+2*gamma));
|
||||
denominator = abs(pow(VGTS,2+gamma)-pow(VGTD,2+gamma)) + pow((1+3)*`Vmin,2+gamma); // small voltage (1+3)*`Vmin~40uV added to avoid division on zero
|
||||
fDeltaID = numerator/denominator;
|
||||
I(DI,SI) <+ W/L*uo/pow(Vgamma,gamma)*6*`CL*(V(DI)-V(SI))*fDeltaID/2/(gamma+1)/(3+2*gamma); // third component of channel modulation current
|
||||
|
||||
/* ============ Channel leakage ============ */
|
||||
// The leakage and off currents between drain and source terminals are defined as currents independent of gate bias
|
||||
// The leakage model is based on back-film capacitance CLL=eBleak*eo/pi/L, eBleak~0.5 ~ (eB~2)/4
|
||||
// resulting in anti-parallel connection of two TFT diodes for leakage due to CLL. The "gate" capacitance of these two leakage TFT is CI=6CLL
|
||||
// Resistor RBS*L/W is also added for Ohmic leakage between drain and source, due to conductance of the bulk of the semiconducting film.
|
||||
|
||||
// Ohmic (linear) leakage
|
||||
I(D,S) <+ V(D,S) * W / L / RBS; // Ohmic leakage in the bulk of the semiconducting film, between D and S
|
||||
//I(DI,SI) <+ V(DI,SI) * W / L / RBS; // Ohmic leakage in the bulk of the semiconducting film, between DI and SI
|
||||
|
||||
// Forward leakage diode
|
||||
VSSSLF = sqrt(pow(VSS,2) + pow((np*(V(D) - VTL - V(S)) + abs(V(D) - VTL - V(S)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTSLF = VSSSLF * ln(1+exp(np*(V(D) - VTL - V(S))/VSSSLF)); // Source overdrive voltage for forward leakage diode
|
||||
VSSDLF = sqrt(pow(VSS,2) + pow((np*(V(D) - VTL - V(D)) + abs(V(D) - VTL - V(D)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTDLF = VSSDLF * ln(1+exp(np*(V(D) - VTL - V(D))/VSSDLF)); // Drain overdrive voltage for forward leakage diode
|
||||
I(D,S) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLF,gamma+2)-pow(VGTDLF,gamma+2))/(gamma+2); // TFT generic for forward leakage diode, between D and S
|
||||
//I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLF,gamma+2)-pow(VGTDLF,gamma+2))/(gamma+2); // TFT generic for forward leakage diode, between DI and SI
|
||||
|
||||
// Reverse leakage diode
|
||||
VSSSLR = sqrt(pow(VSS,2) + pow((np*(V(S) - VTL - V(S)) + abs(V(S) - VTL - V(S)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTSLR = VSSSLR * ln(1+exp(np*(V(S) - VTL - V(S))/VSSSLR)); // Source overdrive voltage for reverse leakage diode
|
||||
VSSDLR = sqrt(pow(VSS,2) + pow((np*(V(S) - VTL - V(D)) + abs(V(S) - VTL - V(D)))/64,2)); // To ensure VGT_/VSS_ <32, so that not overflowing exp(VGT_/VSS_) at high bias and small VSS
|
||||
VGTDLR = VSSDLR * ln(1+exp(np*(V(S) - VTL - V(D))/VSSDLR)); // Drain overdrive voltage for reverse leakage diode
|
||||
I(D,S) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLR,gamma+2)-pow(VGTDLR,gamma+2))/(gamma+2); // TFT generic for reverse leakage diode, between D and S
|
||||
//I(DI,SI) <+ np*W/L*uo/pow(Vgamma,gamma)*6*`CLL*(pow(VGTSLR,gamma+2)-pow(VGTDLR,gamma+2))/(gamma+2); // TFT generic for reverse leakage diode, between DI and SI
|
||||
|
||||
|
||||
/* ============ Quasi-static charge model ============ */
|
||||
//Generic quasi-static charge model of the TFT for computer simulators. QG, QS and QD are the quasi-static charges of gate, source and drain terminals
|
||||
|
||||
// normalized overdrive voltages: ksiS = VGTS/(VGTS+VGTD); ksiD = VGTD/(VGTS+VGTD);
|
||||
ksiS = sqrt(pow(VGTS,2)+pow(`Vmin,2)) / (sqrt(pow(VGTS,2)+pow(`Vmin,2))+sqrt(pow(VGTD,2)+pow(`Vmin,2))); // normalized overdrive voltages for source
|
||||
ksiD = sqrt(pow(VGTD,2)+pow(`Vmin,2)) / (sqrt(pow(VGTS,2)+pow(`Vmin,2))+sqrt(pow(VGTD,2)+pow(`Vmin,2))); // normalized overdrive voltages for drain
|
||||
ksiG = ksiS + ksiD; // this quantity should be always equal to unity. Not used, therefore
|
||||
|
||||
// den, numS, numD; // denominator and numerators of the normalized functions of QS and QD
|
||||
den = pow((pow(ksiS,(2+gamma))/(2+gamma)-pow(ksiD,(2+gamma))/(2+gamma)),2); // denominator of the normalized functions of QS and QD
|
||||
numS = (pow(ksiS,5+2*gamma)/(5+2*gamma))/(2+gamma)-(pow(ksiS,3+gamma)/(3+gamma))*(pow(ksiD,2+gamma)/(2+gamma))+(pow(ksiD,5+2*gamma)/(5+2*gamma))/(3+gamma); // numerator of the normalized function of QS
|
||||
numD = (pow(ksiS,5+2*gamma)/(5+2*gamma))/(3+gamma)-(pow(ksiS,2+gamma)/(2+gamma))*(pow(ksiD,3+gamma)/(3+gamma))+(pow(ksiD,5+2*gamma)/(5+2*gamma))/(2+gamma); // numerator of the normalized function of QD
|
||||
|
||||
// real QG,QS,QD; // quasi-static charges of gate, source and drain terminals
|
||||
QS = np*(-`CG0)*(VGTS+VGTD)*sqrt((pow(numS,2)+pow(((1+ksiS)*`Vmin/6),2))/(pow(den,2)+pow(`Vmin,2))); // quasi-static charge of source terminal
|
||||
QD = np*(-`CG0)*(VGTS+VGTD)*sqrt((pow(numD,2)+pow(((1+ksiD)*`Vmin/6),2))/(pow(den,2)+pow(`Vmin,2))); // quasi-static charge of drain terminal
|
||||
QG = -(QS+QD); // The quasi-static charge of gate terminal is inverted sum of the quasi-static charges of source and drain terminals (charge conservation)
|
||||
|
||||
// (capacitive) currents due to variation of quasi-static charges.
|
||||
// Currents are summed to virtual node "virtualNode".
|
||||
// The sum of currents is zero, but numerical rounding can cause non-zero net flow of currents into the virtualNode. Therefore, the virtualNode is grounded.
|
||||
I(G,virtualNode) <+ ddt(QG)*min(1,selectQS); // (capacitive) current in gate terminal due to variation of the gate quasi-static charge
|
||||
I(S,virtualNode) <+ ddt(QS)*min(1,selectQS); // (capacitive) current in source terminal due to variation of the source quasi-static charge
|
||||
I(D,virtualNode) <+ ddt(QD)*min(1,selectQS); // (capacitive) current in drain terminal due to variation of the drain quasi-static charge
|
||||
V(virtualNode) <+ 0; // ground the virtual node
|
||||
|
||||
/* ============ Overlap capacitances ============ */
|
||||
// Overlap capacitances usually dominate over quasi-static and other capacitances in TFT
|
||||
// COV=CI*W*LOV [F] = Overlap capacitance between gate conductor and drain/source contact pad. These COV are the dominant capacitances in TFT, since LOV>(2-3)L.
|
||||
I(G,S) <+ `COV * ddt(V(G)-V(S)); // Gate-source overlap capacitance
|
||||
I(G,D) <+ `COV * ddt(V(G)-V(D)); // Gate-grain overlap capacitance
|
||||
// CDSOV=W*2*eBov*eo/pi ~ 2*`CL*W*L [F] is geometrical capacitance between drain and source contact pads. It is small, not exceeding twice the fringing capacitance at the "back" of the semiconducting film
|
||||
I(D,S) <+ `CDSOV * ddt(V(D)-V(S)); // Drain-source overlap capacitance (usually negligible)
|
||||
|
||||
|
||||
/* ============ Monitor of quantities ============ */
|
||||
// If you wish monitoring internal quantities in the oTFT model, then use test nodes testGND and testSIGNAL. Examples are given below.
|
||||
// The test terminals are available, if instantiating the oTFT model with the test nodes, e.g.
|
||||
// module oTFT(G,S,D,GI,SI,DI,testGND,testSIGNAL); // oTFT model with all nodes available
|
||||
// module oTFT(G,S,D,testGND,testSIGNAL); // oTFT model with terminal and test nodes available
|
||||
// The test terminals can be used pushing current from testGND to testSIGNAL. Connect testGND to circuit ground.
|
||||
// Connect 1 Ohm resistor between testSIGNAL and ground and monitor the current through the resistor.
|
||||
// (Missing to connect testGND and testSIGNAL to a circuit, it will possibly force the simulator to place gmin to these nodes, or ground the nodes. Do not care, because
|
||||
// the test nodes are isolated from the model, and the oTFT model will properly operate.)
|
||||
|
||||
//I(testGND, testSIGNAL) <+ 0; // The default is monitoring nothing. Uncomment one of the following lines to monitor one of the quantities in the oTFT model.
|
||||
|
||||
// monitor contact voltage drop
|
||||
//I(testGND, testSIGNAL) <+ (+np*(V(SI)-V(S))); // monitor voltage magnitude on source contact, converted to current, 1A=1V. It duplicates monitoring of potentials by all-node instantiation oTFT(G,S,D,GI,SI,DI...)
|
||||
//I(testGND, testSIGNAL) <+ (-np*(V(DI)-V(D))); // monitor voltage magnitude on drain contact, converted to current, 1A=1V. It duplicates monitoring of potentials by all-node instantiation oTFT(G,S,D,GI,SI,DI...)
|
||||
//I(testGND, testSIGNAL) <+ (V(SI)-V(S))-(V(DI)-V(D)); // monitor sum of voltage drops on both source and train contacts, converted to current, 1A=1V.
|
||||
|
||||
|
||||
// monitor quasi-static charges
|
||||
// I(testGND, testSIGNAL) <+ np*(+QG/(`CG0*VGTS)); // = (2+gamma)/(3+gamma) = 0.72222 for gamma=0.6 in saturation regime
|
||||
// I(testGND, testSIGNAL) <+ np*(-QS/(`CG0*VGTS)); // = (2+gamma)/(5+2gamma) = 0.41935 for gamma=0.6 in saturation regime
|
||||
// I(testGND, testSIGNAL) <+ np*(-QD/(`CG0*VGTS)); // = (2+gamma)^2/[(2+gamma)*(5+2gamma)] = 0.30287 for gamma=0.6 in saturation regime
|
||||
|
||||
|
||||
// monitor quasi-static capacitances. Connect an AC source with unit amplitude (A=1) and frequency (f, as set by AC simulation) at one (x) of the TFT terminals, x=gate, drain or source.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QG)/(`CG0 * `M_TWO_PI); // normalized CGx/CG0 * f : gate capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QS)/(`CG0 * `M_TWO_PI); // normalized CSx/CG0 * f : source capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
// I(testGND, testSIGNAL) <+ ddt(QD)/(`CG0 * `M_TWO_PI); // normalized CDx/CG0 * f : drain capacitance due to voltage variation of x-terminal, x=gate, drain or source, depending where the AC source is.
|
||||
|
||||
// I(testGND, testSIGNAL) <+ I(virtualNode); // monitor numerical error for (capacitive) currents in the quasi-static model. Ideally, I(virtualNode) = ddt(QG) + ddt(QS) + ddt(QD) = 0.
|
||||
|
||||
|
||||
end // of "analog begin"
|
||||
|
||||
endmodule // module oTFT;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# run.do
|
||||
|
||||
add wave -r *
|
||||
run -all
|
||||
quit
|
||||
@@ -0,0 +1,23 @@
|
||||
VA_FILE = demo.va
|
||||
TOP_LEVEL_MODULE = demo
|
||||
|
||||
CMD_FILE = demo.cmd
|
||||
DO_FILE = run.do
|
||||
OUT_FILE = demo.wdb
|
||||
|
||||
|
||||
|
||||
sim:
|
||||
valog $(VA_FILE)
|
||||
vasim -c -cmd $(CMD_FILE) -do $(DO_FILE) $(TOP_LEVEL_MODULE)
|
||||
|
||||
ezwave:
|
||||
ezwave -now -loc 10 10 -width 2400 -height 1200 -tcl create_plots.tcl
|
||||
|
||||
clean:
|
||||
rm DefaultVlogALib -rf
|
||||
rm *.chi *.log *.id *.reuse *.wdb -rf
|
||||
rm simcommand transcript* dok_code* -rf
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
############################################################
|
||||
## EZwave - Saved Window File
|
||||
## Tuesday, June 15, 2021 at 1:00:12 AM CEST
|
||||
##
|
||||
## Note: This is an auto-generated file.
|
||||
##
|
||||
## In case of modification, Do not remove this comment
|
||||
############################################################
|
||||
|
||||
onerror {resume}
|
||||
|
||||
# ===== Open required Database =====
|
||||
dataset open /users/ads1/schmidtsi76327/linux/esy1a/LCD_EPD_Simulation_VerilogA/lcd/reflection_vs_input_voltage_lcd_cap/demo.wdb demo
|
||||
|
||||
# ====== Create the expressions =====
|
||||
|
||||
|
||||
|
||||
# ===== Open the window =====
|
||||
wave addwindow -x 0 -y 0 -width 767 -height 558 -divider 0.85
|
||||
|
||||
# ===== Create row #1 =====
|
||||
add wave -versus V(:demo:lcc:(a,b)) VAR(:demo:lcc:trans)
|
||||
|
||||
|
||||
# ====== Create the cursors, markers and measurements =====
|
||||
@@ -0,0 +1,3 @@
|
||||
* demo.cmd
|
||||
|
||||
.tran 1u 10m
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
`include "disciplines.vams"
|
||||
`include "constants.vams"
|
||||
|
||||
module myfet(d, g, s);
|
||||
inout electrical d, g, s;
|
||||
parameter real kp = 1m;
|
||||
parameter real vt = 1;
|
||||
real vgst;
|
||||
real cur;
|
||||
analog begin
|
||||
vgst = V(g,s)-vt;
|
||||
cur = 0.0;
|
||||
if (vgst > 0)
|
||||
if (vgst > V(d,s))
|
||||
cur = (vgst-0.5*V(d,s))*V(d,s);
|
||||
else
|
||||
cur = 0.5*pow(vgst, 2);
|
||||
I(d,s) <+ kp*cur;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module lccap(a,b);
|
||||
inout a,b; //Interface ports
|
||||
electrical a,b;
|
||||
electrical force_node; //Internal node
|
||||
|
||||
real vext=0;
|
||||
real vv=0;
|
||||
real vforce=0;
|
||||
|
||||
parameter real rforce=1; // Rd
|
||||
parameter real cforce=0.001; // Cd
|
||||
parameter real tau = rforce*cforce; // tau=Rd*Cd
|
||||
|
||||
real vcontrol= 0; // RMS Voltage to control the angle
|
||||
|
||||
// capacitance
|
||||
real cap = 0;
|
||||
real qlc = 0;
|
||||
parameter real cmin=2.5e-15; // C
|
||||
parameter real cmax=8.0e-15; // Cparallel
|
||||
|
||||
real alpha = 0;
|
||||
parameter real delta_sq = 0.1;
|
||||
parameter real vtc = 2;
|
||||
parameter real vmc = 0.1;
|
||||
|
||||
// transmittance / reflectance
|
||||
real beta = 0;
|
||||
real trans=0;
|
||||
|
||||
parameter real tmin = 0.01;
|
||||
parameter real eta_sq = 0.1;
|
||||
parameter real vmo = 0.9;
|
||||
parameter real vto = 2;
|
||||
|
||||
analog
|
||||
begin
|
||||
@(initial_step)
|
||||
begin
|
||||
//Initial voltage for internal node
|
||||
vforce = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
//Probing terminal voltage
|
||||
vext = V(a,b);
|
||||
vv = vext * vext;
|
||||
|
||||
// Calculation of Internal node voltage
|
||||
I(force_node) <+ ddt(cforce * V(force_node)); // current into Cd
|
||||
I(force_node) <+ (V(force_node)-vv) / rforce; // current from Rd
|
||||
vforce = V(force_node);
|
||||
vcontrol = sqrt(vforce); // calculate RMS Voltage
|
||||
|
||||
// C-V calculation
|
||||
alpha = (vcontrol - vtc) / vmc;
|
||||
cap = cmin + (2/`M_PI) * (cmax-cmin) * atan( (alpha + sqrt(alpha * alpha + delta_sq ))/2);
|
||||
qlc = cap * vext; // delta Q
|
||||
I(a,b) <+ ddt(qlc); // dQ / dt
|
||||
|
||||
// T-V calculation
|
||||
beta = (vcontrol - vto)/ vmo;
|
||||
trans = 1 - (1-tmin)*tanh( (beta+sqrt(beta*beta + eta_sq)) / 2 );
|
||||
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module demo;
|
||||
electrical src_out, gate, out, gnd;
|
||||
ground gnd;
|
||||
|
||||
analog begin
|
||||
V(out) <+ idt(6.0 * 100, 0, 0); // ramp 0-6V in 10ms
|
||||
$bound_step(10u/100); // bessere Aufloesung
|
||||
end
|
||||
|
||||
lccap lcc(out, gnd);
|
||||
endmodule
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,4 @@
|
||||
add wave -r *
|
||||
add wave -i -r *
|
||||
run -all
|
||||
quit -f
|
||||
@@ -0,0 +1,23 @@
|
||||
VA_FILE = demo.va
|
||||
TOP_LEVEL_MODULE = demo
|
||||
|
||||
CMD_FILE = demo.cmd
|
||||
DO_FILE = run.do
|
||||
OUT_FILE = demo.wdb
|
||||
|
||||
|
||||
|
||||
sim:
|
||||
valog $(VA_FILE)
|
||||
vasim -c -cmd $(CMD_FILE) -do $(DO_FILE) $(TOP_LEVEL_MODULE)
|
||||
|
||||
ezwave:
|
||||
ezwave -now -loc 10 10 -width 2400 -height 1200 -tcl create_plots.tcl
|
||||
|
||||
clean:
|
||||
rm DefaultVlogALib -rf
|
||||
rm *.chi *.log *.id *.reuse *.wdb -rf
|
||||
rm simcommand transcript* -rf
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
############################################################
|
||||
## EZwave - Saved Window File
|
||||
## Tuesday, June 15, 2021 at 12:44:25 AM CEST
|
||||
##
|
||||
## Note: This is an auto-generated file.
|
||||
##
|
||||
## In case of modification, Do not remove this comment
|
||||
############################################################
|
||||
|
||||
onerror {resume}
|
||||
|
||||
# ===== Open required Database =====
|
||||
dataset open /users/ads1/schmidtsi76327/linux/esy1a/LCD_EPD_Simulation_VerilogA/lcd/transient_response_lcd_cap/demo.wdb demo
|
||||
|
||||
# ===== Open the window =====
|
||||
wave addwindow -x 0 -y 0 -width 1490 -height 1075 -divider 0.82
|
||||
|
||||
# ===== Create row #1 =====
|
||||
add wave -overlay -show TRAN.v -color -16711936 -separator : -terminals :demo:lcc:(a,b) -show TRAN.var -color -256 -separator : -signals :demo:lcc:vcontrol
|
||||
|
||||
|
||||
# ===== Create row #2 =====
|
||||
add wave -show TRAN.var -color -16744193 -separator : -signals :demo:lcc:cap
|
||||
|
||||
|
||||
# ===== Create row #3 =====
|
||||
add wave -show TRAN.v -color -32768 -separator : -terminals :demo:gate
|
||||
|
||||
|
||||
# ====== Create the cursors, markers and measurements =====
|
||||
@@ -0,0 +1,3 @@
|
||||
* demo.cmd
|
||||
|
||||
.tran 1u 5m
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
`include "disciplines.vams"
|
||||
`include "constants.vams"
|
||||
|
||||
module myfet(d, g, s);
|
||||
inout electrical d, g, s;
|
||||
parameter real kp = 1m;
|
||||
parameter real vt = 1;
|
||||
real vgst;
|
||||
real cur;
|
||||
analog begin
|
||||
vgst = V(g,s)-vt;
|
||||
cur = 0.0;
|
||||
if (vgst > 0)
|
||||
if (vgst > V(d,s))
|
||||
cur = (vgst-0.5*V(d,s))*V(d,s);
|
||||
else
|
||||
cur = 0.5*pow(vgst, 2);
|
||||
I(d,s) <+ kp*cur;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module lccap(a,b);
|
||||
inout a,b; //Interface ports
|
||||
electrical a,b;
|
||||
electrical force_node; //Internal node
|
||||
|
||||
real vext=0;
|
||||
real vv=0;
|
||||
real vforce=0;
|
||||
|
||||
parameter real rforce=1; // Rd
|
||||
parameter real cforce=0.001; // Cd
|
||||
parameter real tau = rforce*cforce; // tau=Rd*Cd
|
||||
|
||||
real vcontrol= 0; // RMS Voltage to control the angle
|
||||
|
||||
// capacitance
|
||||
real cap = 0;
|
||||
real qlc = 0;
|
||||
parameter real cmin=2.5e-15; // C
|
||||
parameter real cmax=8.0e-15; // Cparallel
|
||||
|
||||
real alpha = 0;
|
||||
parameter real delta_sq = 0.1;
|
||||
parameter real vtc = 2;
|
||||
parameter real vmc = 0.1;
|
||||
|
||||
// transmittance / reflectance
|
||||
real beta = 0;
|
||||
real trans=0;
|
||||
|
||||
parameter real tmin = 0.01;
|
||||
parameter real eta_sq = 0.1;
|
||||
parameter real vmo = 0.9;
|
||||
parameter real vto = 2;
|
||||
|
||||
analog
|
||||
begin
|
||||
@(initial_step)
|
||||
begin
|
||||
//Initial voltage for internal node
|
||||
vforce = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
//Probing terminal voltage
|
||||
vext = V(a,b);
|
||||
vv = vext * vext;
|
||||
|
||||
// Calculation of Internal node voltage
|
||||
I(force_node) <+ ddt(cforce * V(force_node)); // current into Cd
|
||||
I(force_node) <+ (V(force_node)-vv) / rforce; // current from Rd
|
||||
vforce = V(force_node);
|
||||
vcontrol = sqrt(vforce); // calculate RMS Voltage
|
||||
|
||||
// C-V calculation
|
||||
alpha = (vcontrol - vtc) / vmc;
|
||||
cap = cmin + (2/`M_PI) * (cmax-cmin) * atan( (alpha + sqrt(alpha * alpha + delta_sq ))/2);
|
||||
qlc = cap * vext; // delta Q
|
||||
I(a,b) <+ ddt(qlc); // dQ / dt
|
||||
|
||||
// T-V calculation
|
||||
beta = (vcontrol - vto)/ vmo;
|
||||
trans = 1 - (1-tmin)*tanh( (beta+sqrt(beta*beta + eta_sq)) / 2 );
|
||||
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module demo;
|
||||
electrical src_out, gate, out, gnd;
|
||||
ground gnd;
|
||||
|
||||
parameter real on_V = 10.0;
|
||||
parameter real off_V = -1;
|
||||
|
||||
parameter real on_T = 2m; // on 1s
|
||||
parameter real off_T = 0;
|
||||
parameter real startDelay = 1m; // switch to on_V on 2ms
|
||||
|
||||
analog begin
|
||||
$bound_step(10u); // bessere Aufloesung
|
||||
end
|
||||
|
||||
// Puls-Quelle
|
||||
/*prameters expected for 'pulse' are '[dc] [mag [phase]] val0 val1 [td [rise [fall [width [period]]]]] */
|
||||
vpulse #(.val0(off_V), .val1(on_V), .td(startDelay), .rise(1n), .fall(1n), .width(on_T)) PL(gate, gnd);
|
||||
vdc #(.dc(3.2)) VDC (src_out, gnd);
|
||||
|
||||
myfet #(.kp(1m)) FET1 (src_out, gate, out);
|
||||
|
||||
lccap lcc(out, gnd);
|
||||
endmodule
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,4 @@
|
||||
add wave -r *
|
||||
add wave -i -r *
|
||||
run -all
|
||||
quit -f
|
||||
@@ -1,3 +1,9 @@
|
||||
# ESY1B Verifikation mit SystemVerilog und Python
|
||||
|
||||
Verwendeter Programmcode in Studienarbeit für ESY1B zum Thema "Verifikation mit SystemVerilog und Python"
|
||||
|
||||
# ESY1A LCD EPaper Modelling with VerilogA
|
||||
|
||||
Verwendeter Programmcode in Studienarbeit
|
||||
|
||||
# i2c project code
|
||||
@@ -0,0 +1,4 @@
|
||||
*.vcd
|
||||
sim/*.vcd
|
||||
sim/*.wlf
|
||||
sim/testHarness
|
||||
@@ -0,0 +1,7 @@
|
||||
# i2c_slave_opencores
|
||||
|
||||
I2C Verilog Testbench für einen CO2 Sensor
|
||||
|
||||
Beispiel ist von OpenCores
|
||||
|
||||
https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/i2c_slave_opencores
|
||||
@@ -0,0 +1,17 @@
|
||||
// ---------------------------- i2cSlaveTB_defines.v -----------------
|
||||
`define SEND_START 1'b1
|
||||
`define SEND_STOP 1'b1
|
||||
`define NULL 1'b0
|
||||
`define ACK 1'b0
|
||||
`define NACK 1'b1
|
||||
|
||||
`define DEV_I2C_ADDR 8'hcc
|
||||
|
||||
`define PRER_LO_REG 3'b000
|
||||
`define PRER_HI_REG 3'b001
|
||||
`define CTR_REG 3'b010
|
||||
`define RXR_REG 3'b011
|
||||
`define TXR_REG 3'b011
|
||||
`define CR_REG 3'b100
|
||||
`define SR_REG 3'b100
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
// ------------------ multiByteReadWrite.v ----------------------
|
||||
`include "timescale.v"
|
||||
`include "i2cSlaveTB_defines.v"
|
||||
|
||||
|
||||
module multiByteReadWrite();
|
||||
reg ack;
|
||||
reg [31:0] readData;
|
||||
reg [7:0] dataByteRead;
|
||||
//reg [7:0] dataMSB;
|
||||
|
||||
// ------------------ write ----------------------
|
||||
task write;
|
||||
input [7:0] i2cAddr;
|
||||
input [15:0] regAddr;
|
||||
input [31:0] data;
|
||||
input stop;
|
||||
|
||||
begin
|
||||
$write("I2C Write: At [0x%0x] = 0x%0x\n", regAddr, data);
|
||||
|
||||
//i2c address
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, i2cAddr);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//slave reg address high byte
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[15:8]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//slave reg address low byte
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[7:0]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//data[31:24]
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[31:24]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[31:24] sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//data[23:16]
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[23:16]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[23:16] sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//data[15:8]
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[15:8]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[15:8] sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//data[7:0]
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[7:0]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[7:0] sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
// ------------------ read ----------------------
|
||||
task read;
|
||||
input [7:0] i2cAddr;
|
||||
input [15:0] regAddr;
|
||||
input [31:0] expectedData;
|
||||
output [31:0] data;
|
||||
input stop;
|
||||
|
||||
begin
|
||||
|
||||
//i2c address
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, i2cAddr); //write
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
|
||||
#5000;
|
||||
|
||||
//slave reg address high byte
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[15:8]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
|
||||
#5000;
|
||||
//slave reg address low byte
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[7:0]);
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
|
||||
#5000;
|
||||
|
||||
//i2c address
|
||||
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, {i2cAddr[7:1], 1'b1}); //read
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
|
||||
|
||||
//data[31:24]
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[31:24] rxed, SR = 0x%x\n", dataByteRead );
|
||||
testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[31:24]);
|
||||
|
||||
//data[23:16]
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[23:16] rxed, SR = 0x%x\n", dataByteRead );
|
||||
testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[23:16]);
|
||||
|
||||
//data[15:8]
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[15:8] rxed, SR = 0x%x\n", dataByteRead );
|
||||
testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[15:8]);
|
||||
|
||||
//data[7:0]
|
||||
testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, 1'b0, 6'b101000}); //STO, RD, NAK
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
while (dataByteRead[1] == 1'b1) //while trans in progress
|
||||
testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
|
||||
//$write("Data[7:0] rxed, SR = 0x%x\n", dataByteRead );
|
||||
testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[7:0]);
|
||||
|
||||
data = readData;
|
||||
if (data != expectedData) begin
|
||||
$write("***** I2C Read ERROR: At 0x%0x. Expected 0x%0x, got 0x%0x\n", regAddr, expectedData, data);
|
||||
//$stop;
|
||||
end
|
||||
else
|
||||
$write("[read] I2C Read: At [0x%x] = 0x%0x\n", regAddr, data);
|
||||
end
|
||||
endtask
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// ---------------------------------- testcase0.v ----------------------------
|
||||
`include "timescale.v"
|
||||
`include "i2cSlave_define.v"
|
||||
`include "i2cSlaveTB_defines.v"
|
||||
|
||||
module testCase0();
|
||||
|
||||
reg ack;
|
||||
reg [7:0] data;
|
||||
reg [15:0] dataWord;
|
||||
reg [7:0] dataRead;
|
||||
reg [7:0] dataWrite;
|
||||
integer i;
|
||||
integer j;
|
||||
|
||||
initial
|
||||
begin
|
||||
$write("\n\n");
|
||||
testHarness.reset;
|
||||
testHarness.tb_readEn <= 1'b0;
|
||||
testHarness.tb_writeEn <= 1'b0;
|
||||
|
||||
// set i2c master clock scale reg PRER = (48MHz / (5 * 400KHz) ) - 1
|
||||
$write("Testing register read/write\n");
|
||||
testHarness.u_wb_master_model.wb_write(1, `PRER_LO_REG , 8'h17);
|
||||
testHarness.u_wb_master_model.wb_write(1, `PRER_HI_REG , 8'h00);
|
||||
testHarness.u_wb_master_model.wb_cmp(1, `PRER_LO_REG , 8'h17);
|
||||
|
||||
// enable i2c master
|
||||
testHarness.u_wb_master_model.wb_write(1, `CTR_REG , 8'h80);
|
||||
|
||||
|
||||
multiByteReadWrite.write({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, `SEND_STOP);
|
||||
multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
|
||||
#100;
|
||||
|
||||
testHarness.tb_addr <= 16'h1234;
|
||||
testHarness.tb_dataIn <= 16'h5555;
|
||||
|
||||
#10 testHarness.tb_writeEn <= 1'b1;
|
||||
#10 testHarness.tb_readEn <= 1'b1;
|
||||
#10 testHarness.tb_writeEn <= 1'b0;
|
||||
#10 testHarness.tb_readEn <= 1'b0;
|
||||
|
||||
#100;
|
||||
multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
|
||||
|
||||
#100;
|
||||
multiByteReadWrite.write({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, `SEND_STOP);
|
||||
multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
|
||||
|
||||
$write("Finished all tests\n");
|
||||
$finish;
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
// -------------------------- testHarness.v -----------------------
|
||||
`include "timescale.v"
|
||||
|
||||
module testHarness ();
|
||||
|
||||
reg rst;
|
||||
reg clk;
|
||||
reg i2cHostClk;
|
||||
wire sda;
|
||||
wire scl;
|
||||
wire sdaOutEn;
|
||||
wire sdaOut;
|
||||
wire sdaIn;
|
||||
wire [2:0] adr;
|
||||
wire [7:0] masterDout;
|
||||
wire [7:0] masterDin;
|
||||
wire we;
|
||||
wire stb;
|
||||
wire cyc;
|
||||
wire ack;
|
||||
wire scl_pad_i;
|
||||
wire scl_pad_o;
|
||||
wire scl_padoen_o;
|
||||
wire sda_pad_i;
|
||||
wire sda_pad_o;
|
||||
wire sda_padoen_o;
|
||||
|
||||
// tb passthrough
|
||||
reg tb_readEn;
|
||||
reg tb_writeEn;
|
||||
reg [15:0] tb_addr;
|
||||
reg [15:0] tb_dataIn;
|
||||
wire [15:0] tb_dataOut;
|
||||
|
||||
initial begin
|
||||
$dumpfile("wave.vcd");
|
||||
$dumpvars(0, testHarness);
|
||||
end
|
||||
|
||||
i2cSlave u_i2cSlave(
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sda(sda),
|
||||
.scl(scl),
|
||||
.tb_readEn(tb_readEn),
|
||||
.tb_writeEn(tb_writeEn),
|
||||
.tb_addr(tb_addr),
|
||||
.tb_dataIn(tb_dataIn),
|
||||
.tb_dataOut(tb_dataOut)
|
||||
);
|
||||
|
||||
i2c_master_top #(.ARST_LVL(1'b1)) u_i2c_master_top (
|
||||
.wb_clk_i(clk),
|
||||
.wb_rst_i(rst),
|
||||
.arst_i(rst),
|
||||
.wb_adr_i(adr),
|
||||
.wb_dat_i(masterDout),
|
||||
.wb_dat_o(masterDin),
|
||||
.wb_we_i(we),
|
||||
.wb_stb_i(stb),
|
||||
.wb_cyc_i(cyc),
|
||||
.wb_ack_o(ack),
|
||||
.wb_inta_o(),
|
||||
.scl_pad_i(scl_pad_i),
|
||||
.scl_pad_o(scl_pad_o),
|
||||
.scl_padoen_o(scl_padoen_o),
|
||||
.sda_pad_i(sda_pad_i),
|
||||
.sda_pad_o(sda_pad_o),
|
||||
.sda_padoen_o(sda_padoen_o)
|
||||
);
|
||||
|
||||
wb_master_model #(.dwidth(8), .awidth(3)) u_wb_master_model (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.adr(adr),
|
||||
.din(masterDin),
|
||||
.dout(masterDout),
|
||||
.cyc(cyc),
|
||||
.stb(stb),
|
||||
.we(we),
|
||||
.sel(),
|
||||
.ack(ack),
|
||||
.err(1'b0),
|
||||
.rty(1'b0)
|
||||
);
|
||||
|
||||
assign sda = (sda_padoen_o == 1'b0) ? sda_pad_o : 1'bz;
|
||||
assign sda_pad_i = sda;
|
||||
pullup(sda);
|
||||
|
||||
assign scl = (scl_padoen_o == 1'b0) ? scl_pad_o : 1'bz;
|
||||
assign scl_pad_i = scl;
|
||||
pullup(scl);
|
||||
|
||||
|
||||
// ****************************** Clock section ******************************
|
||||
//approx 48MHz clock
|
||||
`define CLK_HALF_PERIOD 10
|
||||
always begin
|
||||
#`CLK_HALF_PERIOD clk <= 1'b0;
|
||||
#`CLK_HALF_PERIOD clk <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// ****************************** reset ******************************
|
||||
task reset;
|
||||
begin
|
||||
rst <= 1'b1;
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
rst <= 1'b0;
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
end
|
||||
endtask
|
||||
|
||||
endmodule
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,538 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE rev.B2 compliant I2C Master bit-controller ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// www.asics.ws ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2001 Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer.////
|
||||
//// ////
|
||||
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||||
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||||
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||||
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||||
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||||
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||||
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||||
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||||
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||||
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||||
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||||
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||||
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CVS Log
|
||||
//
|
||||
// $Id: i2c_master_bit_ctrl.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
|
||||
//
|
||||
// $Date: 2008-11-08 13:15:10 $
|
||||
// $Revision: 1.1 $
|
||||
// $Author: sfielding $
|
||||
// $Locker: $
|
||||
// $State: Exp $
|
||||
//
|
||||
// Change History:
|
||||
// $Log: not supported by cvs2svn $
|
||||
// Revision 1.12 2006/09/04 09:08:13 rherveille
|
||||
// fixed short scl high pulse after clock stretch
|
||||
// fixed slave model not returning correct '(n)ack' signal
|
||||
//
|
||||
// Revision 1.11 2004/05/07 11:02:26 rherveille
|
||||
// Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
|
||||
//
|
||||
// Revision 1.10 2003/08/09 07:01:33 rherveille
|
||||
// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
|
||||
// Fixed a potential bug in the byte controller's host-acknowledge generation.
|
||||
//
|
||||
// Revision 1.9 2003/03/10 14:26:37 rherveille
|
||||
// Fixed cmd_ack generation item (no bug).
|
||||
//
|
||||
// Revision 1.8 2003/02/05 00:06:10 rherveille
|
||||
// Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
|
||||
//
|
||||
// Revision 1.7 2002/12/26 16:05:12 rherveille
|
||||
// Small code simplifications
|
||||
//
|
||||
// Revision 1.6 2002/12/26 15:02:32 rherveille
|
||||
// Core is now a Multimaster I2C controller
|
||||
//
|
||||
// Revision 1.5 2002/11/30 22:24:40 rherveille
|
||||
// Cleaned up code
|
||||
//
|
||||
// Revision 1.4 2002/10/30 18:10:07 rherveille
|
||||
// Fixed some reported minor start/stop generation timing issuess.
|
||||
//
|
||||
// Revision 1.3 2002/06/15 07:37:03 rherveille
|
||||
// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
|
||||
//
|
||||
// Revision 1.2 2001/11/05 11:59:25 rherveille
|
||||
// Fixed wb_ack_o generation bug.
|
||||
// Fixed bug in the byte_controller statemachine.
|
||||
// Added headers.
|
||||
//
|
||||
|
||||
//
|
||||
/////////////////////////////////////
|
||||
// Bit controller section
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// Translate simple commands into SCL/SDA transitions
|
||||
// Each command has 5 states, A/B/C/D/idle
|
||||
//
|
||||
// start: SCL ~~~~~~~~~~\____
|
||||
// SDA ~~~~~~~~\______
|
||||
// x | A | B | C | D | i
|
||||
//
|
||||
// repstart SCL ____/~~~~\___
|
||||
// SDA __/~~~\______
|
||||
// x | A | B | C | D | i
|
||||
//
|
||||
// stop SCL ____/~~~~~~~~
|
||||
// SDA ==\____/~~~~~
|
||||
// x | A | B | C | D | i
|
||||
//
|
||||
//- write SCL ____/~~~~\____
|
||||
// SDA ==X=========X=
|
||||
// x | A | B | C | D | i
|
||||
//
|
||||
//- read SCL ____/~~~~\____
|
||||
// SDA XXXX=====XXXX
|
||||
// x | A | B | C | D | i
|
||||
//
|
||||
|
||||
// Timing: Normal mode Fast mode
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Fscl 100KHz 400KHz
|
||||
// Th_scl 4.0us 0.6us High period of SCL
|
||||
// Tl_scl 4.7us 1.3us Low period of SCL
|
||||
// Tsu:sta 4.7us 0.6us setup time for a repeated start condition
|
||||
// Tsu:sto 4.0us 0.6us setup time for a stop conditon
|
||||
// Tbuf 4.7us 1.3us Bus free time between a stop and start condition
|
||||
//
|
||||
|
||||
// synopsys translate_off
|
||||
`include "timescale.v"
|
||||
// synopsys translate_on
|
||||
|
||||
`include "i2c_master_defines.v"
|
||||
|
||||
module i2c_master_bit_ctrl(
|
||||
clk, rst, nReset,
|
||||
clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout,
|
||||
scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen
|
||||
);
|
||||
|
||||
//
|
||||
// inputs & outputs
|
||||
//
|
||||
input clk;
|
||||
input rst;
|
||||
input nReset;
|
||||
input ena; // core enable signal
|
||||
|
||||
input [15:0] clk_cnt; // clock prescale value
|
||||
|
||||
input [3:0] cmd;
|
||||
output cmd_ack; // command complete acknowledge
|
||||
reg cmd_ack;
|
||||
output busy; // i2c bus busy
|
||||
reg busy;
|
||||
output al; // i2c bus arbitration lost
|
||||
reg al;
|
||||
|
||||
input din;
|
||||
output dout;
|
||||
reg dout;
|
||||
|
||||
// I2C lines
|
||||
input scl_i; // i2c clock line input
|
||||
output scl_o; // i2c clock line output
|
||||
output scl_oen; // i2c clock line output enable (active low)
|
||||
reg scl_oen;
|
||||
input sda_i; // i2c data line input
|
||||
output sda_o; // i2c data line output
|
||||
output sda_oen; // i2c data line output enable (active low)
|
||||
reg sda_oen;
|
||||
|
||||
|
||||
//
|
||||
// variable declarations
|
||||
//
|
||||
|
||||
reg sSCL, sSDA; // synchronized SCL and SDA inputs
|
||||
reg dscl_oen; // delayed scl_oen
|
||||
reg sda_chk; // check SDA output (Multi-master arbitration)
|
||||
reg clk_en; // clock generation signals
|
||||
wire slave_wait;
|
||||
// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation)
|
||||
reg [15:0] cnt; // clock divider counter (synthesis)
|
||||
|
||||
// state machine variable
|
||||
reg [16:0] c_state; // synopsys enum_state
|
||||
|
||||
//
|
||||
// module body
|
||||
//
|
||||
|
||||
// whenever the slave is not ready it can delay the cycle by pulling SCL low
|
||||
// delay scl_oen
|
||||
always @(posedge clk)
|
||||
dscl_oen <= #1 scl_oen;
|
||||
|
||||
assign slave_wait = dscl_oen && !sSCL;
|
||||
|
||||
|
||||
// generate clk enable signal
|
||||
always @(posedge clk or negedge nReset)
|
||||
if(~nReset)
|
||||
begin
|
||||
cnt <= #1 16'h0;
|
||||
clk_en <= #1 1'b1;
|
||||
end
|
||||
else if (rst)
|
||||
begin
|
||||
cnt <= #1 16'h0;
|
||||
clk_en <= #1 1'b1;
|
||||
end
|
||||
else if ( ~|cnt || !ena)
|
||||
begin
|
||||
cnt <= #1 clk_cnt;
|
||||
clk_en <= #1 1'b1;
|
||||
end
|
||||
else if (slave_wait)
|
||||
begin
|
||||
cnt <= #1 cnt;
|
||||
clk_en <= #1 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
cnt <= #1 cnt - 16'h1;
|
||||
clk_en <= #1 1'b0;
|
||||
end
|
||||
|
||||
|
||||
// generate bus status controller
|
||||
reg dSCL, dSDA;
|
||||
reg sta_condition;
|
||||
reg sto_condition;
|
||||
|
||||
// synchronize SCL and SDA inputs
|
||||
// reduce metastability risc
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (~nReset)
|
||||
begin
|
||||
sSCL <= #1 1'b1;
|
||||
sSDA <= #1 1'b1;
|
||||
|
||||
dSCL <= #1 1'b1;
|
||||
dSDA <= #1 1'b1;
|
||||
end
|
||||
else if (rst)
|
||||
begin
|
||||
sSCL <= #1 1'b1;
|
||||
sSDA <= #1 1'b1;
|
||||
|
||||
dSCL <= #1 1'b1;
|
||||
dSDA <= #1 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
sSCL <= #1 scl_i;
|
||||
sSDA <= #1 sda_i;
|
||||
|
||||
dSCL <= #1 sSCL;
|
||||
dSDA <= #1 sSDA;
|
||||
end
|
||||
|
||||
// detect start condition => detect falling edge on SDA while SCL is high
|
||||
// detect stop condition => detect rising edge on SDA while SCL is high
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (~nReset)
|
||||
begin
|
||||
sta_condition <= #1 1'b0;
|
||||
sto_condition <= #1 1'b0;
|
||||
end
|
||||
else if (rst)
|
||||
begin
|
||||
sta_condition <= #1 1'b0;
|
||||
sto_condition <= #1 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
sta_condition <= #1 ~sSDA & dSDA & sSCL;
|
||||
sto_condition <= #1 sSDA & ~dSDA & sSCL;
|
||||
end
|
||||
|
||||
// generate i2c bus busy signal
|
||||
always @(posedge clk or negedge nReset)
|
||||
if(!nReset)
|
||||
busy <= #1 1'b0;
|
||||
else if (rst)
|
||||
busy <= #1 1'b0;
|
||||
else
|
||||
busy <= #1 (sta_condition | busy) & ~sto_condition;
|
||||
|
||||
// generate arbitration lost signal
|
||||
// aribitration lost when:
|
||||
// 1) master drives SDA high, but the i2c bus is low
|
||||
// 2) stop detected while not requested
|
||||
reg cmd_stop;
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (~nReset)
|
||||
cmd_stop <= #1 1'b0;
|
||||
else if (rst)
|
||||
cmd_stop <= #1 1'b0;
|
||||
else if (clk_en)
|
||||
cmd_stop <= #1 cmd == `I2C_CMD_STOP;
|
||||
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (~nReset)
|
||||
al <= #1 1'b0;
|
||||
else if (rst)
|
||||
al <= #1 1'b0;
|
||||
else
|
||||
al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);
|
||||
|
||||
|
||||
// generate dout signal (store SDA on rising edge of SCL)
|
||||
always @(posedge clk)
|
||||
if(sSCL & ~dSCL)
|
||||
dout <= #1 sSDA;
|
||||
|
||||
// generate statemachine
|
||||
|
||||
// nxt_state decoder
|
||||
parameter [16:0] idle = 17'b0_0000_0000_0000_0000;
|
||||
parameter [16:0] start_a = 17'b0_0000_0000_0000_0001;
|
||||
parameter [16:0] start_b = 17'b0_0000_0000_0000_0010;
|
||||
parameter [16:0] start_c = 17'b0_0000_0000_0000_0100;
|
||||
parameter [16:0] start_d = 17'b0_0000_0000_0000_1000;
|
||||
parameter [16:0] start_e = 17'b0_0000_0000_0001_0000;
|
||||
parameter [16:0] stop_a = 17'b0_0000_0000_0010_0000;
|
||||
parameter [16:0] stop_b = 17'b0_0000_0000_0100_0000;
|
||||
parameter [16:0] stop_c = 17'b0_0000_0000_1000_0000;
|
||||
parameter [16:0] stop_d = 17'b0_0000_0001_0000_0000;
|
||||
parameter [16:0] rd_a = 17'b0_0000_0010_0000_0000;
|
||||
parameter [16:0] rd_b = 17'b0_0000_0100_0000_0000;
|
||||
parameter [16:0] rd_c = 17'b0_0000_1000_0000_0000;
|
||||
parameter [16:0] rd_d = 17'b0_0001_0000_0000_0000;
|
||||
parameter [16:0] wr_a = 17'b0_0010_0000_0000_0000;
|
||||
parameter [16:0] wr_b = 17'b0_0100_0000_0000_0000;
|
||||
parameter [16:0] wr_c = 17'b0_1000_0000_0000_0000;
|
||||
parameter [16:0] wr_d = 17'b1_0000_0000_0000_0000;
|
||||
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (!nReset)
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b0;
|
||||
scl_oen <= #1 1'b1;
|
||||
sda_oen <= #1 1'b1;
|
||||
sda_chk <= #1 1'b0;
|
||||
end
|
||||
else if (rst | al)
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b0;
|
||||
scl_oen <= #1 1'b1;
|
||||
sda_oen <= #1 1'b1;
|
||||
sda_chk <= #1 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle
|
||||
|
||||
if (clk_en)
|
||||
case (c_state) // synopsys full_case parallel_case
|
||||
// idle state
|
||||
idle:
|
||||
begin
|
||||
case (cmd) // synopsys full_case parallel_case
|
||||
`I2C_CMD_START:
|
||||
c_state <= #1 start_a;
|
||||
|
||||
`I2C_CMD_STOP:
|
||||
c_state <= #1 stop_a;
|
||||
|
||||
`I2C_CMD_WRITE:
|
||||
c_state <= #1 wr_a;
|
||||
|
||||
`I2C_CMD_READ:
|
||||
c_state <= #1 rd_a;
|
||||
|
||||
default:
|
||||
c_state <= #1 idle;
|
||||
endcase
|
||||
|
||||
scl_oen <= #1 scl_oen; // keep SCL in same state
|
||||
sda_oen <= #1 sda_oen; // keep SDA in same state
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
// start
|
||||
start_a:
|
||||
begin
|
||||
c_state <= #1 start_b;
|
||||
scl_oen <= #1 scl_oen; // keep SCL in same state
|
||||
sda_oen <= #1 1'b1; // set SDA high
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
start_b:
|
||||
begin
|
||||
c_state <= #1 start_c;
|
||||
scl_oen <= #1 1'b1; // set SCL high
|
||||
sda_oen <= #1 1'b1; // keep SDA high
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
start_c:
|
||||
begin
|
||||
c_state <= #1 start_d;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 1'b0; // set SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
start_d:
|
||||
begin
|
||||
c_state <= #1 start_e;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 1'b0; // keep SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
start_e:
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b1;
|
||||
scl_oen <= #1 1'b0; // set SCL low
|
||||
sda_oen <= #1 1'b0; // keep SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
// stop
|
||||
stop_a:
|
||||
begin
|
||||
c_state <= #1 stop_b;
|
||||
scl_oen <= #1 1'b0; // keep SCL low
|
||||
sda_oen <= #1 1'b0; // set SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
stop_b:
|
||||
begin
|
||||
c_state <= #1 stop_c;
|
||||
scl_oen <= #1 1'b1; // set SCL high
|
||||
sda_oen <= #1 1'b0; // keep SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
stop_c:
|
||||
begin
|
||||
c_state <= #1 stop_d;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 1'b0; // keep SDA low
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
stop_d:
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b1;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 1'b1; // set SDA high
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
// read
|
||||
rd_a:
|
||||
begin
|
||||
c_state <= #1 rd_b;
|
||||
scl_oen <= #1 1'b0; // keep SCL low
|
||||
sda_oen <= #1 1'b1; // tri-state SDA
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
rd_b:
|
||||
begin
|
||||
c_state <= #1 rd_c;
|
||||
scl_oen <= #1 1'b1; // set SCL high
|
||||
sda_oen <= #1 1'b1; // keep SDA tri-stated
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
rd_c:
|
||||
begin
|
||||
c_state <= #1 rd_d;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 1'b1; // keep SDA tri-stated
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
rd_d:
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b1;
|
||||
scl_oen <= #1 1'b0; // set SCL low
|
||||
sda_oen <= #1 1'b1; // keep SDA tri-stated
|
||||
sda_chk <= #1 1'b0; // don't check SDA output
|
||||
end
|
||||
|
||||
// write
|
||||
wr_a:
|
||||
begin
|
||||
c_state <= #1 wr_b;
|
||||
scl_oen <= #1 1'b0; // keep SCL low
|
||||
sda_oen <= #1 din; // set SDA
|
||||
sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
|
||||
end
|
||||
|
||||
wr_b:
|
||||
begin
|
||||
c_state <= #1 wr_c;
|
||||
scl_oen <= #1 1'b1; // set SCL high
|
||||
sda_oen <= #1 din; // keep SDA
|
||||
sda_chk <= #1 1'b1; // check SDA output
|
||||
end
|
||||
|
||||
wr_c:
|
||||
begin
|
||||
c_state <= #1 wr_d;
|
||||
scl_oen <= #1 1'b1; // keep SCL high
|
||||
sda_oen <= #1 din;
|
||||
sda_chk <= #1 1'b1; // check SDA output
|
||||
end
|
||||
|
||||
wr_d:
|
||||
begin
|
||||
c_state <= #1 idle;
|
||||
cmd_ack <= #1 1'b1;
|
||||
scl_oen <= #1 1'b0; // set SCL low
|
||||
sda_oen <= #1 din;
|
||||
sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
// assign scl and sda output (always gnd)
|
||||
assign scl_o = 1'b0;
|
||||
assign sda_o = 1'b0;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,344 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE rev.B2 compliant I2C Master byte-controller ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// www.asics.ws ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2001 Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer.////
|
||||
//// ////
|
||||
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||||
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||||
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||||
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||||
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||||
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||||
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||||
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||||
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||||
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||||
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||||
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||||
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CVS Log
|
||||
//
|
||||
// $Id: i2c_master_byte_ctrl.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
|
||||
//
|
||||
// $Date: 2008-11-08 13:15:10 $
|
||||
// $Revision: 1.1 $
|
||||
// $Author: sfielding $
|
||||
// $Locker: $
|
||||
// $State: Exp $
|
||||
//
|
||||
// Change History:
|
||||
// $Log: not supported by cvs2svn $
|
||||
// Revision 1.7 2004/02/18 11:40:46 rherveille
|
||||
// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
|
||||
//
|
||||
// Revision 1.6 2003/08/09 07:01:33 rherveille
|
||||
// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
|
||||
// Fixed a potential bug in the byte controller's host-acknowledge generation.
|
||||
//
|
||||
// Revision 1.5 2002/12/26 15:02:32 rherveille
|
||||
// Core is now a Multimaster I2C controller
|
||||
//
|
||||
// Revision 1.4 2002/11/30 22:24:40 rherveille
|
||||
// Cleaned up code
|
||||
//
|
||||
// Revision 1.3 2001/11/05 11:59:25 rherveille
|
||||
// Fixed wb_ack_o generation bug.
|
||||
// Fixed bug in the byte_controller statemachine.
|
||||
// Added headers.
|
||||
//
|
||||
|
||||
// synopsys translate_off
|
||||
`include "timescale.v"
|
||||
// synopsys translate_on
|
||||
|
||||
`include "i2c_master_defines.v"
|
||||
|
||||
module i2c_master_byte_ctrl (
|
||||
clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
|
||||
cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
|
||||
|
||||
//
|
||||
// inputs & outputs
|
||||
//
|
||||
input clk; // master clock
|
||||
input rst; // synchronous active high reset
|
||||
input nReset; // asynchronous active low reset
|
||||
input ena; // core enable signal
|
||||
|
||||
input [15:0] clk_cnt; // 4x SCL
|
||||
|
||||
// control inputs
|
||||
input start;
|
||||
input stop;
|
||||
input read;
|
||||
input write;
|
||||
input ack_in;
|
||||
input [7:0] din;
|
||||
|
||||
// status outputs
|
||||
output cmd_ack;
|
||||
reg cmd_ack;
|
||||
output ack_out;
|
||||
reg ack_out;
|
||||
output i2c_busy;
|
||||
output i2c_al;
|
||||
output [7:0] dout;
|
||||
|
||||
// I2C signals
|
||||
input scl_i;
|
||||
output scl_o;
|
||||
output scl_oen;
|
||||
input sda_i;
|
||||
output sda_o;
|
||||
output sda_oen;
|
||||
|
||||
|
||||
//
|
||||
// Variable declarations
|
||||
//
|
||||
|
||||
// statemachine
|
||||
parameter [4:0] ST_IDLE = 5'b0_0000;
|
||||
parameter [4:0] ST_START = 5'b0_0001;
|
||||
parameter [4:0] ST_READ = 5'b0_0010;
|
||||
parameter [4:0] ST_WRITE = 5'b0_0100;
|
||||
parameter [4:0] ST_ACK = 5'b0_1000;
|
||||
parameter [4:0] ST_STOP = 5'b1_0000;
|
||||
|
||||
// signals for bit_controller
|
||||
reg [3:0] core_cmd;
|
||||
reg core_txd;
|
||||
wire core_ack, core_rxd;
|
||||
|
||||
// signals for shift register
|
||||
reg [7:0] sr; //8bit shift register
|
||||
reg shift, ld;
|
||||
|
||||
// signals for state machine
|
||||
wire go;
|
||||
reg [2:0] dcnt;
|
||||
wire cnt_done;
|
||||
|
||||
//
|
||||
// Module body
|
||||
//
|
||||
|
||||
// hookup bit_controller
|
||||
i2c_master_bit_ctrl bit_controller (
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.nReset ( nReset ),
|
||||
.ena ( ena ),
|
||||
.clk_cnt ( clk_cnt ),
|
||||
.cmd ( core_cmd ),
|
||||
.cmd_ack ( core_ack ),
|
||||
.busy ( i2c_busy ),
|
||||
.al ( i2c_al ),
|
||||
.din ( core_txd ),
|
||||
.dout ( core_rxd ),
|
||||
.scl_i ( scl_i ),
|
||||
.scl_o ( scl_o ),
|
||||
.scl_oen ( scl_oen ),
|
||||
.sda_i ( sda_i ),
|
||||
.sda_o ( sda_o ),
|
||||
.sda_oen ( sda_oen )
|
||||
);
|
||||
|
||||
// generate go-signal
|
||||
assign go = (read | write | stop) & ~cmd_ack;
|
||||
|
||||
// assign dout output to shift-register
|
||||
assign dout = sr;
|
||||
|
||||
// generate shift register
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (!nReset)
|
||||
sr <= #1 8'h0;
|
||||
else if (rst)
|
||||
sr <= #1 8'h0;
|
||||
else if (ld)
|
||||
sr <= #1 din;
|
||||
else if (shift)
|
||||
sr <= #1 {sr[6:0], core_rxd};
|
||||
|
||||
// generate counter
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (!nReset)
|
||||
dcnt <= #1 3'h0;
|
||||
else if (rst)
|
||||
dcnt <= #1 3'h0;
|
||||
else if (ld)
|
||||
dcnt <= #1 3'h7;
|
||||
else if (shift)
|
||||
dcnt <= #1 dcnt - 3'h1;
|
||||
|
||||
assign cnt_done = ~(|dcnt);
|
||||
|
||||
//
|
||||
// state machine
|
||||
//
|
||||
reg [4:0] c_state; // synopsis enum_state
|
||||
|
||||
always @(posedge clk or negedge nReset)
|
||||
if (!nReset)
|
||||
begin
|
||||
core_cmd <= #1 `I2C_CMD_NOP;
|
||||
core_txd <= #1 1'b0;
|
||||
shift <= #1 1'b0;
|
||||
ld <= #1 1'b0;
|
||||
cmd_ack <= #1 1'b0;
|
||||
c_state <= #1 ST_IDLE;
|
||||
ack_out <= #1 1'b0;
|
||||
end
|
||||
else if (rst | i2c_al)
|
||||
begin
|
||||
core_cmd <= #1 `I2C_CMD_NOP;
|
||||
core_txd <= #1 1'b0;
|
||||
shift <= #1 1'b0;
|
||||
ld <= #1 1'b0;
|
||||
cmd_ack <= #1 1'b0;
|
||||
c_state <= #1 ST_IDLE;
|
||||
ack_out <= #1 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// initially reset all signals
|
||||
core_txd <= #1 sr[7];
|
||||
shift <= #1 1'b0;
|
||||
ld <= #1 1'b0;
|
||||
cmd_ack <= #1 1'b0;
|
||||
|
||||
case (c_state) // synopsys full_case parallel_case
|
||||
ST_IDLE:
|
||||
if (go)
|
||||
begin
|
||||
if (start)
|
||||
begin
|
||||
c_state <= #1 ST_START;
|
||||
core_cmd <= #1 `I2C_CMD_START;
|
||||
end
|
||||
else if (read)
|
||||
begin
|
||||
c_state <= #1 ST_READ;
|
||||
core_cmd <= #1 `I2C_CMD_READ;
|
||||
end
|
||||
else if (write)
|
||||
begin
|
||||
c_state <= #1 ST_WRITE;
|
||||
core_cmd <= #1 `I2C_CMD_WRITE;
|
||||
end
|
||||
else // stop
|
||||
begin
|
||||
c_state <= #1 ST_STOP;
|
||||
core_cmd <= #1 `I2C_CMD_STOP;
|
||||
end
|
||||
|
||||
ld <= #1 1'b1;
|
||||
end
|
||||
|
||||
ST_START:
|
||||
if (core_ack)
|
||||
begin
|
||||
if (read)
|
||||
begin
|
||||
c_state <= #1 ST_READ;
|
||||
core_cmd <= #1 `I2C_CMD_READ;
|
||||
end
|
||||
else
|
||||
begin
|
||||
c_state <= #1 ST_WRITE;
|
||||
core_cmd <= #1 `I2C_CMD_WRITE;
|
||||
end
|
||||
|
||||
ld <= #1 1'b1;
|
||||
end
|
||||
|
||||
ST_WRITE:
|
||||
if (core_ack)
|
||||
if (cnt_done)
|
||||
begin
|
||||
c_state <= #1 ST_ACK;
|
||||
core_cmd <= #1 `I2C_CMD_READ;
|
||||
end
|
||||
else
|
||||
begin
|
||||
c_state <= #1 ST_WRITE; // stay in same state
|
||||
core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
|
||||
shift <= #1 1'b1;
|
||||
end
|
||||
|
||||
ST_READ:
|
||||
if (core_ack)
|
||||
begin
|
||||
if (cnt_done)
|
||||
begin
|
||||
c_state <= #1 ST_ACK;
|
||||
core_cmd <= #1 `I2C_CMD_WRITE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
c_state <= #1 ST_READ; // stay in same state
|
||||
core_cmd <= #1 `I2C_CMD_READ; // read next bit
|
||||
end
|
||||
|
||||
shift <= #1 1'b1;
|
||||
core_txd <= #1 ack_in;
|
||||
end
|
||||
|
||||
ST_ACK:
|
||||
if (core_ack)
|
||||
begin
|
||||
if (stop)
|
||||
begin
|
||||
c_state <= #1 ST_STOP;
|
||||
core_cmd <= #1 `I2C_CMD_STOP;
|
||||
end
|
||||
else
|
||||
begin
|
||||
c_state <= #1 ST_IDLE;
|
||||
core_cmd <= #1 `I2C_CMD_NOP;
|
||||
|
||||
// generate command acknowledge signal
|
||||
cmd_ack <= #1 1'b1;
|
||||
end
|
||||
|
||||
// assign ack_out output to bit_controller_rxd (contains last received bit)
|
||||
ack_out <= #1 core_rxd;
|
||||
|
||||
core_txd <= #1 1'b1;
|
||||
end
|
||||
else
|
||||
core_txd <= #1 ack_in;
|
||||
|
||||
ST_STOP:
|
||||
if (core_ack)
|
||||
begin
|
||||
c_state <= #1 ST_IDLE;
|
||||
core_cmd <= #1 `I2C_CMD_NOP;
|
||||
|
||||
// generate command acknowledge signal
|
||||
cmd_ack <= #1 1'b1;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,64 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE rev.B2 compliant I2C Master controller defines ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// www.asics.ws ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2001 Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer.////
|
||||
//// ////
|
||||
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||||
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||||
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||||
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||||
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||||
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||||
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||||
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||||
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||||
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||||
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||||
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||||
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CVS Log
|
||||
//
|
||||
// $Id: i2c_master_defines.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
|
||||
//
|
||||
// $Date: 2008-11-08 13:15:10 $
|
||||
// $Revision: 1.1 $
|
||||
// $Author: sfielding $
|
||||
// $Locker: $
|
||||
// $State: Exp $
|
||||
//
|
||||
// Change History:
|
||||
// $Log: not supported by cvs2svn $
|
||||
// Revision 1.3 2001/11/05 11:59:25 rherveille
|
||||
// Fixed wb_ack_o generation bug.
|
||||
// Fixed bug in the byte_controller statemachine.
|
||||
// Added headers.
|
||||
//
|
||||
|
||||
|
||||
// I2C registers wishbone addresses
|
||||
|
||||
// bitcontroller states
|
||||
`define I2C_CMD_NOP 4'b0000
|
||||
`define I2C_CMD_START 4'b0001
|
||||
`define I2C_CMD_STOP 4'b0010
|
||||
`define I2C_CMD_WRITE 4'b0100
|
||||
`define I2C_CMD_READ 4'b1000
|
||||
@@ -0,0 +1,301 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE revB.2 compliant I2C Master controller Top-level ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// www.asics.ws ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2001 Richard Herveille ////
|
||||
//// richard@asics.ws ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer.////
|
||||
//// ////
|
||||
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||||
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||||
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||||
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||||
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||||
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||||
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||||
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||||
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||||
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||||
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||||
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||||
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CVS Log
|
||||
//
|
||||
// $Id: i2c_master_top.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
|
||||
//
|
||||
// $Date: 2008-11-08 13:15:10 $
|
||||
// $Revision: 1.1 $
|
||||
// $Author: sfielding $
|
||||
// $Locker: $
|
||||
// $State: Exp $
|
||||
//
|
||||
// Change History:
|
||||
// $Log: not supported by cvs2svn $
|
||||
// Revision 1.11 2005/02/27 09:26:24 rherveille
|
||||
// Fixed register overwrite issue.
|
||||
// Removed full_case pragma, replaced it by a default statement.
|
||||
//
|
||||
// Revision 1.10 2003/09/01 10:34:38 rherveille
|
||||
// Fix a blocking vs. non-blocking error in the wb_dat output mux.
|
||||
//
|
||||
// Revision 1.9 2003/01/09 16:44:45 rherveille
|
||||
// Fixed a bug in the Command Register declaration.
|
||||
//
|
||||
// Revision 1.8 2002/12/26 16:05:12 rherveille
|
||||
// Small code simplifications
|
||||
//
|
||||
// Revision 1.7 2002/12/26 15:02:32 rherveille
|
||||
// Core is now a Multimaster I2C controller
|
||||
//
|
||||
// Revision 1.6 2002/11/30 22:24:40 rherveille
|
||||
// Cleaned up code
|
||||
//
|
||||
// Revision 1.5 2001/11/10 10:52:55 rherveille
|
||||
// Changed PRER reset value from 0x0000 to 0xffff, conform specs.
|
||||
//
|
||||
|
||||
// synopsys translate_off
|
||||
`include "timescale.v"
|
||||
// synopsys translate_on
|
||||
|
||||
`include "i2c_master_defines.v"
|
||||
|
||||
module i2c_master_top(
|
||||
wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
|
||||
wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
|
||||
scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );
|
||||
|
||||
// parameters
|
||||
parameter ARST_LVL = 1'b0; // asynchronous reset level
|
||||
|
||||
//
|
||||
// inputs & outputs
|
||||
//
|
||||
|
||||
// wishbone signals
|
||||
input wb_clk_i; // master clock input
|
||||
input wb_rst_i; // synchronous active high reset
|
||||
input arst_i; // asynchronous reset
|
||||
input [2:0] wb_adr_i; // lower address bits
|
||||
input [7:0] wb_dat_i; // databus input
|
||||
output [7:0] wb_dat_o; // databus output
|
||||
input wb_we_i; // write enable input
|
||||
input wb_stb_i; // stobe/core select signal
|
||||
input wb_cyc_i; // valid bus cycle input
|
||||
output wb_ack_o; // bus cycle acknowledge output
|
||||
output wb_inta_o; // interrupt request signal output
|
||||
|
||||
reg [7:0] wb_dat_o;
|
||||
reg wb_ack_o;
|
||||
reg wb_inta_o;
|
||||
|
||||
// I2C signals
|
||||
// i2c clock line
|
||||
input scl_pad_i; // SCL-line input
|
||||
output scl_pad_o; // SCL-line output (always 1'b0)
|
||||
output scl_padoen_o; // SCL-line output enable (active low)
|
||||
|
||||
// i2c data line
|
||||
input sda_pad_i; // SDA-line input
|
||||
output sda_pad_o; // SDA-line output (always 1'b0)
|
||||
output sda_padoen_o; // SDA-line output enable (active low)
|
||||
|
||||
|
||||
//
|
||||
// variable declarations
|
||||
//
|
||||
|
||||
// registers
|
||||
reg [15:0] prer; // clock prescale register
|
||||
reg [ 7:0] ctr; // control register
|
||||
reg [ 7:0] txr; // transmit register
|
||||
wire [ 7:0] rxr; // receive register
|
||||
reg [ 7:0] cr; // command register
|
||||
wire [ 7:0] sr; // status register
|
||||
|
||||
// done signal: command completed, clear command register
|
||||
wire done;
|
||||
|
||||
// core enable signal
|
||||
wire core_en;
|
||||
wire ien;
|
||||
|
||||
// status register signals
|
||||
wire irxack;
|
||||
reg rxack; // received aknowledge from slave
|
||||
reg tip; // transfer in progress
|
||||
reg irq_flag; // interrupt pending flag
|
||||
wire i2c_busy; // bus busy (start signal detected)
|
||||
wire i2c_al; // i2c bus arbitration lost
|
||||
reg al; // status register arbitration lost bit
|
||||
|
||||
//
|
||||
// module body
|
||||
//
|
||||
|
||||
// generate internal reset
|
||||
wire rst_i = arst_i ^ ARST_LVL;
|
||||
|
||||
// generate wishbone signals
|
||||
wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i;
|
||||
|
||||
// generate acknowledge output signal
|
||||
always @(posedge wb_clk_i)
|
||||
wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored
|
||||
|
||||
// assign DAT_O
|
||||
always @(posedge wb_clk_i)
|
||||
begin
|
||||
case (wb_adr_i) // synopsis parallel_case
|
||||
3'b000: wb_dat_o <= #1 prer[ 7:0];
|
||||
3'b001: wb_dat_o <= #1 prer[15:8];
|
||||
3'b010: wb_dat_o <= #1 ctr;
|
||||
3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr)
|
||||
3'b100: wb_dat_o <= #1 sr; // write is command register (cr)
|
||||
3'b101: wb_dat_o <= #1 txr;
|
||||
3'b110: wb_dat_o <= #1 cr;
|
||||
3'b111: wb_dat_o <= #1 0; // reserved
|
||||
endcase
|
||||
end
|
||||
|
||||
// generate registers
|
||||
always @(posedge wb_clk_i or negedge rst_i)
|
||||
if (!rst_i)
|
||||
begin
|
||||
prer <= #1 16'hffff;
|
||||
ctr <= #1 8'h0;
|
||||
txr <= #1 8'h0;
|
||||
end
|
||||
else if (wb_rst_i)
|
||||
begin
|
||||
prer <= #1 16'hffff;
|
||||
ctr <= #1 8'h0;
|
||||
txr <= #1 8'h0;
|
||||
end
|
||||
else
|
||||
if (wb_wacc)
|
||||
case (wb_adr_i) // synopsis parallel_case
|
||||
3'b000 : prer [ 7:0] <= #1 wb_dat_i;
|
||||
3'b001 : prer [15:8] <= #1 wb_dat_i;
|
||||
3'b010 : ctr <= #1 wb_dat_i;
|
||||
3'b011 : txr <= #1 wb_dat_i;
|
||||
default: ;
|
||||
endcase
|
||||
|
||||
// generate command register (special case)
|
||||
always @(posedge wb_clk_i or negedge rst_i)
|
||||
if (~rst_i)
|
||||
cr <= #1 8'h0;
|
||||
else if (wb_rst_i)
|
||||
cr <= #1 8'h0;
|
||||
else if (wb_wacc)
|
||||
begin
|
||||
if (core_en & (wb_adr_i == 3'b100) )
|
||||
cr <= #1 wb_dat_i;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (done | i2c_al)
|
||||
cr[7:4] <= #1 4'h0; // clear command bits when done
|
||||
// or when aribitration lost
|
||||
cr[2:1] <= #1 2'b0; // reserved bits
|
||||
cr[0] <= #1 2'b0; // clear IRQ_ACK bit
|
||||
end
|
||||
|
||||
|
||||
// decode command register
|
||||
wire sta = cr[7];
|
||||
wire sto = cr[6];
|
||||
wire rd = cr[5];
|
||||
wire wr = cr[4];
|
||||
wire ack = cr[3];
|
||||
wire iack = cr[0];
|
||||
|
||||
// decode control register
|
||||
assign core_en = ctr[7];
|
||||
assign ien = ctr[6];
|
||||
|
||||
// hookup byte controller block
|
||||
i2c_master_byte_ctrl byte_controller (
|
||||
.clk ( wb_clk_i ),
|
||||
.rst ( wb_rst_i ),
|
||||
.nReset ( rst_i ),
|
||||
.ena ( core_en ),
|
||||
.clk_cnt ( prer ),
|
||||
.start ( sta ),
|
||||
.stop ( sto ),
|
||||
.read ( rd ),
|
||||
.write ( wr ),
|
||||
.ack_in ( ack ),
|
||||
.din ( txr ),
|
||||
.cmd_ack ( done ),
|
||||
.ack_out ( irxack ),
|
||||
.dout ( rxr ),
|
||||
.i2c_busy ( i2c_busy ),
|
||||
.i2c_al ( i2c_al ),
|
||||
.scl_i ( scl_pad_i ),
|
||||
.scl_o ( scl_pad_o ),
|
||||
.scl_oen ( scl_padoen_o ),
|
||||
.sda_i ( sda_pad_i ),
|
||||
.sda_o ( sda_pad_o ),
|
||||
.sda_oen ( sda_padoen_o )
|
||||
);
|
||||
|
||||
// status register block + interrupt request signal
|
||||
always @(posedge wb_clk_i or negedge rst_i)
|
||||
if (!rst_i)
|
||||
begin
|
||||
al <= #1 1'b0;
|
||||
rxack <= #1 1'b0;
|
||||
tip <= #1 1'b0;
|
||||
irq_flag <= #1 1'b0;
|
||||
end
|
||||
else if (wb_rst_i)
|
||||
begin
|
||||
al <= #1 1'b0;
|
||||
rxack <= #1 1'b0;
|
||||
tip <= #1 1'b0;
|
||||
irq_flag <= #1 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
al <= #1 i2c_al | (al & ~sta);
|
||||
rxack <= #1 irxack;
|
||||
tip <= #1 (rd | wr);
|
||||
irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated
|
||||
end
|
||||
|
||||
// generate interrupt request signals
|
||||
always @(posedge wb_clk_i or negedge rst_i)
|
||||
if (!rst_i)
|
||||
wb_inta_o <= #1 1'b0;
|
||||
else if (wb_rst_i)
|
||||
wb_inta_o <= #1 1'b0;
|
||||
else
|
||||
wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set)
|
||||
|
||||
// assign status register bits
|
||||
assign sr[7] = rxack;
|
||||
assign sr[6] = i2c_busy;
|
||||
assign sr[5] = al;
|
||||
assign sr[4:2] = 3'h0; // reserved
|
||||
assign sr[1] = tip;
|
||||
assign sr[0] = irq_flag;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,176 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// wb_master_model.v ////
|
||||
//// ////
|
||||
//// This file is part of the SPI IP core project ////
|
||||
//// http://www.opencores.org/projects/spi/ ////
|
||||
//// ////
|
||||
//// Author(s): ////
|
||||
//// - Simon Srot (simons@opencores.org) ////
|
||||
//// ////
|
||||
//// Based on: ////
|
||||
//// - i2c/bench/verilog/wb_master_model.v ////
|
||||
//// Copyright (C) 2001 Richard Herveille ////
|
||||
//// ////
|
||||
//// All additional information is avaliable in the Readme.txt ////
|
||||
//// file. ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2002 Authors ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from http://www.opencores.org/lgpl.shtml ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "timescale.v"
|
||||
|
||||
module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty);
|
||||
|
||||
parameter dwidth = 32;
|
||||
parameter awidth = 32;
|
||||
|
||||
input clk, rst;
|
||||
output [awidth -1:0] adr;
|
||||
input [dwidth -1:0] din;
|
||||
output [dwidth -1:0] dout;
|
||||
output cyc, stb;
|
||||
output we;
|
||||
output [dwidth/8 -1:0] sel;
|
||||
input ack, err, rty;
|
||||
|
||||
// Internal signals
|
||||
reg [awidth -1:0] adr;
|
||||
reg [dwidth -1:0] dout;
|
||||
reg cyc, stb;
|
||||
reg we;
|
||||
reg [dwidth/8 -1:0] sel;
|
||||
|
||||
reg [dwidth -1:0] q;
|
||||
|
||||
// Memory Logic
|
||||
initial
|
||||
begin
|
||||
adr = {awidth{1'bx}};
|
||||
dout = {dwidth{1'bx}};
|
||||
cyc = 1'b0;
|
||||
stb = 1'bx;
|
||||
we = 1'hx;
|
||||
sel = {dwidth/8{1'bx}};
|
||||
#1;
|
||||
end
|
||||
|
||||
// Wishbone write cycle
|
||||
task wb_write;
|
||||
input delay;
|
||||
integer delay;
|
||||
|
||||
input [awidth -1:0] a;
|
||||
input [dwidth -1:0] d;
|
||||
|
||||
begin
|
||||
|
||||
// wait initial delay
|
||||
repeat(delay) @(posedge clk);
|
||||
|
||||
// assert wishbone signal
|
||||
#1;
|
||||
adr = a;
|
||||
dout = d;
|
||||
cyc = 1'b1;
|
||||
stb = 1'b1;
|
||||
we = 1'b1;
|
||||
sel = {dwidth/8{1'b1}};
|
||||
@(posedge clk);
|
||||
|
||||
// wait for acknowledge from slave
|
||||
while(~ack) @(posedge clk);
|
||||
|
||||
// negate wishbone signals
|
||||
#1;
|
||||
cyc = 1'b0;
|
||||
stb = 1'bx;
|
||||
adr = {awidth{1'bx}};
|
||||
dout = {dwidth{1'bx}};
|
||||
we = 1'hx;
|
||||
sel = {dwidth/8{1'bx}};
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
// Wishbone read cycle
|
||||
task wb_read;
|
||||
input delay;
|
||||
integer delay;
|
||||
|
||||
input [awidth -1:0] a;
|
||||
output [dwidth -1:0] d;
|
||||
|
||||
begin
|
||||
|
||||
// wait initial delay
|
||||
repeat(delay) @(posedge clk);
|
||||
|
||||
// assert wishbone signals
|
||||
#1;
|
||||
adr = a;
|
||||
dout = {dwidth{1'bx}};
|
||||
cyc = 1'b1;
|
||||
stb = 1'b1;
|
||||
we = 1'b0;
|
||||
sel = {dwidth/8{1'b1}};
|
||||
@(posedge clk);
|
||||
|
||||
// wait for acknowledge from slave
|
||||
while(~ack) @(posedge clk);
|
||||
|
||||
// negate wishbone signals
|
||||
#1;
|
||||
cyc = 1'b0;
|
||||
stb = 1'bx;
|
||||
adr = {awidth{1'bx}};
|
||||
dout = {dwidth{1'bx}};
|
||||
we = 1'hx;
|
||||
sel = {dwidth/8{1'bx}};
|
||||
d = din;
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
// Wishbone compare cycle (read data from location and compare with expected data)
|
||||
task wb_cmp;
|
||||
input delay;
|
||||
integer delay;
|
||||
|
||||
input [awidth -1:0] a;
|
||||
input [dwidth -1:0] d_exp;
|
||||
|
||||
begin
|
||||
wb_read (delay, a, q);
|
||||
|
||||
if (d_exp !== q)
|
||||
$display("Data compare error. Received %h, expected %h at time %t", q, d_exp, $time);
|
||||
end
|
||||
endtask
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// i2cSlave.v ////
|
||||
//// ////
|
||||
//// This file is part of the i2cSlave opencores effort.
|
||||
//// <http://www.opencores.org/cores//> ////
|
||||
//// ////
|
||||
//// Module Description: ////
|
||||
//// You will need to modify this file to implement your
|
||||
//// interface.
|
||||
//// ////
|
||||
//// To Do: ////
|
||||
////
|
||||
//// ////
|
||||
//// Author(s): ////
|
||||
//// - Steve Fielding, sfielding@base2designs.com ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from <http://www.opencores.org/lgpl.shtml> ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
`include "i2cSlave_define.v"
|
||||
|
||||
|
||||
module i2cSlave (
|
||||
clk,
|
||||
rst,
|
||||
sda,
|
||||
scl,
|
||||
tb_readEn,
|
||||
tb_writeEn,
|
||||
tb_addr,
|
||||
tb_dataIn,
|
||||
tb_dataOut
|
||||
);
|
||||
|
||||
input clk;
|
||||
input rst;
|
||||
inout sda;
|
||||
input scl;
|
||||
|
||||
// tb interface
|
||||
input tb_readEn;
|
||||
input tb_writeEn;
|
||||
input [15:0] tb_addr;
|
||||
input [15:0] tb_dataIn;
|
||||
output [15:0] tb_dataOut;
|
||||
|
||||
// local wires and regs
|
||||
reg sdaDeb;
|
||||
reg sclDeb;
|
||||
reg [`DEB_I2C_LEN-1:0] sdaPipe;
|
||||
reg [`DEB_I2C_LEN-1:0] sclPipe;
|
||||
|
||||
reg [`SCL_DEL_LEN-1:0] sclDelayed;
|
||||
reg [`SDA_DEL_LEN-1:0] sdaDelayed;
|
||||
reg [1:0] startStopDetState;
|
||||
wire clearStartStopDet;
|
||||
wire sdaOut;
|
||||
wire sdaIn;
|
||||
wire [15:0] regAddr;
|
||||
wire [7:0] dataToRegIF;
|
||||
wire writeEn;
|
||||
wire [7:0] dataFromRegIF;
|
||||
reg [1:0] rstPipe;
|
||||
wire rstSyncToClk;
|
||||
reg startEdgeDet;
|
||||
|
||||
assign sda = (sdaOut == 1'b0) ? 1'b0 : 1'bz;
|
||||
assign sdaIn = sda;
|
||||
|
||||
// sync rst rsing edge to clk
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1)
|
||||
rstPipe <= 2'b11;
|
||||
else
|
||||
rstPipe <= {rstPipe[0], 1'b0};
|
||||
end
|
||||
|
||||
assign rstSyncToClk = rstPipe[1];
|
||||
|
||||
// debounce sda and scl
|
||||
always @(posedge clk) begin
|
||||
if (rstSyncToClk == 1'b1) begin
|
||||
sdaPipe <= {`DEB_I2C_LEN{1'b1}};
|
||||
sdaDeb <= 1'b1;
|
||||
sclPipe <= {`DEB_I2C_LEN{1'b1}};
|
||||
sclDeb <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
sdaPipe <= {sdaPipe[`DEB_I2C_LEN-2:0], sdaIn};
|
||||
sclPipe <= {sclPipe[`DEB_I2C_LEN-2:0], scl};
|
||||
if (&sclPipe[`DEB_I2C_LEN-1:1] == 1'b1)
|
||||
sclDeb <= 1'b1;
|
||||
else if (|sclPipe[`DEB_I2C_LEN-1:1] == 1'b0)
|
||||
sclDeb <= 1'b0;
|
||||
if (&sdaPipe[`DEB_I2C_LEN-1:1] == 1'b1)
|
||||
sdaDeb <= 1'b1;
|
||||
else if (|sdaPipe[`DEB_I2C_LEN-1:1] == 1'b0)
|
||||
sdaDeb <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// delay scl and sda
|
||||
// sclDelayed is used as a delayed sampling clock
|
||||
// sdaDelayed is only used for start stop detection
|
||||
// Because sda hold time from scl falling is 0nS
|
||||
// sda must be delayed with respect to scl to avoid incorrect
|
||||
// detection of start/stop at scl falling edge.
|
||||
always @(posedge clk) begin
|
||||
if (rstSyncToClk == 1'b1) begin
|
||||
sclDelayed <= {`SCL_DEL_LEN{1'b1}};
|
||||
sdaDelayed <= {`SDA_DEL_LEN{1'b1}};
|
||||
end
|
||||
else begin
|
||||
sclDelayed <= {sclDelayed[`SCL_DEL_LEN-2:0], sclDeb};
|
||||
sdaDelayed <= {sdaDelayed[`SDA_DEL_LEN-2:0], sdaDeb};
|
||||
end
|
||||
end
|
||||
|
||||
// start stop detection
|
||||
always @(posedge clk) begin
|
||||
if (rstSyncToClk == 1'b1) begin
|
||||
startStopDetState <= `NULL_DET;
|
||||
startEdgeDet <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
if (sclDeb == 1'b1 && sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
|
||||
startEdgeDet <= 1'b1;
|
||||
else
|
||||
startEdgeDet <= 1'b0;
|
||||
if (clearStartStopDet == 1'b1)
|
||||
startStopDetState <= `NULL_DET;
|
||||
else if (sclDeb == 1'b1) begin
|
||||
if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b1 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b0)
|
||||
startStopDetState <= `STOP_DET;
|
||||
else if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
|
||||
startStopDetState <= `START_DET;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
registerInterface u_registerInterface(
|
||||
.clk(clk),
|
||||
.addr(regAddr),
|
||||
.dataIn(dataToRegIF),
|
||||
.writeEn(writeEn),
|
||||
.dataOut(dataFromRegIF),
|
||||
.tb_readEn(tb_readEn),
|
||||
.tb_writeEn(tb_writeEn),
|
||||
.tb_addr(tb_addr),
|
||||
.tb_dataIn(tb_dataIn),
|
||||
.tb_dataOut(tb_dataOut)
|
||||
);
|
||||
|
||||
serialInterface u_serialInterface (
|
||||
.clk(clk),
|
||||
.rst(rstSyncToClk | startEdgeDet),
|
||||
.dataIn(dataFromRegIF),
|
||||
.dataOut(dataToRegIF),
|
||||
.writeEn(writeEn),
|
||||
.regAddr(regAddr),
|
||||
.scl(sclDelayed[`SCL_DEL_LEN-1]),
|
||||
.sdaIn(sdaDeb),
|
||||
.sdaOut(sdaOut),
|
||||
.startStopDetState(startStopDetState),
|
||||
.clearStartStopDet(clearStartStopDet)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// ----------------------- i2cSlave_define.v --------------------
|
||||
|
||||
// stream states
|
||||
`define STREAM_IDLE 2'b00
|
||||
`define STREAM_READ 2'b01
|
||||
`define STREAM_WRITE_ADDR 2'b10
|
||||
`define STREAM_WRITE_DATA 2'b11
|
||||
|
||||
// start stop detection states
|
||||
`define NULL_DET 2'b00
|
||||
`define START_DET 2'b01
|
||||
`define STOP_DET 2'b10
|
||||
|
||||
// i2c ack and nak
|
||||
`define I2C_NAK 1'b1
|
||||
`define I2C_ACK 1'b0
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// ------------- modify constants below this line -----------------
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// i2c device address
|
||||
`define I2C_ADDRESS 7'h3c
|
||||
|
||||
// System clock frequency in MHz
|
||||
// If you are using a clock frequency below 24MHz, then the macro
|
||||
// for SDA_DEL_LEN will result in compile errors for i2cSlave.v
|
||||
// you will need to hand tweak the SDA_DEL_LEN constant definition
|
||||
`define CLK_FREQ 48
|
||||
|
||||
// Debounce SCL and SDA over this many clock ticks
|
||||
// The rise time of SCL and SDA can be up to 1000nS (in standard mode)
|
||||
// so it is essential to debounce the inputs.
|
||||
// The spec requires 0.05V of hysteresis, but in practise
|
||||
// simply debouncing the inputs is sufficient
|
||||
// I2C spec requires suppresion of spikes of
|
||||
// maximum duration 50nS, so this debounce time should be greater than 50nS
|
||||
// Also increases data hold time and decreases data setup time
|
||||
// during an I2C read operation
|
||||
// 10 ticks = 208nS @ 48MHz
|
||||
`define DEB_I2C_LEN (10*`CLK_FREQ)/48
|
||||
|
||||
// Delay SCL for use as internal sampling clock
|
||||
// Using delayed version of SCL to ensure that
|
||||
// SDA is stable when it is sampled.
|
||||
// Not entirely citical, as according to I2C spec
|
||||
// SDA should have a minimum of 100nS of set up time
|
||||
// with respect to SCL rising edge. But with the very slow edge
|
||||
// speeds used in I2C it is better to err on the side of caution.
|
||||
// This delay also has the effect of adding extra hold time to the data
|
||||
// with respect to SCL falling edge. I2C spec requires 0nS of data hold time.
|
||||
// 10 ticks = 208nS @ 48MHz
|
||||
`define SCL_DEL_LEN (10*`CLK_FREQ)/48
|
||||
|
||||
// Delay SDA for use in start/stop detection
|
||||
// Use delayed SDA during start/stop detection to avoid
|
||||
// incorrect detection at SCL falling edge.
|
||||
// From I2C spec start/stop setup is 600nS with respect to SCL rising edge
|
||||
// and start/stop hold is 600nS wrt SCL falling edge.
|
||||
// So it is relatively easy to discriminate start/stop,
|
||||
// but data setup time is a minimum of 100nS with respect to SCL rising edge
|
||||
// and 0nS hold wrt to SCL falling edge.
|
||||
// So the tricky part is providing robust start/stop detection
|
||||
// in the presence of regular data transitions.
|
||||
// This delay time should be less than 100nS
|
||||
// 4 ticks = 83nS @ 48MHz
|
||||
`define SDA_DEL_LEN (4*`CLK_FREQ)/48
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// registerInterface.v ////
|
||||
//// ////
|
||||
//// This file is part of the i2cSlave opencores effort.
|
||||
//// <http://www.opencores.org/cores//> ////
|
||||
//// ////
|
||||
//// Module Description: ////
|
||||
//// You will need to modify this file to implement your
|
||||
//// interface.
|
||||
//// Add your control and status bytes/bits to module inputs and outputs,
|
||||
//// and also to the I2C read and write process blocks
|
||||
//// ////
|
||||
//// To Do: ////
|
||||
////
|
||||
//// ////
|
||||
//// Author(s): ////
|
||||
//// - Steve Fielding, sfielding@base2designs.com ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from <http://www.opencores.org/lgpl.shtml> ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
`include "i2cSlave_define.v"
|
||||
|
||||
|
||||
module registerInterface (
|
||||
clk,
|
||||
addr,
|
||||
dataIn,
|
||||
writeEn,
|
||||
dataOut,
|
||||
tb_readEn,
|
||||
tb_writeEn,
|
||||
tb_addr,
|
||||
tb_dataIn,
|
||||
tb_dataOut
|
||||
);
|
||||
|
||||
// i2c interface
|
||||
input clk;
|
||||
input [15:0] addr;
|
||||
input [7:0] dataIn;
|
||||
input writeEn;
|
||||
output [7:0] dataOut;
|
||||
reg [7:0] dataOut;
|
||||
|
||||
// speicher
|
||||
reg [7:0] memory [16'hffff:0];
|
||||
|
||||
// tb interface
|
||||
input tb_readEn;
|
||||
input tb_writeEn;
|
||||
input [15:0] tb_addr;
|
||||
input [15:0] tb_dataIn;
|
||||
output [15:0] tb_dataOut;
|
||||
reg [15:0] tb_dataOut;
|
||||
|
||||
// --- TB Read
|
||||
always @(posedge tb_readEn) begin
|
||||
tb_dataOut[15:8] <= memory[tb_addr];
|
||||
tb_dataOut[7:0] <= memory[tb_addr + 1'b1];
|
||||
end
|
||||
|
||||
// --- TB Write
|
||||
always @(posedge tb_writeEn) begin
|
||||
memory[tb_addr] <= tb_dataIn[15:8];
|
||||
memory[tb_addr + 1'b1] <= tb_dataIn[7:0];
|
||||
end
|
||||
|
||||
// --- I2C Read
|
||||
always @(posedge clk) begin
|
||||
dataOut <= memory[addr];
|
||||
end
|
||||
|
||||
// --- I2C Write
|
||||
always @(posedge clk) begin
|
||||
if (writeEn == 1'b1) begin
|
||||
memory[addr] <= dataIn;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// serialInterface.v ////
|
||||
//// ////
|
||||
//// This file is part of the i2cSlave opencores effort.
|
||||
//// <http://www.opencores.org/cores//> ////
|
||||
//// ////
|
||||
//// Module Description: ////
|
||||
//// Perform all serial to parallel, and parallel
|
||||
//// to serial conversions. Perform device address matching
|
||||
//// Handle arbitrary length I2C reads terminated by NAK
|
||||
//// from host, and arbitrary length I2C writes terminated
|
||||
//// by STOP from host
|
||||
//// The second byte of a I2C write is always interpreted
|
||||
//// as a register address, and becomes the base register address
|
||||
//// for all read and write transactions.
|
||||
//// I2C WRITE: devAddr, regAddr, data[regAddr], data[regAddr+1], ..... data[regAddr+N]
|
||||
//// I2C READ: data[regAddr], data[regAddr+1], ..... data[regAddr+N]
|
||||
//// Note that when regAddR reaches 255 it will automatically wrap round to 0
|
||||
//// ////
|
||||
//// To Do: ////
|
||||
////
|
||||
//// ////
|
||||
//// Author(s): ////
|
||||
//// - Steve Fielding, sfielding@base2designs.com ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from <http://www.opencores.org/lgpl.shtml> ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
`include "timescale.v"
|
||||
`include "i2cSlave_define.v"
|
||||
|
||||
module serialInterface (clearStartStopDet, clk, dataIn, dataOut, regAddr, rst, scl, sdaIn, sdaOut, startStopDetState, writeEn);
|
||||
input clk;
|
||||
input [7:0]dataIn;
|
||||
input rst;
|
||||
input scl;
|
||||
input sdaIn;
|
||||
input [1:0]startStopDetState;
|
||||
output clearStartStopDet;
|
||||
output [7:0]dataOut;
|
||||
output [15:0]regAddr;
|
||||
output sdaOut;
|
||||
output writeEn;
|
||||
|
||||
reg clearStartStopDet, next_clearStartStopDet;
|
||||
wire clk;
|
||||
wire [7:0]dataIn;
|
||||
reg [7:0]dataOut, next_dataOut;
|
||||
reg [15:0]regAddr, next_regAddr;
|
||||
reg regAddr_hiByte = 1'b0; //high and low byte of regAddr
|
||||
wire rst;
|
||||
wire scl;
|
||||
wire sdaIn;
|
||||
reg sdaOut, next_sdaOut;
|
||||
wire [1:0]startStopDetState;
|
||||
reg writeEn, next_writeEn;
|
||||
|
||||
// diagram signals declarations
|
||||
reg [2:0]bitCnt, next_bitCnt;
|
||||
reg [7:0]rxData, next_rxData;
|
||||
reg [1:0]streamSt, next_streamSt;
|
||||
reg [7:0]txData, next_txData;
|
||||
|
||||
// BINARY ENCODED state machine: SISt
|
||||
// State codes definitions:
|
||||
`define START 4'b0000
|
||||
`define CHK_RD_WR 4'b0001
|
||||
`define READ_RD_LOOP 4'b0010
|
||||
`define READ_WT_HI 4'b0011
|
||||
`define READ_CHK_LOOP_FIN 4'b0100
|
||||
`define READ_WT_LO 4'b0101
|
||||
`define READ_WT_ACK 4'b0110
|
||||
`define WRITE_WT_LO 4'b0111
|
||||
`define WRITE_WT_HI 4'b1000
|
||||
`define WRITE_CHK_LOOP_FIN 4'b1001
|
||||
`define WRITE_LOOP_WT_LO 4'b1010
|
||||
`define WRITE_ST_LOOP 4'b1011
|
||||
`define WRITE_WT_LO2 4'b1100
|
||||
`define WRITE_WT_HI2 4'b1101
|
||||
`define WRITE_CLR_WR 4'b1110
|
||||
`define WRITE_CLR_ST_STOP 4'b1111
|
||||
|
||||
reg [3:0]CurrState_SISt, NextState_SISt;
|
||||
|
||||
// Diagram actions (continuous assignments allowed only: assign ...)
|
||||
// diagram ACTION
|
||||
|
||||
|
||||
// Machine: SISt
|
||||
|
||||
// NextState logic (combinatorial)
|
||||
always @ (startStopDetState or streamSt or scl or txData or bitCnt or rxData or sdaIn or regAddr or dataIn or sdaOut or writeEn or dataOut or clearStartStopDet or CurrState_SISt)
|
||||
begin
|
||||
NextState_SISt <= CurrState_SISt;
|
||||
// Set default values for outputs and signals
|
||||
next_streamSt <= streamSt;
|
||||
next_txData <= txData;
|
||||
next_rxData <= rxData;
|
||||
next_sdaOut <= sdaOut;
|
||||
next_writeEn <= writeEn;
|
||||
next_dataOut <= dataOut;
|
||||
next_bitCnt <= bitCnt;
|
||||
next_clearStartStopDet <= clearStartStopDet;
|
||||
next_regAddr <= regAddr;
|
||||
case (CurrState_SISt) // synopsys parallel_case full_case
|
||||
`START:
|
||||
begin
|
||||
next_streamSt <= `STREAM_IDLE;
|
||||
next_txData <= 8'h00;
|
||||
next_rxData <= 8'h00;
|
||||
next_sdaOut <= 1'b1;
|
||||
next_writeEn <= 1'b0;
|
||||
next_dataOut <= 8'h00;
|
||||
next_bitCnt <= 3'b000;
|
||||
next_clearStartStopDet <= 1'b0;
|
||||
NextState_SISt <= `CHK_RD_WR;
|
||||
end
|
||||
`CHK_RD_WR:
|
||||
begin
|
||||
if (streamSt == `STREAM_READ)
|
||||
begin
|
||||
NextState_SISt <= `READ_RD_LOOP;
|
||||
next_txData <= dataIn;
|
||||
next_regAddr <= regAddr + 1'b1;
|
||||
next_bitCnt <= 3'b001;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NextState_SISt <= `WRITE_WT_HI;
|
||||
next_rxData <= 8'h00;
|
||||
end
|
||||
end
|
||||
`READ_RD_LOOP:
|
||||
begin
|
||||
if (scl == 1'b0)
|
||||
begin
|
||||
NextState_SISt <= `READ_WT_HI;
|
||||
next_sdaOut <= txData [7];
|
||||
next_txData <= {txData [6:0], 1'b0};
|
||||
end
|
||||
end
|
||||
`READ_WT_HI:
|
||||
begin
|
||||
if (scl == 1'b1)
|
||||
begin
|
||||
NextState_SISt <= `READ_CHK_LOOP_FIN;
|
||||
end
|
||||
end
|
||||
`READ_CHK_LOOP_FIN:
|
||||
begin
|
||||
if (bitCnt == 3'b000)
|
||||
begin
|
||||
NextState_SISt <= `READ_WT_LO;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NextState_SISt <= `READ_RD_LOOP;
|
||||
next_bitCnt <= bitCnt + 1'b1;
|
||||
end
|
||||
end
|
||||
`READ_WT_LO:
|
||||
begin
|
||||
if (scl == 1'b0)
|
||||
begin
|
||||
NextState_SISt <= `READ_WT_ACK;
|
||||
next_sdaOut <= 1'b1;
|
||||
end
|
||||
end
|
||||
`READ_WT_ACK:
|
||||
begin
|
||||
if (scl == 1'b1)
|
||||
begin
|
||||
NextState_SISt <= `CHK_RD_WR;
|
||||
if (sdaIn == `I2C_NAK)
|
||||
next_streamSt <= `STREAM_IDLE;
|
||||
end
|
||||
end
|
||||
`WRITE_WT_LO:
|
||||
begin
|
||||
if ((scl == 1'b0) && (startStopDetState == `STOP_DET ||
|
||||
(streamSt == `STREAM_IDLE && startStopDetState == `NULL_DET)))
|
||||
begin
|
||||
NextState_SISt <= `WRITE_CLR_ST_STOP;
|
||||
case (startStopDetState)
|
||||
`NULL_DET:
|
||||
next_bitCnt <= bitCnt + 1'b1;
|
||||
`START_DET: begin
|
||||
next_streamSt <= `STREAM_IDLE;
|
||||
next_rxData <= 8'h00;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
next_streamSt <= `STREAM_IDLE;
|
||||
next_clearStartStopDet <= 1'b1;
|
||||
end
|
||||
else if (scl == 1'b0)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_ST_LOOP;
|
||||
case (startStopDetState)
|
||||
`NULL_DET:
|
||||
next_bitCnt <= bitCnt + 1'b1;
|
||||
`START_DET: begin
|
||||
next_streamSt <= `STREAM_IDLE;
|
||||
next_rxData <= 8'h00;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`WRITE_WT_HI:
|
||||
begin
|
||||
if (scl == 1'b1)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_WT_LO;
|
||||
next_rxData <= {rxData [6:0], sdaIn};
|
||||
next_bitCnt <= 3'b000;
|
||||
end
|
||||
end
|
||||
`WRITE_CHK_LOOP_FIN:
|
||||
begin
|
||||
if (bitCnt == 3'b111)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_CLR_WR;
|
||||
next_sdaOut <= `I2C_ACK;
|
||||
case (streamSt)
|
||||
`STREAM_IDLE: begin
|
||||
if (rxData[7:1] == `I2C_ADDRESS && startStopDetState == `START_DET) begin
|
||||
if (rxData[0] == 1'b1)
|
||||
next_streamSt <= `STREAM_READ;
|
||||
else
|
||||
next_streamSt <= `STREAM_WRITE_ADDR;
|
||||
end
|
||||
else
|
||||
next_sdaOut <= `I2C_NAK;
|
||||
end
|
||||
`STREAM_WRITE_ADDR: begin
|
||||
if(regAddr_hiByte == 0) begin
|
||||
next_regAddr[15:8] <= rxData;
|
||||
regAddr_hiByte <= 1;
|
||||
end
|
||||
else begin
|
||||
next_streamSt <= `STREAM_WRITE_DATA;
|
||||
next_regAddr[7:0] <= rxData;
|
||||
regAddr_hiByte <= 0;
|
||||
end
|
||||
end
|
||||
`STREAM_WRITE_DATA: begin
|
||||
next_dataOut <= rxData;
|
||||
next_writeEn <= 1'b1;
|
||||
end
|
||||
default:
|
||||
next_streamSt <= streamSt;
|
||||
endcase
|
||||
end
|
||||
else
|
||||
begin
|
||||
NextState_SISt <= `WRITE_ST_LOOP;
|
||||
next_bitCnt <= bitCnt + 1'b1;
|
||||
end
|
||||
end
|
||||
`WRITE_LOOP_WT_LO:
|
||||
begin
|
||||
if (scl == 1'b0)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_CHK_LOOP_FIN;
|
||||
end
|
||||
end
|
||||
`WRITE_ST_LOOP:
|
||||
begin
|
||||
if (scl == 1'b1)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_LOOP_WT_LO;
|
||||
next_rxData <= {rxData [6:0], sdaIn};
|
||||
end
|
||||
end
|
||||
`WRITE_WT_LO2:
|
||||
begin
|
||||
if (scl == 1'b0)
|
||||
begin
|
||||
NextState_SISt <= `CHK_RD_WR;
|
||||
next_sdaOut <= 1'b1;
|
||||
end
|
||||
end
|
||||
`WRITE_WT_HI2:
|
||||
begin
|
||||
next_clearStartStopDet <= 1'b0;
|
||||
if (scl == 1'b1)
|
||||
begin
|
||||
NextState_SISt <= `WRITE_WT_LO2;
|
||||
end
|
||||
end
|
||||
`WRITE_CLR_WR:
|
||||
begin
|
||||
if (writeEn == 1'b1)
|
||||
next_regAddr <= regAddr + 1'b1;
|
||||
next_writeEn <= 1'b0;
|
||||
next_clearStartStopDet <= 1'b1;
|
||||
NextState_SISt <= `WRITE_WT_HI2;
|
||||
end
|
||||
`WRITE_CLR_ST_STOP:
|
||||
begin
|
||||
next_clearStartStopDet <= 1'b0;
|
||||
NextState_SISt <= `CHK_RD_WR;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// Current State Logic (sequential)
|
||||
always @ (posedge clk)
|
||||
begin
|
||||
if (rst == 1'b1)
|
||||
CurrState_SISt <= `START;
|
||||
else
|
||||
CurrState_SISt <= NextState_SISt;
|
||||
end
|
||||
|
||||
// Registered outputs logic
|
||||
always @ (posedge clk)
|
||||
begin
|
||||
if (rst == 1'b1)
|
||||
begin
|
||||
sdaOut <= 1'b1;
|
||||
writeEn <= 1'b0;
|
||||
dataOut <= 8'h00;
|
||||
clearStartStopDet <= 1'b0;
|
||||
// regAddr <= // Initialization in the reset state or default value required!!
|
||||
streamSt <= `STREAM_IDLE;
|
||||
txData <= 8'h00;
|
||||
rxData <= 8'h00;
|
||||
bitCnt <= 3'b000;
|
||||
end
|
||||
else
|
||||
begin
|
||||
sdaOut <= next_sdaOut;
|
||||
writeEn <= next_writeEn;
|
||||
dataOut <= next_dataOut;
|
||||
clearStartStopDet <= next_clearStartStopDet;
|
||||
regAddr <= next_regAddr;
|
||||
streamSt <= next_streamSt;
|
||||
txData <= next_txData;
|
||||
rxData <= next_rxData;
|
||||
bitCnt <= next_bitCnt;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,5 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// timescale.v
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
iverilog -o testHarness -c filelist.icarus
|
||||
@@ -0,0 +1,16 @@
|
||||
../rtl/serialInterface.v
|
||||
../rtl/registerInterface.v
|
||||
../rtl/i2cSlave.v
|
||||
../model/i2c_master_bit_ctrl.v
|
||||
../model/i2c_master_byte_ctrl.v
|
||||
../model/i2c_master_top.v
|
||||
../model/wb_master_model.v
|
||||
../bench/multiByteReadWrite.v
|
||||
../bench/testHarness.v
|
||||
../bench/testCase0.v
|
||||
|
||||
+incdir+../rtl
|
||||
+incdir+../bench
|
||||
+incdir+../model
|
||||
+define+SIM_COMPILE
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# sample rc file
|
||||
#
|
||||
hier_max_level 1
|
||||
force_toolbars 0
|
||||
|
||||
dynamic_resizing 1
|
||||
hpane_pack 1
|
||||
use_vcd 0
|
||||
#initial_window_x 700
|
||||
#initial_window_y 400
|
||||
use_maxtime_display 0
|
||||
|
||||
enable_vcd_autosave 0
|
||||
use_roundcaps 1
|
||||
|
||||
use_nonprop_fonts yes
|
||||
enable_horiz_grid yes
|
||||
use_big_fonts no
|
||||
constant_marker_update yes
|
||||
show_grid yes
|
||||
show_base_symbols no
|
||||
use_roundcaps yes
|
||||
|
||||
atomic_vectors yes
|
||||
vcd_explicit_zero_subscripts no
|
||||
|
||||
#
|
||||
# color additions
|
||||
#
|
||||
color_back 000000
|
||||
color_grid 202070
|
||||
color_high 00ff00
|
||||
color_low 008000
|
||||
color_trans 00c000
|
||||
color_mid c0c000
|
||||
|
||||
color_value ffffff
|
||||
color_vbox 00ff00
|
||||
color_vtrans 00c000
|
||||
|
||||
color_x 00ff00
|
||||
color_xfill 004000
|
||||
|
||||
color_umark ff8080
|
||||
color_mark ffff80
|
||||
|
||||
color_time ffffff
|
||||
color_timeb 000000
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
*-27.236394 43400000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
@28
|
||||
testHarness.u_i2cSlave.scl
|
||||
testHarness.u_i2cSlave.sda
|
||||
@22
|
||||
testHarness.u_i2cSlave.tb_readEn
|
||||
testHarness.u_i2cSlave.tb_writeEn
|
||||
testHarness.u_i2cSlave.tb_addr[15:0]
|
||||
testHarness.u_i2cSlave.tb_dataIn[15:0]
|
||||
testHarness.u_i2cSlave.tb_dataOut[15:0]
|
||||
@@ -0,0 +1,2 @@
|
||||
vvp testHarness
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
iverilog -o testHarness -cfilelist.icarus && vvp testHarness
|
||||
@@ -0,0 +1 @@
|
||||
gtkwave wave.vcd myWave.sav
|
||||
Reference in new issue
Block a user