Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///////////////////////////////////////////////////////////////
- timeunit 1ns;
- timeprecision 1ns;
- class Transaction ;
- rand bit n; // nickel
- rand bit d; // dime
- rand bit q; // quarter
- constraint C1 { {n,d,q} dist {3'b100:=120, 3'b010:=50, 3'b001:=20};}
- endclass: Transaction
- ////////////////////////////////////////////////////////////
- class Generator;
- Transaction trans;
- mailbox drv_mb;
- mailbox scb_mb;
- function new (mailbox drv_mb, scb_mb);
- this.drv_mb = drv_mb;
- this.scb_mb = scb_mb;
- endfunction
- /////////////////////
- task main (int count);
- repeat (count) begin
- trans = new();
- if (!trans.randomize)
- $fatal (0, "<<<<---Randomization Failure--->>>");
- drv_mb.put(trans);
- scb_mb.put(trans);
- end//repeat
- endtask
- ///////////////////
- endclass:Generator
- ////////////////////////////////////////////////////////////
- class Driver;
- Transaction trans;
- mailbox gen2drv;
- virtual candy_if.TEST tb_port_h;
- int nickels, dimes, quarters;
- bit done;
- function new (virtual candy_if.TEST tb_port_h, mailbox bb);
- this.tb_port_h = tb_port_h;
- gen2drv = bb;
- endfunction
- task reset();
- tb_port_h.rst <= 0;
- $display ("RESET started.. @%0t",$time);
- tb_port_h.n <= 0;
- tb_port_h.d <= 0;
- tb_port_h.q <= 0;
- #12ns;
- tb_port_h.rst <= 1; // de-assert reset...
- $display ("RESET ended.. @%0t",$time);
- endtask
- ///////////////////////////
- task drive(int count);
- repeat (count) begin:loop
- gen2drv.get(trans);
- @(posedge tb_port_h.clk);
- tb_port_h.n <= trans.n;
- tb_port_h.d <= trans.d;
- tb_port_h.q <= trans.q;
- @(posedge tb_port_h.clk); // one clock duration pulse
- tb_port_h.n <= 0;
- tb_port_h.d <= 0;
- tb_port_h.q <= 0;
- if(tb_port_h.dispense)
- repeat (20)@(posedge tb_port_h.clk);//for next set of coins..
- nickels += trans.n;
- dimes += trans.d;
- quarters += trans.q;
- end:loop
- done = 1'b1; //mailbox emptied
- //$display("DRIVER::\tNICKELS = %0d, DIMES = %0d, QUARTERS = %0d\n",nickels, dimes, quarters);
- endtask
- /////////////////////////////
- endclass
- ////////////////////////////////////////////////////////////
- class Scoreboard;
- mailbox scb_mb;
- Transaction trans;
- nickels, dimes, quarters, num_candies;
- int candy_cents, total_cents;
- int rn, rd;
- ///////////////////////////
- function new (mailbox scb_mb);
- this.scb_mb = scb_mb;
- endfunction
- ///////////////////////////
- task compute(int count);
- repeat (count) begin
- scb_mb.get(trans);
- nickels += trans.n;
- dimes += trans.d;
- quarters += trans.q;
- candy_cents += 5*trans.n + 10*trans.d + 25*trans.q;
- total_cents += 5*trans.n + 10*trans.d + 25*trans.q;
- if(candy_cents >= 25) begin
- num_candies++;
- if(candy_cents==30) rn++;
- else if (candy_cents ==35) rd++;
- else if (candy_cents ==40) begin rd++;rn++; end
- else if (candy_cents ==45) begin rd++;rd++; end
- candy_cents = 0; // prepare for the next candy dispense...
- end
- end //repeat
- endtask
- ///////////////////////////
- task scb_display;
- //$display("SCOREBOARD:: TOTAL CENTS=%0d",total_cents);
- //$display("SCOREBOARD:: NICKELS = %0d, DIMES = %0d, QUARTERS = %0d\n",
- //nickels, dimes, quarters);
- $display("SCOREBOARD:: CANDIES = %0d", num_candies);
- $display("SCOREBOARD:: DIMES Returned = %0d",rd);
- $display("SCOREBOARD:: NICKELS Returned = %0d\n",rn);
- endtask
- endclass
- ////////////////////////////////////////////////////////////
- class Monitor;
- int num_candies, rn, rd;
- virtual candy_if.MONITOR mon_port_h;
- //////////////////////
- function new(virtual candy_if.MONITOR aa);
- mon_port_h = aa;
- endfunction
- //////////////////////
- task collect_info;
- @(negedge mon_port_h.clk);
- if(mon_port_h.dispense) num_candies++;
- if(mon_port_h.rd) rd++;
- if(mon_port_h.rn) rn++;
- endtask
- //////////////////////
- task mon_display;
- $display ("MONITOR:: CANDIES = %0d", num_candies);
- $display ("MONITOR:: DIMES Returned = %0d", rd);
- $display ("MONITOR:: NICKELS returned = %0d\n", rn);
- endtask
- //////////////////////
- endclass
- ////////////////////////////////////////////////////////////
- class Environment;
- Generator gen;
- mailbox gen_mb, scb_mb;
- Driver drv;
- Scoreboard scb;
- Monitor mon;
- bit fail;
- // declare handles to the Interface for use by Driver and Monitor
- virtual candy_if.TEST tb_port_h;
- virtual candy_if.MONITOR mon_port_h;
- //////////////////////
- function new (virtual candy_if.TEST aa, virtual candy_if.MONITOR bb);
- tb_port_h = aa;
- mon_port_h = bb;
- gen_mb = new(1);
- scb_mb = new(1);
- gen = new(gen_mb, scb_mb);
- drv = new(tb_port_h, gen_mb);
- scb = new(scb_mb);
- mon = new(mon_port_h);
- endfunction
- /////////////////////
- task run(int count);
- pre_test();
- test(count);
- post_test();
- endtask
- ////////////////////
- task pre_test();
- drv.reset;
- repeat (5)
- @(posedge tb_port_h.clk); // some arbitrary delay...
- endtask
- ///////////////////
- task test(count);
- fork:fj1
- gen.main(count);
- drv.drive(count);
- scb.compute(count);
- while (!drv.done)
- mon.collect_info();
- join:fj1
- endtask
- //////////////////
- task post_test();
- scb.scb_display();
- mon.mon_display();
- if((scb.num_candies != mon.num_candies) || mon.num_candies ==0 )
- fail = 1;
- if((scb.rn != mon.rn) || mon.rn==0)
- fail = 1;
- if((scb.rd != mon.rd) || mon.rd==0)
- fail = 1;
- if(fail)
- $display ("<<<<<----TEST FAILED --->>>>>>\n");
- else
- $display ("!!! TEST PASSED !!!\n");
- endtask
- //////////////////
- endclass
- ////////////////////////////////////////////////////////////
- interface candy_if (input bit clk);
- logic rst;
- logic n;
- logic d;
- logic q;
- logic dispense;
- logic rn;
- logic rd;
- ///////////
- modport DUT (
- output dispense, rn ,rd,
- input rst, n, d, q, clk
- );
- modport TEST (
- input dispense, rn ,rd, clk,
- output rst, n, d, q
- );
- modport MONITOR (
- input dispense, rn, rd, clk
- );
- endinterface:candy_if
- ////////////////////////////////////////////////////////////
- program automatic tb_candy_vending (tb_port, mon_port);
- candy_if.TEST tb_port;
- candy_if.MONITOR mon_port;
- Environment env;
- int rpt_count = 401;
- bit fail;
- // declare and initialize the interface handles..
- virtual candy_if.TEST tb_port_h = tb_port;
- virtual candy_if.MONITOR mon_port_h = mon_port;
- // apply the inputs.....
- initial begin
- env = new (tb_port_h, mon_port_h);
- env.run(rpt_count);
- end
- initial
- begin
- $recordfile("candy_vending_ver3.trn");
- $recordvars();
- end
- endprogram
- ////////////////////////////////////////////////////////////
- module top_candy_vending_ver4;
- // generate the clock....
- bit clk=1;
- always #5 clk++;
- // instantiate the interface..
- candy_if IF1(
- .clk(clk)
- );
- // instantiate the design unit...
- candy_vending U2 (
- .design_port(IF1.DUT)
- );
- // instantiate the program block
- tb_candy_vending U1 (
- .tb_port(IF1.TEST),
- .mon_port(IF1.MONITOR)
- );
- endmodule
- ////////////////////////////////////////////////////////////
- module candy_vending ( design_port);
- candy_if.DUT design_port;
- localparam [3:0] // for holding value of money deposited....
- S0 = 4'b0000,
- S5 = 4'b0001,
- S10 = 4'b0010,
- S15 = 4'b0011,
- S20 = 4'b0100,
- S25 = 4'b0101,
- S30 = 4'b0110,
- S35 = 4'b0111,
- S40 = 4'b1000,
- S45 = 4'b1001,
- Sdd = 4'b1010, // dummy state...
- SDD = 4'b1011; // dispense dime
- reg [3:0] cst, nst; /// current and next states...
- always_comb begin
- nst = cst;
- case (cst)
- S0 :
- if(design_port.n) nst = S5;
- else if(design_port.d) nst = S10;
- else if(design_port.q) nst = S25;
- S5 :
- if(design_port.n) nst = S10;
- else if(design_port.d) nst = S15;
- else if(design_port.q) nst = S30;
- S10 :
- if(design_port.n) nst = S15;
- else if(design_port.d) nst = S20;
- else if(design_port.q) nst = S35;
- S15 :
- if(design_port.n) nst = S20;
- else if(design_port.d) nst = S25;
- else if(design_port.q) nst = S40;
- S20 :
- if(design_port.n) nst = S25;
- else if(design_port.d) nst = S30;
- else if(design_port.q) nst = S45;
- S25 , // in all these states candy is dispensed....
- S30 ,
- S35 ,
- S40 ,
- SDD : nst = S0;
- S45 : nst = Sdd; // candy dispensed in S45
- Sdd : nst = SDD; // Sdd is dummy state to separate out release of two dimes....
- default: nst = S0;
- endcase
- end // begin
- always_ff @(posedge design_port.clk or negedge design_port.rst) // sequential logic....
- if(!design_port.rst)
- cst <= S0;
- else
- cst <= nst;
- assign design_port.dispense = (cst == S25)
- | (cst == S30)
- | (cst == S35)
- | (cst == S40)
- | (cst == S45);
- assign design_port.rn = (cst == S30)
- | (cst == S40);
- assign design_port.rd = (cst == S35)
- | (cst == S40)
- | (cst == S45)
- | (cst == SDD);
- endmodule
- ///////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement