1) show phpinfo
<?php
phpinfo();
?>
2) array
$data_arr = array();
Monday, March 31, 2014
some basic systemVerilog syntax
1) Integer data types
2) Default values
10) class
/////////////////////////////////////////////
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
endclass: cpu_transaction
11) program
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
program test(cpu_interface.master cpu_intf);
initial begin
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`include "cpu_interface.svi"
`include "test.sv"
module top;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
endmodule
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/program
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/program
SVTB = $(TB_DIR)/test.sv
SVTB += $(TB_DIR)/top.sv
INCDIR = +incdir+/mnt/program
COMPILE_LOG_ARG = -l vcs.log
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
12) interface
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
program test(cpu_interface.master cpu_intf);
event done;
initial begin
cpu_intf.rst_n <= 1'b0;
cpu_intf.cb.addr <= 8'h0;
cpu_intf.cb.data <= 32'h0;
cpu_intf.cb.rw <= 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n <= 1'b1;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h1;
cpu_intf.cb.data <= 32'h1;
cpu_intf.cb.rw <= 1'b0;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h2;
cpu_intf.cb.data <= 32'h2;
cpu_intf.cb.rw <= 1'b1;
->done;
end
initial begin
@done;
#10 $finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2)
clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/interface
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/interface
SVTB = $(TB_DIR)/test.sv
SVTB += $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
100) transaction
/////////////////////////////////////////////
//cpu_transaction
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h", prefix, $realtime, name, addr, data);
endfunction
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_transaction.sv"
program test();
event done;
initial begin
cpu_transaction cpu_tran;
cpu_tran = new();
repeat(10) begin
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
cpu_tran.display();
#1;
end
->done;
end
initial begin
@done;
#10 $finish();
end
endprogram
`endif
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/transaction
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/transaction
SVTB = $(TB_DIR)/test.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
101) generator
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h", prefix, $realtime, name, addr, data);
endfunction
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran = new();
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
out_box.put(cpu_tran);
end
->done;
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_generator.sv"
`include "cpu_define.sv"
program test();
event done;
cpu_tran_mbox mbox = new();
cpu_generator cpu_gen;
initial begin
cpu_gen = new("CPU Generator", mbox);
cpu_gen.run_for_n_trans = 10;
cpu_gen.start();
end
initial begin
cpu_transaction cpu_tran;
forever begin
mbox.get(cpu_tran);
cpu_tran.display();
end
end
initial begin
@cpu_gen.done;
#10 $finish();
end
endprogram
`endif
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/generator
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/generator
SVTB = $(TB_DIR)/test.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
102) driver
/////////////////////////////////////////////
/////////////////////////////////////////////
/////////////////////////////////////////////
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
rand logic rw;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h, rw = %d", prefix, $realtime, name, addr, data, rw);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran = new();
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
out_box.put(cpu_tran);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.data <= cpu_tran.data;
cpu_intf.cb.rw <= cpu_tran.rw;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h0 ;
cpu_intf.cb.data <= 32'h0 ;
cpu_intf.cb.rw <= 1'b1 ;
end
join_none
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
program test(cpu_interface.master cpu_intf);
event done;
cpu_tran_mbox mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
initial begin
cpu_gen = new("CPU Generator", mbox);
cpu_drv = new("CPU Driver", mbox, cpu_intf);
cpu_gen.run_for_n_trans = 10;
cpu_gen.start();
cpu_drv.start();
@cpu_gen.done;
repeat(100) @(cpu_intf.cb);
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/driver
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/driver
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
103) monitor
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(addr) begin
case(addr)
8'h0 : dout = config_reg;
8'h1 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
//driver and monitor in the same bfm
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
cpu_intf.cb.addr <= 8'h0 ;
cpu_intf.cb.din <= 32'h0 ;
cpu_intf.cb.rw <= 1'b1 ;
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
event done;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_transaction_ext cpu_tran_ext = new();
initial begin
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
cpu_gen.cpu_tran = cpu_tran_ext;
cpu_gen.run_for_n_trans = 100;
cpu_gen.start();
cpu_drv.start();
@cpu_gen.done;
repeat(100) @(cpu_intf.cb);
$finish();
end
initial begin
cpu_transaction cpu_tran = new();
forever begin
mon_mbox.get(cpu_tran);
cpu_tran.display("Monitor Mbox");
end
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/monitor
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/monitor
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
103) scoreboard
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
if(cpu_tran.rw == 1'b1) begin
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
end
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_scoreboard.sv
/////////////////////////////////////////////
`ifndef __CPU_SCOREBOARD_SV__
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_scoreboard;
string name;
cpu_tran_mbox in_box;
cpu_transaction cpu_tran;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
extern function new(string name = "CPU Scoreboard", cpu_tran_mbox in_box);
extern task start();
extern task check();
extern function display(string prefix = "CPU Scoreboard Result");
endclass
function cpu_scoreboard::new(string name, cpu_tran_mbox in_box);
this.name = name;
this.in_box = in_box;
for(int i=0; i<128; i++) begin
cpu_reg[i] = 32'h0;
end
endfunction
task cpu_scoreboard::start();
fork
forever begin
in_box.get(cpu_tran);
total_no++;
check();
end
join_none
endtask
task cpu_scoreboard::check();
string message;
if(cpu_tran.rw == 1'b0) begin
cpu_reg[cpu_tran.addr] = cpu_tran.din;
end
else if(cpu_tran.rw == 1'b1) begin
if(cpu_reg[cpu_tran.addr] != cpu_tran.dout) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, cpu_tran.dout = %0h\n", cpu_tran.addr, cpu_reg[cpu_tran.addr], cpu_tran.dout) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] cpu_tran.rw can only be 0 or 1");
error_no++;
end
endtask
function cpu_scoreboard::display(string prefix);
$display("Total: %d, Error: %d", total_no, error_no);
endfunction
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
`include "cpu_scoreboard.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
event done;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_transaction_ext cpu_tran_ext = new();
cpu_scoreboard cpu_sb;
initial begin
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
cpu_sb = new("CPU Scoreboard", mon_mbox);
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
cpu_gen.cpu_tran = cpu_tran_ext;
cpu_gen.run_for_n_trans = 100;
cpu_gen.start();
cpu_drv.start();
cpu_sb.start();
@cpu_gen.done;
repeat(1000) begin
@(cpu_intf.cb);
if(cpu_sb.total_no == cpu_gen.run_for_n_trans) begin
break;
end
end
cpu_sb.display();
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/scoreboard
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/scoreboard
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
104) env
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
begin
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
if(cpu_tran.rw == 1'b1) begin
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
end
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_scoreboard.sv
/////////////////////////////////////////////
`ifndef __CPU_SCOREBOARD_SV__
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_scoreboard;
string name;
cpu_tran_mbox in_box;
cpu_transaction cpu_tran;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
extern function new(string name = "CPU Scoreboard", cpu_tran_mbox in_box);
extern task start();
extern task check();
extern function display(string prefix = "CPU Scoreboard Result");
endclass
function cpu_scoreboard::new(string name, cpu_tran_mbox in_box);
this.name = name;
this.in_box = in_box;
for(int i=0; i<128; i++) begin
cpu_reg[i] = 32'h0;
end
endfunction
task cpu_scoreboard::start();
fork
forever begin
in_box.get(cpu_tran);
total_no++;
check();
end
join_none
endtask
task cpu_scoreboard::check();
string message;
if(cpu_tran.rw == 1'b0) begin
cpu_reg[cpu_tran.addr] = cpu_tran.din;
end
else if(cpu_tran.rw == 1'b1) begin
if(cpu_reg[cpu_tran.addr] != cpu_tran.dout) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, cpu_tran.dout = %0h\n", cpu_tran.addr, cpu_reg[cpu_tran.addr], cpu_tran.dout) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] cpu_tran.rw can only be 0 or 1");
error_no++;
end
endtask
function cpu_scoreboard::display(string prefix);
$display("Total: %d, Error: %d", total_no, error_no);
endfunction
`endif
/////////////////////////////////////////////
//cpu_env.sv
/////////////////////////////////////////////
`ifndef __CPU_ENV_SV__
`define __CPU_ENV_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
`include "cpu_scoreboard.sv"
class cpu_env;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_scoreboard cpu_sb;
virtual cpu_interface.master cpu_intf;
extern function new(virtual cpu_interface.master cpu_intf);
extern function configure();
extern task reset();
extern task start();
endclass
function cpu_env::new(virtual cpu_interface.master cpu_intf);
this.cpu_intf = cpu_intf;
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
cpu_sb = new("CPU Scoreboard", mon_mbox);
endfunction
function cpu_env::configure();
endfunction
task cpu_env::reset();
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
endtask
task cpu_env::start();
cpu_gen.start();
cpu_drv.start();
cpu_sb.start();
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_env.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
cpu_transaction_ext cpu_tran_ext = new();
cpu_env cpu_e;
initial begin
cpu_e = new(cpu_intf);
cpu_e.configure();
cpu_e.cpu_gen.cpu_tran = cpu_tran_ext;
cpu_e.cpu_gen.run_for_n_trans = 100;
cpu_e.reset();
cpu_e.start();
@cpu_e.cpu_gen.done;
repeat(1000) begin
@(cpu_intf.cb);
if(cpu_e.cpu_sb.total_no == cpu_e.cpu_gen.run_for_n_trans) begin
break;
end
end
cpu_e.cpu_sb.display();
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/env
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/env
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
110) driver and monitor are in 2 different class (bfm)
link: http://scott2595.blogspot.com/2014/08/an-example-of-systemverilog-tb.html
111) TB env with 2 TB envs
linke: http://scott2595.blogspot.com/2014/10/an-example-of-sv-tb-with-callback.html
shortint | 2-state SystemVerilog data type, 16 bit signed integer |
int | 2-state SystemVerilog data type, 32 bit signed integer |
longint | 2-state SystemVerilog data type, 64 bit signed integer |
byte | 2-state SystemVerilog data type, 8 bit signed integer or ASCII character |
bit | 2-state SystemVerilog data type, user-defined vector size |
logic | 4-state SystemVerilog data type, user-defined vector size |
reg | 4-state Verilog-2001 data type, user-defined vector size |
integer | 4-state Verilog-2001 data type, 32 bit signed integer |
time | 4-state Verilog-2001 data type, 64-bit unsigned integer |
2) Default values
Type | Default Initial value |
4 state | integral ’X |
2 state | integral ’0 |
real, shortreal | 0.0 |
Enumeration | First value in the enumeration |
string | "" (empty string) |
event | New event |
class | null |
chandle | (Opaque handle) null |
10) class
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
class cpu_transaction;logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
endclass: cpu_transaction
11) program
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
program test(cpu_interface.master cpu_intf);
initial begin
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`include "cpu_interface.svi"
`include "test.sv"
module top;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
endmodule
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/program
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/program
SVTB = $(TB_DIR)/test.sv
SVTB += $(TB_DIR)/top.sv
INCDIR = +incdir+/mnt/program
COMPILE_LOG_ARG = -l vcs.log
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
12) interface
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
program test(cpu_interface.master cpu_intf);
event done;
initial begin
cpu_intf.rst_n <= 1'b0;
cpu_intf.cb.addr <= 8'h0;
cpu_intf.cb.data <= 32'h0;
cpu_intf.cb.rw <= 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n <= 1'b1;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h1;
cpu_intf.cb.data <= 32'h1;
cpu_intf.cb.rw <= 1'b0;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h2;
cpu_intf.cb.data <= 32'h2;
cpu_intf.cb.rw <= 1'b1;
->done;
end
initial begin
@done;
#10 $finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2)
clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/interface
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/interface
SVTB = $(TB_DIR)/test.sv
SVTB += $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
100) transaction
/////////////////////////////////////////////
//cpu_transaction
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h", prefix, $realtime, name, addr, data);
endfunction
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_transaction.sv"
program test();
event done;
initial begin
cpu_transaction cpu_tran;
cpu_tran = new();
repeat(10) begin
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
cpu_tran.display();
#1;
end
->done;
end
initial begin
@done;
#10 $finish();
end
endprogram
`endif
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/transaction
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/transaction
SVTB = $(TB_DIR)/test.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
101) generator
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h", prefix, $realtime, name, addr, data);
endfunction
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran = new();
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
out_box.put(cpu_tran);
end
->done;
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_generator.sv"
`include "cpu_define.sv"
program test();
event done;
cpu_tran_mbox mbox = new();
cpu_generator cpu_gen;
initial begin
cpu_gen = new("CPU Generator", mbox);
cpu_gen.run_for_n_trans = 10;
cpu_gen.start();
end
initial begin
cpu_transaction cpu_tran;
forever begin
mbox.get(cpu_tran);
cpu_tran.display();
end
end
initial begin
@cpu_gen.done;
#10 $finish();
end
endprogram
`endif
#############################################
#Makefile
#############################################
RTL_DIR = /mnt/generator
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/generator
SVTB = $(TB_DIR)/test.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
102) driver
/////////////////////////////////////////////
/////////////////////////////////////////////
//driver and monitor in the same bfm/////////////////////////////////////////////
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
rand logic [7:0] addr;
rand logic [31:0] data;
rand logic rw;
string name;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, data = %0h, rw = %d", prefix, $realtime, name, addr, data, rw);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] data ;
logic rw ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output data ;
output rw ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran = new();
if(!cpu_tran.randomize()) begin
$display("Error to randomize cpu_tran");
end
out_box.put(cpu_tran);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.data <= cpu_tran.data;
cpu_intf.cb.rw <= cpu_tran.rw;
@(cpu_intf.cb);
cpu_intf.cb.addr <= 8'h0 ;
cpu_intf.cb.data <= 32'h0 ;
cpu_intf.cb.rw <= 1'b1 ;
end
join_none
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
program test(cpu_interface.master cpu_intf);
event done;
cpu_tran_mbox mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
initial begin
cpu_gen = new("CPU Generator", mbox);
cpu_drv = new("CPU Driver", mbox, cpu_intf);
cpu_gen.run_for_n_trans = 10;
cpu_gen.start();
cpu_drv.start();
@cpu_gen.done;
repeat(100) @(cpu_intf.cb);
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/driver
#RTL = $(RTL_DIR)/rtl/router.v
TB_DIR = /mnt/driver
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
103) monitor
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(addr) begin
case(addr)
8'h0 : dout = config_reg;
8'h1 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
//driver and monitor in the same bfm
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
cpu_intf.cb.addr <= 8'h0 ;
cpu_intf.cb.din <= 32'h0 ;
cpu_intf.cb.rw <= 1'b1 ;
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
event done;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_transaction_ext cpu_tran_ext = new();
initial begin
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
cpu_gen.cpu_tran = cpu_tran_ext;
cpu_gen.run_for_n_trans = 100;
cpu_gen.start();
cpu_drv.start();
@cpu_gen.done;
repeat(100) @(cpu_intf.cb);
$finish();
end
initial begin
cpu_transaction cpu_tran = new();
forever begin
mon_mbox.get(cpu_tran);
cpu_tran.display("Monitor Mbox");
end
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/monitor
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/monitor
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
103) scoreboard
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
if(cpu_tran.rw == 1'b1) begin
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
end
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_scoreboard.sv
/////////////////////////////////////////////
`ifndef __CPU_SCOREBOARD_SV__
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_scoreboard;
string name;
cpu_tran_mbox in_box;
cpu_transaction cpu_tran;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
extern function new(string name = "CPU Scoreboard", cpu_tran_mbox in_box);
extern task start();
extern task check();
extern function display(string prefix = "CPU Scoreboard Result");
endclass
function cpu_scoreboard::new(string name, cpu_tran_mbox in_box);
this.name = name;
this.in_box = in_box;
for(int i=0; i<128; i++) begin
cpu_reg[i] = 32'h0;
end
endfunction
task cpu_scoreboard::start();
fork
forever begin
in_box.get(cpu_tran);
total_no++;
check();
end
join_none
endtask
task cpu_scoreboard::check();
string message;
if(cpu_tran.rw == 1'b0) begin
cpu_reg[cpu_tran.addr] = cpu_tran.din;
end
else if(cpu_tran.rw == 1'b1) begin
if(cpu_reg[cpu_tran.addr] != cpu_tran.dout) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, cpu_tran.dout = %0h\n", cpu_tran.addr, cpu_reg[cpu_tran.addr], cpu_tran.dout) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] cpu_tran.rw can only be 0 or 1");
error_no++;
end
endtask
function cpu_scoreboard::display(string prefix);
$display("Total: %d, Error: %d", total_no, error_no);
endfunction
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
`include "cpu_scoreboard.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
event done;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_transaction_ext cpu_tran_ext = new();
cpu_scoreboard cpu_sb;
initial begin
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
cpu_sb = new("CPU Scoreboard", mon_mbox);
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
cpu_gen.cpu_tran = cpu_tran_ext;
cpu_gen.run_for_n_trans = 100;
cpu_gen.start();
cpu_drv.start();
cpu_sb.start();
@cpu_gen.done;
repeat(1000) begin
@(cpu_intf.cb);
if(cpu_sb.total_no == cpu_gen.run_for_n_trans) begin
break;
end
end
cpu_sb.display();
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/scoreboard
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/scoreboard
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
104) env
/////////////////////////////////////////////
//dut.v
/////////////////////////////////////////////
`timescale 1ns/1ps
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
dout
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
output [31:0] dout ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
reg [31:0] dout ;
wire write ;
wire read ;
reg [31:0] config_reg ;
reg [31:0] max_pkt_size ;
assign write = (rw == 1'b0);
assign read = (rw == 1'b1);
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
config_reg <= 32'h0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
config_reg <= din;
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'h0;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
max_pkt_size <= din;
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
endmodule
/////////////////////////////////////////////
//cpu_interface.svi
/////////////////////////////////////////////
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk);
logic rst_n ;
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output din ;
output rw ;
input dout ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
/////////////////////////////////////////////
//cpu_transaction.sv
/////////////////////////////////////////////
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction;
string name;
rand logic [7:0] addr;
rand logic rw;
rand logic [31:0] din;
logic [31:0] dout = 32'h0;
extern function new(string name = "CPU Transaction");
extern function void display(string prefix = "Note");
endclass
function cpu_transaction::new(string name);
this.name = name;
endfunction
function void cpu_transaction::display(string prefix);
$display("[%s]%t %s addr = %0h, din = %0h, rw = %d, dout = %0h", prefix, $realtime, name, addr, din, rw, dout);
endfunction
`endif
/////////////////////////////////////////////
//cpu_define.sv
/////////////////////////////////////////////
`ifndef __CPU_DEFINE_SV__
`define __CPU_DEFINE_SV__
typedef class cpu_transaction;
typedef mailbox #(cpu_transaction) cpu_tran_mbox;
`endif
/////////////////////////////////////////////
//cpu_generator.sv
/////////////////////////////////////////////
`ifndef __CPU_GENERATOR_SV__
`define __CPU_GENERATOR_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_generator;
string name;
cpu_tran_mbox out_box;
int run_for_n_trans = 0;
cpu_transaction cpu_tran;
event done;
extern function new(string name = "CPU Generator", cpu_tran_mbox out_box);
extern task start();
endclass
function cpu_generator::new(string name, cpu_tran_mbox out_box);
this.name = name;
this.out_box = out_box;
endfunction
task cpu_generator::start();
fork
begin
for(int i=0; i<run_for_n_trans; i++) begin
cpu_transaction cpu_tran_cpy = new cpu_tran;
if(!cpu_tran_cpy.randomize()) begin
$display("Error to randomize cpu_tran_cpy");
end
out_box.put(cpu_tran_cpy);
end
->done;
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_driver.sv
/////////////////////////////////////////////
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
`include "cpu_interface.svi"
class cpu_driver;
string name;
cpu_tran_mbox in_box;
cpu_tran_mbox out_box;
virtual cpu_interface.master cpu_intf;
extern function new(string name = "CPU Driver", cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
extern task start();
endclass
function cpu_driver::new(string name, cpu_tran_mbox in_box, cpu_tran_mbox out_box, virtual cpu_interface.master cpu_intf);
this.name = name;
this.in_box = in_box;
this.out_box = out_box;
this.cpu_intf = cpu_intf;
endfunction
task cpu_driver::start();
fork
forever begin
cpu_transaction cpu_tran;
in_box.get(cpu_tran);
cpu_tran.display();
@(cpu_intf.cb);
cpu_intf.cb.addr <= cpu_tran.addr;
cpu_intf.cb.din <= cpu_tran.din;
cpu_intf.cb.rw <= cpu_tran.rw;
if(cpu_tran.rw == 1'b1) begin
@(cpu_intf.cb);
cpu_tran.dout = cpu_intf.cb.dout;
end
out_box.put(cpu_tran);
end
join_none
endtask
`endif
/////////////////////////////////////////////
//cpu_scoreboard.sv
/////////////////////////////////////////////
`ifndef __CPU_SCOREBOARD_SV__
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
`include "cpu_define.sv"
class cpu_scoreboard;
string name;
cpu_tran_mbox in_box;
cpu_transaction cpu_tran;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
extern function new(string name = "CPU Scoreboard", cpu_tran_mbox in_box);
extern task start();
extern task check();
extern function display(string prefix = "CPU Scoreboard Result");
endclass
function cpu_scoreboard::new(string name, cpu_tran_mbox in_box);
this.name = name;
this.in_box = in_box;
for(int i=0; i<128; i++) begin
cpu_reg[i] = 32'h0;
end
endfunction
task cpu_scoreboard::start();
fork
forever begin
in_box.get(cpu_tran);
total_no++;
check();
end
join_none
endtask
task cpu_scoreboard::check();
string message;
if(cpu_tran.rw == 1'b0) begin
cpu_reg[cpu_tran.addr] = cpu_tran.din;
end
else if(cpu_tran.rw == 1'b1) begin
if(cpu_reg[cpu_tran.addr] != cpu_tran.dout) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, cpu_tran.dout = %0h\n", cpu_tran.addr, cpu_reg[cpu_tran.addr], cpu_tran.dout) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] cpu_tran.rw can only be 0 or 1");
error_no++;
end
endtask
function cpu_scoreboard::display(string prefix);
$display("Total: %d, Error: %d", total_no, error_no);
endfunction
`endif
/////////////////////////////////////////////
//cpu_env.sv
/////////////////////////////////////////////
`ifndef __CPU_ENV_SV__
`define __CPU_ENV_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_generator.sv"
`include "cpu_define.sv"
`include "cpu_driver.sv"
`include "cpu_scoreboard.sv"
class cpu_env;
cpu_tran_mbox drv_mbox = new();
cpu_tran_mbox mon_mbox = new();
cpu_generator cpu_gen;
cpu_driver cpu_drv;
cpu_scoreboard cpu_sb;
virtual cpu_interface.master cpu_intf;
extern function new(virtual cpu_interface.master cpu_intf);
extern function configure();
extern task reset();
extern task start();
endclass
function cpu_env::new(virtual cpu_interface.master cpu_intf);
this.cpu_intf = cpu_intf;
cpu_gen = new("CPU Generator", drv_mbox);
cpu_drv = new("CPU Driver", drv_mbox, mon_mbox, cpu_intf);
cpu_sb = new("CPU Scoreboard", mon_mbox);
endfunction
function cpu_env::configure();
endfunction
task cpu_env::reset();
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b0;
@(cpu_intf.cb);
cpu_intf.rst_n = 1'b1;
@(cpu_intf.cb);
endtask
task cpu_env::start();
cpu_gen.start();
cpu_drv.start();
cpu_sb.start();
endtask
`endif
/////////////////////////////////////////////
//test.sv
/////////////////////////////////////////////
`ifndef __TEST_SV__
`define __TEST_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
`include "cpu_env.sv"
program test(cpu_interface.master cpu_intf);
class cpu_transaction_ext extends cpu_transaction;
constraint addr_range {addr[7:2] inside {[8'h0:8'h1]}; addr[1:0] == 2'h0;}
//constraint write {rw == 1'b0;}
endclass
cpu_transaction_ext cpu_tran_ext = new();
cpu_env cpu_e;
initial begin
cpu_e = new(cpu_intf);
cpu_e.configure();
cpu_e.cpu_gen.cpu_tran = cpu_tran_ext;
cpu_e.cpu_gen.run_for_n_trans = 100;
cpu_e.reset();
cpu_e.start();
@cpu_e.cpu_gen.done;
repeat(1000) begin
@(cpu_intf.cb);
if(cpu_e.cpu_sb.total_no == cpu_e.cpu_gen.run_for_n_trans) begin
break;
end
end
cpu_e.cpu_sb.display();
$finish();
end
endprogram
`endif
/////////////////////////////////////////////
//top.sv
/////////////////////////////////////////////
`timescale 1ns/1ps
`include "cpu_interface.svi"
`include "test.sv"
module top;
parameter cpu_clock_cycle = 10;
logic clk;
cpu_interface cpu_intf(clk);
test u_test(cpu_intf);
dut u_dut (
.clk (cpu_intf.clk ) ,
.rst_n (cpu_intf.rst_n ) ,
.addr (cpu_intf.addr ) ,
.din (cpu_intf.din ) ,
.rw (cpu_intf.rw ) ,
.dout (cpu_intf.dout )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(cpu_clock_cycle/2) clk = ~clk;
end
end
`ifdef WAVE_ON
initial begin
$vcdpluson();
end
`endif
endmodule
#############################################
#Makefile
#############################################
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
RTL_DIR = /mnt/env
RTL = $(RTL_DIR)/dut.v
TB_DIR = /mnt/env
SVTB = $(TB_DIR)/top.sv
INCDIR = +incdir+$(TB_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
COMPILE_ARG = -sverilog -debug_all
COMPILE_ARG += $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
RUN_ARG =
RUN_ARG += $(RUN_LOG_ARG) $(GUI_ARG)
SEED = 1
default: test
test: compile run
run:
./simv $(RUN_ARG) +ntb_random_seed=$(SEED)
compile:
vcs $(COMPILE_ARG) $(SVTB) $(RTL)
clean:
rm -rf simv simv.* *log
110) driver and monitor are in 2 different class (bfm)
link: http://scott2595.blogspot.com/2014/08/an-example-of-systemverilog-tb.html
111) TB env with 2 TB envs
linke: http://scott2595.blogspot.com/2014/10/an-example-of-sv-tb-with-callback.html
some basic VHDL syntax
1) entity
library ieee;
use ieee.std_logic_1164.all;
entity dataProcess is
port (
din : in std_logic_vector(7 downto 0);
dout : out std_logic_vector(7 downto 0);
dio : inout std_logic
);
end entity dataProcess;
architecture behavioral of dataProcess is
begin
end behavioral;
2) combinational logic
library ieee;
use ieee.std_logic_1164.all;
entity clkGen is
port (
clk : in std_logic;
mode : in std_logic;
sclk : out std_logic
);
end entity clkGen;
architecture behavioral of clkGen is
signal clk_en : std_logic;
begin
--generate sclk
sclk <= clk when clk_en = '1' else '0';
process(mode)
begin
case mode is
when '0' =>
clk_en <= '0';
when '1' =>
clk_en <= '1';
when others =>
clk_en <= '0';
end case;
end process;
end behavioral;
3) timing logic
library ieee;
use ieee.std_logic_1164.all;
entity dff_1 is
port (
clk : in std_logic;
rst_n : in std_logic;
din : in std_logic;
dout : out std_logic
);
end entity dff_1;
architecture behavioral of dff_1 is
begin
process(clk, rst_n)
begin
if(rst_n = '0') then
dout <= '0';
elsif(clk'event and clk = '1') then
-- elsif(rising_edge(clk)) then
dout <= din;
end if;
end process;
end behavioral;
4) tristate gate
library ieee;
use ieee.std_logic_1164.all;
entity dataProcess is
port (
sclk : in std_logic;
rst_n : in std_logic;
rw : in std_logic;
sdio : inout std_logic
);
end entity dataProcess;
architecture behavioral of dataProcess is
signal sdi : std_logic;
signal sdo : std_logic;
signal sdo_en : std_logic;
signal data : std_logic_vector(7 downto 0);
begin
--generate sdio
sdio <= sdo when sdo_en = '1' else 'Z';
sdi <= sdio;
process(sclk, rst_n)
begin
if(rst_n = '0') then
data <= (others => '0');
elsif(rising_edge(sclk)) then
if(rw = '0') then
data <= data(6 downto 0) & sdi;
else
data <= data(6 downto 0) & '0';
end if;
end if;
end process;
process(sclk, rst_n)
begin
if(rst_n = '0') then
sdo <= '0';
sdo_en <= '0';
elsif(rising_edge(sclk)) then
if(rw = '1') then
sdo <= data(7);
sdo_en <= '1';
else
sdo <= '0';
sdo_en <= '0';
end if;
end if;
end process;
end behavioral;
5) package with function
use ieee.std_logic_1164.all;
package user_pkg is
function to_stdulogic(V: Boolean) return std_ulogic;
end;
package body user_pkg is
--function to convert boolean to std_logic
function to_stdulogic(V: Boolean) return std_ulogic is
begin
if V then
return '1';
else
return '0';
end if;
end to_stdulogic;
end behavioral;
6) package with procedure
-------------------------------------------------------
-- package user_pkg
use ieee.std_logic_1164.all;
package user_pkg is
procedure segment_dec (signal bcd: in std_logic_vector(3 downto 0); signal segment : out std_logic_vector(6 downto 0));
end;
package body user_pkg is
procedure segment_dec (
signal bcd: in std_logic_vector(3 downto 0);
signal segment : out std_logic_vector(6 downto 0)
) is
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"1000000";
when x"1" => segment <= b"1111001";
when x"2" => segment <= b"0100100";
when x"3" => segment <= b"0110000";
when x"4" => segment <= b"0011001";
when x"5" => segment <= b"0010010";
when x"6" => segment <= b"0000010";
when x"7" => segment <= b"1111000";
when x"8" => segment <= b"0000000";
when x"9" => segment <= b"0010000";
when others => segment <= b"1000000";
end case;
end procedure segment_dec;
library ieee;
use ieee.std_logic_1164.all;
entity dataProcess is
port (
din : in std_logic_vector(7 downto 0);
dout : out std_logic_vector(7 downto 0);
dio : inout std_logic
);
end entity dataProcess;
architecture behavioral of dataProcess is
begin
end behavioral;
2) combinational logic
library ieee;
use ieee.std_logic_1164.all;
entity clkGen is
port (
clk : in std_logic;
mode : in std_logic;
sclk : out std_logic
);
end entity clkGen;
architecture behavioral of clkGen is
signal clk_en : std_logic;
begin
--generate sclk
sclk <= clk when clk_en = '1' else '0';
process(mode)
begin
case mode is
when '0' =>
clk_en <= '0';
when '1' =>
clk_en <= '1';
when others =>
clk_en <= '0';
end case;
end process;
end behavioral;
3) timing logic
library ieee;
use ieee.std_logic_1164.all;
entity dff_1 is
port (
clk : in std_logic;
rst_n : in std_logic;
din : in std_logic;
dout : out std_logic
);
end entity dff_1;
architecture behavioral of dff_1 is
begin
process(clk, rst_n)
begin
if(rst_n = '0') then
dout <= '0';
elsif(clk'event and clk = '1') then
-- elsif(rising_edge(clk)) then
dout <= din;
end if;
end process;
end behavioral;
4) tristate gate
library ieee;
use ieee.std_logic_1164.all;
entity dataProcess is
port (
sclk : in std_logic;
rst_n : in std_logic;
rw : in std_logic;
sdio : inout std_logic
);
end entity dataProcess;
architecture behavioral of dataProcess is
signal sdi : std_logic;
signal sdo : std_logic;
signal sdo_en : std_logic;
signal data : std_logic_vector(7 downto 0);
begin
--generate sdio
sdio <= sdo when sdo_en = '1' else 'Z';
sdi <= sdio;
process(sclk, rst_n)
begin
if(rst_n = '0') then
data <= (others => '0');
elsif(rising_edge(sclk)) then
if(rw = '0') then
data <= data(6 downto 0) & sdi;
else
data <= data(6 downto 0) & '0';
end if;
end if;
end process;
process(sclk, rst_n)
begin
if(rst_n = '0') then
sdo <= '0';
sdo_en <= '0';
elsif(rising_edge(sclk)) then
if(rw = '1') then
sdo <= data(7);
sdo_en <= '1';
else
sdo <= '0';
sdo_en <= '0';
end if;
end if;
end process;
end behavioral;
5) package with function
-------------------------------------------------------
-- package user_pkg
-------------------------------------------------------
library ieee;use ieee.std_logic_1164.all;
package user_pkg is
function to_stdulogic(V: Boolean) return std_ulogic;
end;
package body user_pkg is
--function to convert boolean to std_logic
function to_stdulogic(V: Boolean) return std_ulogic is
begin
if V then
return '1';
else
return '0';
end if;
end to_stdulogic;
end package body;
-------------------------------------------------------
-- entity calling package
-------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.user_pkg.all;
entity test_package is
port (
clk : in std_logic;
rst_n : in std_logic;
mode : in std_logic;
mode_trig : out std_logic
);
end entity test_package;
architecture behavioral of test_package is
--signal declaration in architecture
signal mode_ff1 : std_logic;
signal mode_ff2 : std_logic;
signal mode_ff3 : std_logic;
--begin of architecture
begin
process(clk, rst_n)
begin
if(rst_n = '0') then
mode_ff1 <= '0';
mode_ff2 <= '0';
mode_ff3 <= '0';
elsif(clk'event and clk = '1') then
mode_ff1 <= mode;
mode_ff2 <= mode_ff1;
mode_ff3 <= mode_ff2;
end if;
end process;
mode_trig <= to_stdulogic((mode_ff2 = '0') and (mode_ff3 = '1'));
end behavioral;
6) package with procedure
-------------------------------------------------------
-- package user_pkg
-------------------------------------------------------
library ieee;use ieee.std_logic_1164.all;
package user_pkg is
procedure segment_dec (signal bcd: in std_logic_vector(3 downto 0); signal segment : out std_logic_vector(6 downto 0));
end;
package body user_pkg is
procedure segment_dec (
signal bcd: in std_logic_vector(3 downto 0);
signal segment : out std_logic_vector(6 downto 0)
) is
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"1000000";
when x"1" => segment <= b"1111001";
when x"2" => segment <= b"0100100";
when x"3" => segment <= b"0110000";
when x"4" => segment <= b"0011001";
when x"5" => segment <= b"0010010";
when x"6" => segment <= b"0000010";
when x"7" => segment <= b"1111000";
when x"8" => segment <= b"0000000";
when x"9" => segment <= b"0010000";
when others => segment <= b"1000000";
end case;
end procedure segment_dec;
end package body;
-------------------------------------------------------
-- entity calling package
-------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.user_pkg.all;
entity bcd2segment is
port (
bcd : in std_logic_vector(3 downto 0);
segment : out std_logic_vector(6 downto 0)
);
end entity bcd2segment;
architecture behavioral of bcd2segment is
begin
process(bcd)
begin
segment_dec(bcd, segment);
end process;
end behavioral;
7) generic
-----------------------------------------------------------------
--clk dividor
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity clk_div is
generic (
N: integer := 12499999
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity clk_div;
architecture behavioral of clk_div is
signal clk_cnt : integer range 0 to N;
signal clk_out_tmp : std_logic;
begin
--counter for half second
process(clk, rst_n)
begin
if(rst_n = '0')then
clk_cnt <= 0;
clk_out_tmp <= '0';
elsif(clk'event and clk = '1') then
--when counter reaches to half second,
--need to reset the counter to 0
if(clk_cnt = N) then
clk_cnt <= 0;
clk_out_tmp <= not (clk_out_tmp);
else
clk_cnt <= clk_cnt + 1;
clk_out_tmp <= clk_out_tmp;
end if;
end if;
end process;
clk_out <= clk_out_tmp;
end behavioral;
-----------------------------------------------------------------
--top
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity top is
generic (
N: integer := 20
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity top;
architecture behavioral of top is
component clk_div is
generic (
N: integer := 12499999
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end component;
--begin of architecture
begin
--instance clock dividor
u_clk_div: clk_div generic map (
N => N
) PORT MAP (
clk => clk ,
rst_n => rst_n ,
clk_out => clk_out
);
end behavioral;
--end of architecture
8) instance component
-----------------------------------------------------------------
--clk dividor
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity clk_div is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity clk_div;
architecture behavioral of clk_div is
signal clk_out_tmp : std_logic;
begin
--counter for half second
process(clk, rst_n)
begin
if(rst_n = '0')then
clk_out_tmp <= '0';
elsif(clk'event and clk = '1') then
clk_out_tmp <= not clk_out_tmp;
end if;
end process;
clk_out <= clk_out_tmp;
end behavioral;
-----------------------------------------------------------------
--top
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity top is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity top;
architecture behavioral of top is
component clk_div is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end component;
--begin of architecture
begin
--instance clock dividor
u_clk_div: clk_div PORT MAP (
clk => clk ,
rst_n => rst_n ,
clk_out => clk_out
);
end behavioral;
9) generate
library ieee;
use ieee.std_logic_1164.all;
entity bcd2segment is
generic (
M: integer := 7
);
port (
bcd : in std_logic_vector(3 downto 0);
segment : out std_logic_vector(M-1 downto 0)
);
end entity bcd2segment;
architecture behavioral of bcd2segment is
begin
SEGMENT_WITHOUT_DP: if M=7 generate
process(bcd)
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"1111111";
when x"1" => segment <= b"1111001";
when x"2" => segment <= b"0100100";
when x"3" => segment <= b"0110000";
when x"4" => segment <= b"0011001";
when x"5" => segment <= b"0010010";
when x"6" => segment <= b"0000010";
when x"7" => segment <= b"1111000";
when x"8" => segment <= b"0000000";
when x"9" => segment <= b"0010000";
--when in selector 1, counter should add 1 after each half second
--for other unknown selectors, set counter to 0
when others => segment <= b"1111111";
end case;
end process;
end generate SEGMENT_WITHOUT_DP;
SEGMENT_WITH_DP: if M=8 generate
process(bcd)
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"11111111";
when x"1" => segment <= b"11111001";
when x"2" => segment <= b"10100100";
when x"3" => segment <= b"10110000";
when x"4" => segment <= b"10011001";
when x"5" => segment <= b"10010010";
when x"6" => segment <= b"10000010";
when x"7" => segment <= b"11111000";
when x"8" => segment <= b"10000000";
when x"9" => segment <= b"10010000";
--when in selector 1, counter should add 1 after each half second
--for other unknown selectors, set counter to 0
when others => segment <= b"11111111";
end case;
end process;
end generate SEGMENT_WITH_DP;
end behavioral;
31) testbench
-----------------------------------------------------------------
--DUT
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package user_pkg is
procedure new_logic (signal A, B, CIN: in std_logic; signal S, COUT : out std_logic);
end package;
package body user_pkg is
procedure new_logic (
signal A, B, CIN: in std_logic;
signal S, COUT : out std_logic
) is
begin
S <= (A xor B) xor CIN;
COUT <= (A and B) or ((A xor B) and CIN);
end procedure new_logic;
end package body;
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.user_pkg.all;
entity adder is
port (
clk : in std_logic ;
rst_n : in std_logic ;
enable : in std_logic ;
a : in std_logic_vector(3 downto 0) ;
b : in std_logic_vector(3 downto 0) ;
s : out std_logic_vector(3 downto 0) ;
cout : out std_logic
);
end entity adder;
architecture behavioral of adder is
signal c : std_logic_vector(3 downto 0);
signal s_tmp : std_logic_vector(3 downto 0);
signal cout_tmp : std_logic;
begin
c(0) <= '0';
process(a, b, c)
begin
new_logic(a(0), b(0), c(0), s_tmp(0), c(1));
new_logic(a(1), b(1), c(1), s_tmp(1), c(2));
new_logic(a(2), b(2), c(2), s_tmp(2), c(3));
new_logic(a(3), b(3), c(3), s_tmp(3), cout_tmp);
end process;
process(clk, rst_n)
begin
if(rst_n = '0') then
s <= x"0";
cout <= '0';
elsif(clk'event and clk = '0') then
if(enable = '1') then
s <= s_tmp;
cout <= cout_tmp;
end if;
end if;
end process;
end behavioral;
-----------------------------------------------------------------
--tb
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.env.all;
entity tb_adder is
end entity tb_adder;
architecture behavioral of tb_adder is
component adder is
port (
clk : in std_logic ;
rst_n : in std_logic ;
enable : in std_logic ;
a : in std_logic_vector(3 downto 0) ;
b : in std_logic_vector(3 downto 0) ;
s : out std_logic_vector(3 downto 0) ;
cout : out std_logic
);
end component;
signal clk : std_logic ;
signal rst_n : std_logic ;
signal enable : std_logic ;
signal a : std_logic_vector(3 downto 0) ;
signal b : std_logic_vector(3 downto 0) ;
signal s : std_logic_vector(3 downto 0) ;
signal cout : std_logic ;
begin
u_adder: adder port map (
clk => clk ,
rst_n => rst_n ,
enable => enable ,
a => a ,
b => b ,
s => s ,
cout => cout
);
process
begin
clk <= '0';
wait for 6.67 ns;
clk <= '1';
wait for 6.67 ns;
end process;
process
variable i, j, k: integer;
begin
rst_n <= '0';
wait for 600 ns;
rst_n <= '1';
wait;
end process;
process
variable i, j, k: integer;
begin
enable <= '0';
a <= x"0";
b <= x"0";
wait until rst_n'event and rst_n = '1';
wait until clk'event and clk = '0';
for i in 0 to 15 loop
for j in 0 to 15 loop
wait until clk'event and clk = '0';
a <= std_logic_vector(to_unsigned(i, a'length));
b <= std_logic_vector(to_unsigned(j, b'length));
enable <= '0';
wait until clk'event and clk = '0';
enable <= '1';
end loop;
end loop;
wait for 100 ns;
finish(0);
end process;
end behavioral;
use ieee.std_logic_1164.all;
use work.user_pkg.all;
entity bcd2segment is
port (
bcd : in std_logic_vector(3 downto 0);
segment : out std_logic_vector(6 downto 0)
);
end entity bcd2segment;
architecture behavioral of bcd2segment is
begin
process(bcd)
begin
segment_dec(bcd, segment);
end process;
end behavioral;
7) generic
-----------------------------------------------------------------
--clk dividor
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity clk_div is
generic (
N: integer := 12499999
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity clk_div;
architecture behavioral of clk_div is
signal clk_cnt : integer range 0 to N;
signal clk_out_tmp : std_logic;
begin
--counter for half second
process(clk, rst_n)
begin
if(rst_n = '0')then
clk_cnt <= 0;
clk_out_tmp <= '0';
elsif(clk'event and clk = '1') then
--when counter reaches to half second,
--need to reset the counter to 0
if(clk_cnt = N) then
clk_cnt <= 0;
clk_out_tmp <= not (clk_out_tmp);
else
clk_cnt <= clk_cnt + 1;
clk_out_tmp <= clk_out_tmp;
end if;
end if;
end process;
clk_out <= clk_out_tmp;
end behavioral;
-----------------------------------------------------------------
--top
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity top is
generic (
N: integer := 20
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity top;
architecture behavioral of top is
component clk_div is
generic (
N: integer := 12499999
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end component;
--begin of architecture
begin
--instance clock dividor
u_clk_div: clk_div generic map (
N => N
) PORT MAP (
clk => clk ,
rst_n => rst_n ,
clk_out => clk_out
);
end behavioral;
--end of architecture
8) instance component
-----------------------------------------------------------------
--clk dividor
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity clk_div is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity clk_div;
architecture behavioral of clk_div is
signal clk_out_tmp : std_logic;
begin
--counter for half second
process(clk, rst_n)
begin
if(rst_n = '0')then
clk_out_tmp <= '0';
elsif(clk'event and clk = '1') then
clk_out_tmp <= not clk_out_tmp;
end if;
end process;
clk_out <= clk_out_tmp;
end behavioral;
-----------------------------------------------------------------
--top
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity top is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end entity top;
architecture behavioral of top is
component clk_div is
port (
clk : in std_logic;
rst_n : in std_logic;
clk_out : out std_logic
);
end component;
--begin of architecture
begin
--instance clock dividor
u_clk_div: clk_div PORT MAP (
clk => clk ,
rst_n => rst_n ,
clk_out => clk_out
);
end behavioral;
9) generate
library ieee;
use ieee.std_logic_1164.all;
entity bcd2segment is
generic (
M: integer := 7
);
port (
bcd : in std_logic_vector(3 downto 0);
segment : out std_logic_vector(M-1 downto 0)
);
end entity bcd2segment;
architecture behavioral of bcd2segment is
begin
SEGMENT_WITHOUT_DP: if M=7 generate
process(bcd)
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"1111111";
when x"1" => segment <= b"1111001";
when x"2" => segment <= b"0100100";
when x"3" => segment <= b"0110000";
when x"4" => segment <= b"0011001";
when x"5" => segment <= b"0010010";
when x"6" => segment <= b"0000010";
when x"7" => segment <= b"1111000";
when x"8" => segment <= b"0000000";
when x"9" => segment <= b"0010000";
--when in selector 1, counter should add 1 after each half second
--for other unknown selectors, set counter to 0
when others => segment <= b"1111111";
end case;
end process;
end generate SEGMENT_WITHOUT_DP;
SEGMENT_WITH_DP: if M=8 generate
process(bcd)
begin
case bcd is
--decode from bcd to segment
when x"0" => segment <= b"11111111";
when x"1" => segment <= b"11111001";
when x"2" => segment <= b"10100100";
when x"3" => segment <= b"10110000";
when x"4" => segment <= b"10011001";
when x"5" => segment <= b"10010010";
when x"6" => segment <= b"10000010";
when x"7" => segment <= b"11111000";
when x"8" => segment <= b"10000000";
when x"9" => segment <= b"10010000";
--when in selector 1, counter should add 1 after each half second
--for other unknown selectors, set counter to 0
when others => segment <= b"11111111";
end case;
end process;
end generate SEGMENT_WITH_DP;
end behavioral;
31) testbench
-----------------------------------------------------------------
--DUT
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package user_pkg is
procedure new_logic (signal A, B, CIN: in std_logic; signal S, COUT : out std_logic);
end package;
package body user_pkg is
procedure new_logic (
signal A, B, CIN: in std_logic;
signal S, COUT : out std_logic
) is
begin
S <= (A xor B) xor CIN;
COUT <= (A and B) or ((A xor B) and CIN);
end procedure new_logic;
end package body;
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.user_pkg.all;
entity adder is
port (
clk : in std_logic ;
rst_n : in std_logic ;
enable : in std_logic ;
a : in std_logic_vector(3 downto 0) ;
b : in std_logic_vector(3 downto 0) ;
s : out std_logic_vector(3 downto 0) ;
cout : out std_logic
);
end entity adder;
architecture behavioral of adder is
signal c : std_logic_vector(3 downto 0);
signal s_tmp : std_logic_vector(3 downto 0);
signal cout_tmp : std_logic;
begin
c(0) <= '0';
process(a, b, c)
begin
new_logic(a(0), b(0), c(0), s_tmp(0), c(1));
new_logic(a(1), b(1), c(1), s_tmp(1), c(2));
new_logic(a(2), b(2), c(2), s_tmp(2), c(3));
new_logic(a(3), b(3), c(3), s_tmp(3), cout_tmp);
end process;
process(clk, rst_n)
begin
if(rst_n = '0') then
s <= x"0";
cout <= '0';
elsif(clk'event and clk = '0') then
if(enable = '1') then
s <= s_tmp;
cout <= cout_tmp;
end if;
end if;
end process;
end behavioral;
-----------------------------------------------------------------
--tb
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.env.all;
entity tb_adder is
end entity tb_adder;
architecture behavioral of tb_adder is
component adder is
port (
clk : in std_logic ;
rst_n : in std_logic ;
enable : in std_logic ;
a : in std_logic_vector(3 downto 0) ;
b : in std_logic_vector(3 downto 0) ;
s : out std_logic_vector(3 downto 0) ;
cout : out std_logic
);
end component;
signal clk : std_logic ;
signal rst_n : std_logic ;
signal enable : std_logic ;
signal a : std_logic_vector(3 downto 0) ;
signal b : std_logic_vector(3 downto 0) ;
signal s : std_logic_vector(3 downto 0) ;
signal cout : std_logic ;
begin
u_adder: adder port map (
clk => clk ,
rst_n => rst_n ,
enable => enable ,
a => a ,
b => b ,
s => s ,
cout => cout
);
process
begin
clk <= '0';
wait for 6.67 ns;
clk <= '1';
wait for 6.67 ns;
end process;
process
variable i, j, k: integer;
begin
rst_n <= '0';
wait for 600 ns;
rst_n <= '1';
wait;
end process;
process
variable i, j, k: integer;
begin
enable <= '0';
a <= x"0";
b <= x"0";
wait until rst_n'event and rst_n = '1';
wait until clk'event and clk = '0';
for i in 0 to 15 loop
for j in 0 to 15 loop
wait until clk'event and clk = '0';
a <= std_logic_vector(to_unsigned(i, a'length));
b <= std_logic_vector(to_unsigned(j, b'length));
enable <= '0';
wait until clk'event and clk = '0';
enable <= '1';
end loop;
end loop;
wait for 100 ns;
finish(0);
end process;
end behavioral;
some basic verilog syntax
1) module
module dataProcess (
din ,
dout ,
dio
);
input din ;
output dout ;
inout dio ;
wire din ;
wire dout ;
// reg dout ;
wire dio ;
endmodule
2) combinational logic
input clk ;
input mode ;
output sclk ;
wire clk ;
wire mode ;
wire sclk ;
reg clk_en;
// generate sclk
assign sclk = (clk_en == 1'b1) ? clk : 1'b0;
always @(mode)
//verilog 2000
//always @(*)
begin
case (mode)
0 : begin
clk_en = 1'b0;
end
1 : begin
clk_en = 1'b1;
end
default : begin
clk_en = 1'b0;
end
endcase
end
endmodule
3) timing logic
module dff_1 (
clk ,
rst_n ,
din ,
dout
);
input clk ;
input rst_n ;
input din ;
output dout ;
wire clk ;
wire rst_n ;
wire din ;
reg dout ;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
dout <= 1'b0;
else
dout <= din;
end
endmodule
4) tristate gate
module dataProcess (
sclk ,
rst_n ,
rw ,
sdio
);
input sclk ;
input rst_n ;
input rw ;
inout sdio ;
wire sclk ;
wire rst_n ;
wire rw ;
wire sdio ;
wire sdi ;
reg sdo ;
reg sdo_en ;
reg [7:0] data ;
//generate sdio
assign sdio = (sdo_en == 1'b1) ? sdo : 1'bz;
assign sdi = sdio;
always @(posedge sclk or negedge rst_n) begin
if(rst_n == 1'b0)
data <= 'h0;
else begin
if(rw == 1'b0)
data <= {data[6:0], sdi};
else
data <= {data[6:0], 1'b0};
end
end
always @(posedge sclk or negedge rst_n) begin
if(rst_n == 1'b0) begin
sdo <= 1'b0;
sdo_en <= 1'b0;
end
else begin
if(rw == 1'b1) begin
sdo <= data[7];
sdo_en <= 1'b1;
end
else begin
sdo <= 1'b0;
sdo_en <= 1'b0;
end
end
end
endmodule
5) module calling function
module dataProcess (
din ,
dout ,
dio
);
input din ;
output dout ;
inout dio ;
wire din ;
wire dout ;
// reg dout ;
wire dio ;
endmodule
2) combinational logic
input clk ;
input mode ;
output sclk ;
wire clk ;
wire mode ;
wire sclk ;
reg clk_en;
// generate sclk
assign sclk = (clk_en == 1'b1) ? clk : 1'b0;
always @(mode)
//verilog 2000
//always @(*)
begin
case (mode)
0 : begin
clk_en = 1'b0;
end
1 : begin
clk_en = 1'b1;
end
default : begin
clk_en = 1'b0;
end
endcase
end
endmodule
3) timing logic
module dff_1 (
clk ,
rst_n ,
din ,
dout
);
input clk ;
input rst_n ;
input din ;
output dout ;
wire clk ;
wire rst_n ;
wire din ;
reg dout ;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
dout <= 1'b0;
else
dout <= din;
end
endmodule
4) tristate gate
module dataProcess (
sclk ,
rst_n ,
rw ,
sdio
);
input sclk ;
input rst_n ;
input rw ;
inout sdio ;
wire sclk ;
wire rst_n ;
wire rw ;
wire sdio ;
wire sdi ;
reg sdo ;
reg sdo_en ;
reg [7:0] data ;
//generate sdio
assign sdio = (sdo_en == 1'b1) ? sdo : 1'bz;
assign sdi = sdio;
always @(posedge sclk or negedge rst_n) begin
if(rst_n == 1'b0)
data <= 'h0;
else begin
if(rw == 1'b0)
data <= {data[6:0], sdi};
else
data <= {data[6:0], 1'b0};
end
end
always @(posedge sclk or negedge rst_n) begin
if(rst_n == 1'b0) begin
sdo <= 1'b0;
sdo_en <= 1'b0;
end
else begin
if(rw == 1'b1) begin
sdo <= data[7];
sdo_en <= 1'b1;
end
else begin
sdo <= 1'b0;
sdo_en <= 1'b0;
end
end
end
endmodule
5) module calling function
///////////////////////////////////////////////////////
// module user_pkg contains the function
///////////////////////////////////////////////////////
module user_pkg;
function [31:0] factorial;
input [3:0] operand;
reg [3:0] index ;
begin
factorial = operand ? 1 : 0;
for(index = 2; index <= operand; index = index + 1)
factorial = index * factorial;
end
endfunction
endmodule
///////////////////////////////////////////////////////
// module calling package
///////////////////////////////////////////////////////
module test_package (
n ,
result
);
input [3:0 ] n ;
output [31:0] result ;
wire [3:0 ] n ;
reg [31:0] result ;
always @(n) begin
result = n * user_pkg.factorial(n) / ((n * 2) + 1);
end
endmodule
// module user_pkg contains the function
///////////////////////////////////////////////////////
module user_pkg;
function [31:0] factorial;
input [3:0] operand;
reg [3:0] index ;
begin
factorial = operand ? 1 : 0;
for(index = 2; index <= operand; index = index + 1)
factorial = index * factorial;
end
endfunction
endmodule
///////////////////////////////////////////////////////
// module calling package
///////////////////////////////////////////////////////
module test_package (
n ,
result
);
input [3:0 ] n ;
output [31:0] result ;
wire [3:0 ] n ;
reg [31:0] result ;
always @(n) begin
result = n * user_pkg.factorial(n) / ((n * 2) + 1);
end
endmodule
6) module calling task
///////////////////////////////////////////////////////
// module user_pkg contains task
///////////////////////////////////////////////////////
module user_pkg;
task segment_dec;
input [3:0] bcd ;
output [6:0] segment;
begin
case(bcd)
//decode from bcd to segment
4'h0: segment = 7'b1000000;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
default: segment = 7'b1000000;
endcase
end
endtask
endmodule
///////////////////////////////////////////////////////
// module calling task
///////////////////////////////////////////////////////
module bcd2segment (
bcd ,
segment
);
input [3:0] bcd ;
output [6:0] segment ;
wire [3:0] bcd ;
reg [6:0] segment ;
always @(bcd) begin
user_pkg.segment_dec(bcd, segment);
end
endmodule
7) parameter
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
clk ,
rst_n ,
clk_out
);
parameter N = 12499999;
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
reg clk_out ;
integer clk_cnt;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
clk_cnt <= 0;
clk_out <= 1'b0;
end
else begin
//when counter reaches to half second,
//need to reset the counter to 0
if(clk_cnt == N) begin
clk_cnt <= 0;
clk_out <= ~clk_out;
end
else begin
clk_cnt <= clk_cnt + 1;
clk_out <= clk_out;
end
end
end
endmodule
/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
clk ,
rst_n ,
clk_out
);
parameter N = 20;
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
wire clk_out ;
//instance clock dividor
clk_div #(
//verilog 2000
//.N(N)
N
) u_clk_div (
.clk (clk ) ,
.rst_n (rst_n ) ,
.clk_out (clk_out )
);
endmodule
8) instance module
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
clk ,
rst_n ,
clk_out
);
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
reg clk_out ;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
clk_out <= 1'b0;
end
else begin
clk_out <= ~clk_out;
end
end
endmodule
/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
clk ,
rst_n ,
clk_out
);
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
wire clk_out ;
//instance clock dividor
clk_div u_clk_div (
.clk (clk ) ,
.rst_n (rst_n ) ,
.clk_out (clk_out )
);
endmodule
9) ifdef
`define M7 7
module bcd2segment (
bcd ,
segment
);
input [3:0 ] bcd ;
output [`M7-1:0] segment;
wire [3:0 ] bcd ;
reg [`M7-1:0] segment;
always @(bcd) begin
case(bcd)
`ifdef M7
//decode from bcd to segment
4'h0: segment = 7'b1111111;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
//for other unknown selectors, set counter to 0
default: segment = 7'b1111111;
`else
//decode from bcd to segment
4'h0: segment = 8'b11111111;
4'h1: segment = 8'b11111001;
4'h2: segment = 8'b10100100;
4'h3: segment = 8'b10110000;
4'h4: segment = 8'b10011001;
4'h5: segment = 8'b10010010;
4'h6: segment = 8'b10000010;
4'h7: segment = 8'b11111000;
4'h8: segment = 8'b10000000;
4'h9: segment = 8'b10010000;
//for other unknown selectors, set counter to 0
default: segment = 8'b11111111;
`endif
endcase
end
endmodule
///////////////////////////////////////////////////////
// module user_pkg contains task
///////////////////////////////////////////////////////
module user_pkg;
task segment_dec;
input [3:0] bcd ;
output [6:0] segment;
begin
case(bcd)
//decode from bcd to segment
4'h0: segment = 7'b1000000;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
default: segment = 7'b1000000;
endcase
end
endtask
endmodule
///////////////////////////////////////////////////////
// module calling task
///////////////////////////////////////////////////////
module bcd2segment (
bcd ,
segment
);
input [3:0] bcd ;
output [6:0] segment ;
wire [3:0] bcd ;
reg [6:0] segment ;
always @(bcd) begin
user_pkg.segment_dec(bcd, segment);
end
endmodule
7) parameter
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
clk ,
rst_n ,
clk_out
);
parameter N = 12499999;
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
reg clk_out ;
integer clk_cnt;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
clk_cnt <= 0;
clk_out <= 1'b0;
end
else begin
//when counter reaches to half second,
//need to reset the counter to 0
if(clk_cnt == N) begin
clk_cnt <= 0;
clk_out <= ~clk_out;
end
else begin
clk_cnt <= clk_cnt + 1;
clk_out <= clk_out;
end
end
end
endmodule
/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
clk ,
rst_n ,
clk_out
);
parameter N = 20;
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
wire clk_out ;
//instance clock dividor
clk_div #(
//verilog 2000
//.N(N)
N
) u_clk_div (
.clk (clk ) ,
.rst_n (rst_n ) ,
.clk_out (clk_out )
);
endmodule
8) instance module
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
clk ,
rst_n ,
clk_out
);
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
reg clk_out ;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
clk_out <= 1'b0;
end
else begin
clk_out <= ~clk_out;
end
end
endmodule
/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
clk ,
rst_n ,
clk_out
);
input clk ;
input rst_n ;
output clk_out ;
wire clk ;
wire rst_n ;
wire clk_out ;
//instance clock dividor
clk_div u_clk_div (
.clk (clk ) ,
.rst_n (rst_n ) ,
.clk_out (clk_out )
);
endmodule
9) ifdef
`define M7 7
module bcd2segment (
bcd ,
segment
);
input [3:0 ] bcd ;
output [`M7-1:0] segment;
wire [3:0 ] bcd ;
reg [`M7-1:0] segment;
always @(bcd) begin
case(bcd)
`ifdef M7
//decode from bcd to segment
4'h0: segment = 7'b1111111;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
//for other unknown selectors, set counter to 0
default: segment = 7'b1111111;
`else
//decode from bcd to segment
4'h0: segment = 8'b11111111;
4'h1: segment = 8'b11111001;
4'h2: segment = 8'b10100100;
4'h3: segment = 8'b10110000;
4'h4: segment = 8'b10011001;
4'h5: segment = 8'b10010010;
4'h6: segment = 8'b10000010;
4'h7: segment = 8'b11111000;
4'h8: segment = 8'b10000000;
4'h9: segment = 8'b10010000;
//for other unknown selectors, set counter to 0
default: segment = 8'b11111111;
`endif
endcase
end
endmodule
10) parameter used as data width
`define M7
module bcd2segment (
bcd ,
segment
);
`ifdef M7
parameter M = 7;
`else
parameter M = 8;
`endif
input [3:0 ] bcd ;
output [M-1:0] segment;
wire [3:0 ] bcd ;
reg [M-1:0] segment;
always @(bcd) begin
case(bcd)
`ifdef M7
//decode from bcd to segment
4'h0: segment = 7'b1111111;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
//for other unknown selectors, set counter to 0
default: segment = 7'b1111111;
`else
//decode from bcd to segment
4'h0: segment = 8'b11111111;
4'h1: segment = 8'b11111001;
4'h2: segment = 8'b10100100;
4'h3: segment = 8'b10110000;
4'h4: segment = 8'b10011001;
4'h5: segment = 8'b10010010;
4'h6: segment = 8'b10000010;
4'h7: segment = 8'b11111000;
4'h8: segment = 8'b10000000;
4'h9: segment = 8'b10010000;
//for other unknown selectors, set counter to 0
default: segment = 8'b11111111;
`endif
endcase
end
endmodule
31) testbench
/////////////////////////////////////////////////////////////////
//DUT
/////////////////////////////////////////////////////////////////
module adder (
clk ,
rst_n ,
enable ,
a ,
b ,
s ,
cout
);
input clk ;
input rst_n ;
input enable ;
input [3:0] a ;
input [3:0] b ;
output [3:0] s ;
output cout ;
wire clk ;
wire rst_n ;
wire enable ;
wire [3:0] a ;
wire [3:0] b ;
wire [3:0] s ;
wire cout ;
reg [4:0] sum ;
assign s = sum[3:0];
assign cout = sum[4];
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
sum <= 5'h0;
else begin
if(enable == 1)
sum <= a + b;
end
end
endmodule
/////////////////////////////////////////////////////////////////
//tb
/////////////////////////////////////////////////////////////////
module tb_adder();
reg clk ;
reg rst_n ;
reg enable ;
reg [3:0] a ;
reg [3:0] b ;
wire [3:0] s ;
wire cout ;
adder u_adder (
.clk (clk ) ,
.rst_n (rst_n ) ,
.enable (enable ) ,
.a (a ) ,
.b (b ) ,
.s (s ) ,
.cout (cout )
);
initial begin
clk = 1'b0;
forever #6.67 clk = ~clk;
end
initial begin
rst_n = 1'b0;
#600;
rst_n = 1'b1;
end
integer i;
integer j;
initial begin
enable <= 1'b0;
a <= 'h0;
b <= 'h0;
@(posedge rst_n);
@(negedge clk)
for(i=0; i<16; i=i+1) begin
for(j=0; j<16; j=j+1) begin
@(negedge clk);
a = i[3:0];
b = j[3:0];
enable = 1'b0;
@(posedge clk);
#1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
@(negedge clk);
enable = 1'b1;
@(posedge clk);
#1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
end
end
#100;
$finish();
end
endmodule
`define M7
module bcd2segment (
bcd ,
segment
);
`ifdef M7
parameter M = 7;
`else
parameter M = 8;
`endif
input [3:0 ] bcd ;
output [M-1:0] segment;
wire [3:0 ] bcd ;
reg [M-1:0] segment;
always @(bcd) begin
case(bcd)
`ifdef M7
//decode from bcd to segment
4'h0: segment = 7'b1111111;
4'h1: segment = 7'b1111001;
4'h2: segment = 7'b0100100;
4'h3: segment = 7'b0110000;
4'h4: segment = 7'b0011001;
4'h5: segment = 7'b0010010;
4'h6: segment = 7'b0000010;
4'h7: segment = 7'b1111000;
4'h8: segment = 7'b0000000;
4'h9: segment = 7'b0010000;
//for other unknown selectors, set counter to 0
default: segment = 7'b1111111;
`else
//decode from bcd to segment
4'h0: segment = 8'b11111111;
4'h1: segment = 8'b11111001;
4'h2: segment = 8'b10100100;
4'h3: segment = 8'b10110000;
4'h4: segment = 8'b10011001;
4'h5: segment = 8'b10010010;
4'h6: segment = 8'b10000010;
4'h7: segment = 8'b11111000;
4'h8: segment = 8'b10000000;
4'h9: segment = 8'b10010000;
//for other unknown selectors, set counter to 0
default: segment = 8'b11111111;
`endif
endcase
end
endmodule
31) testbench
/////////////////////////////////////////////////////////////////
//DUT
/////////////////////////////////////////////////////////////////
module adder (
clk ,
rst_n ,
enable ,
a ,
b ,
s ,
cout
);
input clk ;
input rst_n ;
input enable ;
input [3:0] a ;
input [3:0] b ;
output [3:0] s ;
output cout ;
wire clk ;
wire rst_n ;
wire enable ;
wire [3:0] a ;
wire [3:0] b ;
wire [3:0] s ;
wire cout ;
reg [4:0] sum ;
assign s = sum[3:0];
assign cout = sum[4];
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
sum <= 5'h0;
else begin
if(enable == 1)
sum <= a + b;
end
end
endmodule
/////////////////////////////////////////////////////////////////
//tb
/////////////////////////////////////////////////////////////////
module tb_adder();
reg clk ;
reg rst_n ;
reg enable ;
reg [3:0] a ;
reg [3:0] b ;
wire [3:0] s ;
wire cout ;
adder u_adder (
.clk (clk ) ,
.rst_n (rst_n ) ,
.enable (enable ) ,
.a (a ) ,
.b (b ) ,
.s (s ) ,
.cout (cout )
);
initial begin
clk = 1'b0;
forever #6.67 clk = ~clk;
end
initial begin
rst_n = 1'b0;
#600;
rst_n = 1'b1;
end
integer i;
integer j;
initial begin
enable <= 1'b0;
a <= 'h0;
b <= 'h0;
@(posedge rst_n);
@(negedge clk)
for(i=0; i<16; i=i+1) begin
for(j=0; j<16; j=j+1) begin
@(negedge clk);
a = i[3:0];
b = j[3:0];
enable = 1'b0;
@(posedge clk);
#1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
@(negedge clk);
enable = 1'b1;
@(posedge clk);
#1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
end
end
#100;
$finish();
end
endmodule
Subscribe to:
Posts (Atom)