Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //INSTRUCTIONS
- //Extend the vending machine model from Section 16.3 to allow
- //U.S.A. currencies from a nickel to twenty dollar bill (0.05, 0.10, 0.25, 0.50, 1.00, 2.00, 5.00, 10.00, and 20.00).
- //Add a cancel button which will return the currency inserted.
- //Add a two character selection criteria with first character being from A-H and second character from 1-9.
- //Read a price file for each of the 72 items.
- //Add a current monies held for each type of currency (also read from a file)
- //and after dispensing return the residual using the minimum number of currency unit.
- //Write a testbench which validates each of these functions.
- //d flip flop for state control
- module DFF(clk, in, out);
- parameter n = 1; //width
- input clk;
- input [n-1:0] in;
- output [n-1:0] out;
- reg [n-1:0] out;
- //posedge triggers on rising edge of clock signal
- always @(posedge clk)
- out = in;
- endmodule
- //mux3 - pg 157
- //three input mux with one-hot select (arbitrary width)
- module Mux3(a2, a1, a0, s, b);
- parameter k = 1;
- input [k-1:0] a2, a1, a0; //inputs
- input [2:0] s; //one-hot selet
- output [k-1:0] b;
- assign b = ({k{s[2]}} & a2) |
- ({k{s[1]}} & a1) |
- ({k{s[0]}} & a0);
- endmodule
- //addsub - pg 221
- // add a+b or subtract a - b, check for overflow
- module AddSub(a, b, sub, s, ovf);
- parameter n = 8;
- input [n-1:0] a, b;
- input sub; //subtract if sub=1, otherwise add
- output [n-1:0] s;
- output ovf; //1 if overflow
- wire c1, c2; //carry out of last two bits
- assign ovf = c1 ^ c2; //overflow if signs don't match
- //add non sign bits
- assign {c1, s[n-2:0]} = a[n-2:0] + (b[n-2:0] ^ {n-1{sub}}) + sub;
- //add sign bits
- assign {c2, s[n-1]} = a[n-1] + (b[n-1] ^ sub) + c1;
- endmodule
- module VendingMachine(clk, rst, nickel, dime, quarter, dispense, done, price, serve, change);
- parameter n = `DWIDTH;
- input clk, rst, nickel, dime, quarter, dispense, done;
- input [n-1:0] price;
- output serve, change;
- wire enough, zero, sub;
- wire [3:0] selval;
- wire [2:0] selnext;
- VendingMachineControl vmc(clk, rst, nickel, dime, quarter, dispense, done, enough, zero, serve, change, selval, selnext, sub);
- VendingMachineData #(n) vmd(clk, selval, selnext, sub, price, enough, zero);
- endmodule
- module VendingMachineControl(clk, rst, nickel, dime, quarter, dispense, done, enough, zero, serve, change, selval, selnext, sub);
- input clk, rst, nickel, dime, quarter, dispense, done, enough, zero;
- output serve, change, sub;
- output [3:0] selval;
- output [2:0] selnext;
- wire [`SWIDTH-1:0] state, next; //current and next state
- reg [`SWIDTH-1:0] next1; //next state w/o reset
- //outputs
- wire first; //true during first cycle of serve1 or change1
- wire serve1 = (state == `SERVE1);
- wire change1 = (state == `CHANGE1);
- assign serve = serve1 & first;
- assign change = chang1 & first;
- //datapath controls
- wire dep = (state == `DEPOSIT);
- // price, 1, 2, 5
- wire [3:0] selval = {(dep & dispense),
- ((dep & nickel) | change),
- (dep & dime),
- (dep & quarter)};
- // amount, sum, 0
- wire selv = (dep & (nickel | dime | quarter | (dispense & enough))) |
- (change & first);
- wire [2:0] selnext = {~(selv | rst), ~rst & selv,rst};
- //subtract
- wire sub = (dep & dispense) | change;
- //only do actions on first cycle of serve1 or change1
- wire nfirst = !(serve1 | change1);
- DFF #(1) first_reg(clk, nfirst, first);
- //state register
- DFF #(`SWIDTH) state_reg(clk, next, state);
- //next state logic
- always @(*) begin
- casex({dispense, enough, done, zero, state})
- {4'b11xx, `DEPOSIT}: next1 = `SERVE1; //dispense & enough
- {4'b0xxx, `DEPOSIT}: next1 = `DEPOSIT;
- {4'bx0xx, `DEPOSIT}: next1 = `DEPOSIT;
- {4'bxx1x, `SERVE1}: next1 = `SERVE2; //done
- {4'bxx0x, `SERVE1}: next1 = `SERVE1;
- {4'bxx01, `SERVE2}: next1 = `DEPOSIT; //~done & zero
- {4'bxx00, `SERVE2}: next1 = `CHANGE1; //~done & ~zero
- {4'bxx1x, `SERVE2}: next1 = `SERVE2; //done
- {4'bxx1x, `CHANGE1}: next1 = `CHANGE2; //done
- {4'bxx0x, `CHANGE1}: next1 = `CHANGE1; //done
- {4'bxx00, `CHANGE2}: next1 = `CHANGE1; //~done & ~zero
- {4'bxx01, `CHANGE2}: next1 = `DEPOSIT; //~done & zero
- {4'bxx1x, `CHANGE2}: next1 = `CHANGE2; //~done & ~zero
- endcase
- end
- //reset next state
- assign next = rst ? `DEPOSIT : next1;
- endmodule
- module VendingMachineData(clk, selval, selnext, sub, price, enough, zero);
- parameter n = 6;
- input clk, sub;
- input [3:0] selval; //price, 1, 2, 5
- input [2:0] selnext; //amount, sum, 0
- input [n-1:0] price; //price of soft drink - in nickels
- output enough; //amount > price
- output zero; //amount = zero
- wire [n-1:0] sum; //output of add/subtract unit
- wire [n-1:0] amount; //current amount
- wire [n-1:0] next; //next amount
- wire [n-1:0] value; //value to add or subtract from amount
- wire ovf; //overflow - ignore for now
- //state register holds current amount
- DFF #(n) amt(clk, next, amount);
- //select next state from 0, sum, or hold
- Mux3 #(n) nsmux(amount, sum, {n{1'b0}}, selnext, next);
- //add or subtract a value from current amount
- AddSub #(n) add(amount, value, sub, sum, ovf);
- //select the value to add or subtract
- //p
- Mux4 #(n) vmux(price, `NICKEL, `DIME, `QUARTER, selval, value);
- //comparators
- wire enough = (amount >= price);
- wire zero = (amount == 0);
- endmodule
- module testVend;
- reg clk, rst, nickel, dime, quarter, dispense, done;
- reg [3:0] price;
- wire serve, change;
- VendingMachine #(4) vm(clk, rst, nickel, dime, quarter, dispense, done, price,
- serve, change);
- //clock with period of 10 units
- initial begin
- clk = 1; #5 clk = 0;
- forever begin
- $display("%b %h %h %b %b",
- {nickel, dime, quarter, dispense}, vm.vmc.state, vm.vmd.amount, serve, change);
- #5 clk = 1; #5 clk = 0;
- end
- end
- //give prompt feedback
- always @(posedge clk) begin
- done = (serve | change);
- end
- initial begin
- rst = 1; {nickel, dime, quarter, dispense} = 4'b0;
- price = `PRICE;
- #25 rst = 0;
- #10 {nickel, dime, quarter, dispense} = 4'b1000; //nickel 1
- #10 {nickel, dime, quarter, dispense} = 4'b0100; //dime 3
- #10 {nickel, dime, quarter, dispense} = 4'b0000; //nothing
- #10 {nickel, dime, quarter, dispense} = 4'b0001; //try to dispense early
- #10 {nickel, dime, quarter, dispense} = 4'b0010; //quarter 8
- #10 {nickel, dime, quarter, dispense} = 4'b0010; //quarter 13
- #10 {nickel, dime, quarter, dispense} = 4'b0000; //nothing
- #10 {nickel, dime, quarter, dispense} = 4'b0001; //dispense 2
- #10 dispense = 0;
- #100 $stop;
- end
- endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement