SHOW:
|
|
- or go back to the newest paste.
1 | //INSTRUCTIONS | |
2 | //Extend the vending machine model from Section 16.3 to allow | |
3 | //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). | |
4 | //Add a cancel button which will return the currency inserted. | |
5 | //Add a two character selection criteria with first character being from A-H and second character from 1-9. | |
6 | //Read a price file for each of the 72 items. | |
7 | //Add a current monies held for each type of currency (also read from a file) | |
8 | //and after dispensing return the residual using the minimum number of currency unit. | |
9 | //Write a testbench which validates each of these functions. | |
10 | ||
11 | ||
12 | ||
13 | ||
14 | //d flip flop for state control | |
15 | module DFF(clk, in, out); | |
16 | parameter n = 1; //width | |
17 | input clk; | |
18 | input [n-1:0] in; | |
19 | output [n-1:0] out; | |
20 | reg [n-1:0] out; | |
21 | ||
22 | //posedge triggers on rising edge of clock signal | |
23 | always @(posedge clk) | |
24 | out = in; | |
25 | endmodule | |
26 | ||
27 | ||
28 | //mux3 - pg 157 | |
29 | //three input mux with one-hot select (arbitrary width) | |
30 | module Mux3(a2, a1, a0, s, b); | |
31 | parameter k = 1; | |
32 | input [k-1:0] a2, a1, a0; //inputs | |
33 | input [2:0] s; //one-hot selet | |
34 | output [k-1:0] b; | |
35 | assign b = ({k{s[2]}} & a2) | | |
36 | ({k{s[1]}} & a1) | | |
37 | ({k{s[0]}} & a0); | |
38 | endmodule | |
39 | ||
40 | ||
41 | //addsub - pg 221 | |
42 | // add a+b or subtract a - b, check for overflow | |
43 | module AddSub(a, b, sub, s, ovf); | |
44 | parameter n = 8; | |
45 | input [n-1:0] a, b; | |
46 | input sub; //subtract if sub=1, otherwise add | |
47 | output [n-1:0] s; | |
48 | output ovf; //1 if overflow | |
49 | wire c1, c2; //carry out of last two bits | |
50 | assign ovf = c1 ^ c2; //overflow if signs don't match | |
51 | ||
52 | //add non sign bits | |
53 | assign {c1, s[n-2:0]} = a[n-2:0] + (b[n-2:0] ^ {n-1{sub}}) + sub; | |
54 | //add sign bits | |
55 | assign {c2, s[n-1]} = a[n-1] + (b[n-1] ^ sub) + c1; | |
56 | endmodule | |
57 | ||
58 | ||
59 | ||
60 | module VendingMachine(clk, rst, nickel, dime, quarter, dispense, done, price, serve, change); | |
61 | parameter n = `DWIDTH; | |
62 | input clk, rst, nickel, dime, quarter, dispense, done; | |
63 | input [n-1:0] price; | |
64 | output serve, change; | |
65 | ||
66 | wire enough, zero, sub; | |
67 | wire [3:0] selval; | |
68 | wire [2:0] selnext; | |
69 | ||
70 | VendingMachineControl vmc(clk, rst, nickel, dime, quarter, dispense, done, enough, zero, serve, change, selval, selnext, sub); | |
71 | ||
72 | VendingMachineData #(n) vmd(clk, selval, selnext, sub, price, enough, zero); | |
73 | endmodule | |
74 | ||
75 | ||
76 | ||
77 | ||
78 | module VendingMachineControl(clk, rst, nickel, dime, quarter, dispense, done, enough, zero, serve, change, selval, selnext, sub); | |
79 | input clk, rst, nickel, dime, quarter, dispense, done, enough, zero; | |
80 | output serve, change, sub; | |
81 | output [3:0] selval; | |
82 | output [2:0] selnext; | |
83 | wire [`SWIDTH-1:0] state, next; //current and next state | |
84 | reg [`SWIDTH-1:0] next1; //next state w/o reset | |
85 | ||
86 | //outputs | |
87 | wire first; //true during first cycle of serve1 or change1 | |
88 | wire serve1 = (state == `SERVE1); | |
89 | wire change1 = (state == `CHANGE1); | |
90 | assign serve = serve1 & first; | |
91 | assign change = chang1 & first; | |
92 | ||
93 | //datapath controls | |
94 | wire dep = (state == `DEPOSIT); | |
95 | // price, 1, 2, 5 | |
96 | wire [3:0] selval = {(dep & dispense), | |
97 | ((dep & nickel) | change), | |
98 | (dep & dime), | |
99 | (dep & quarter)}; | |
100 | // amount, sum, 0 | |
101 | wire selv = (dep & (nickel | dime | quarter | (dispense & enough))) | | |
102 | (change & first); | |
103 | wire [2:0] selnext = {~(selv | rst), ~rst & selv,rst}; | |
104 | ||
105 | //subtract | |
106 | wire sub = (dep & dispense) | change; | |
107 | ||
108 | //only do actions on first cycle of serve1 or change1 | |
109 | wire nfirst = !(serve1 | change1); | |
110 | DFF #(1) first_reg(clk, nfirst, first); | |
111 | ||
112 | //state register | |
113 | DFF #(`SWIDTH) state_reg(clk, next, state); | |
114 | ||
115 | //next state logic | |
116 | always @(*) begin | |
117 | casex({dispense, enough, done, zero, state}) | |
118 | {4'b11xx, `DEPOSIT}: next1 = `SERVE1; //dispense & enough | |
119 | {4'b0xxx, `DEPOSIT}: next1 = `DEPOSIT; | |
120 | {4'bx0xx, `DEPOSIT}: next1 = `DEPOSIT; | |
121 | {4'bxx1x, `SERVE1}: next1 = `SERVE2; //done | |
122 | {4'bxx0x, `SERVE1}: next1 = `SERVE1; | |
123 | {4'bxx01, `SERVE2}: next1 = `DEPOSIT; //~done & zero | |
124 | {4'bxx00, `SERVE2}: next1 = `CHANGE1; //~done & ~zero | |
125 | {4'bxx1x, `SERVE2}: next1 = `SERVE2; //done | |
126 | {4'bxx1x, `CHANGE1}: next1 = `CHANGE2; //done | |
127 | {4'bxx0x, `CHANGE1}: next1 = `CHANGE1; //done | |
128 | {4'bxx00, `CHANGE2}: next1 = `CHANGE1; //~done & ~zero | |
129 | {4'bxx01, `CHANGE2}: next1 = `DEPOSIT; //~done & zero | |
130 | {4'bxx1x, `CHANGE2}: next1 = `CHANGE2; //~done & ~zero | |
131 | endcase | |
132 | end | |
133 | ||
134 | //reset next state | |
135 | assign next = rst ? `DEPOSIT : next1; | |
136 | endmodule | |
137 | ||
138 | ||
139 | ||
140 | ||
141 | ||
142 | ||
143 | module VendingMachineData(clk, selval, selnext, sub, price, enough, zero); | |
144 | parameter n = 6; | |
145 | input clk, sub; | |
146 | input [3:0] selval; //price, 1, 2, 5 | |
147 | input [2:0] selnext; //amount, sum, 0 | |
148 | input [n-1:0] price; //price of soft drink - in nickels | |
149 | output enough; //amount > price | |
150 | output zero; //amount = zero | |
151 | ||
152 | wire [n-1:0] sum; //output of add/subtract unit | |
153 | wire [n-1:0] amount; //current amount | |
154 | wire [n-1:0] next; //next amount | |
155 | wire [n-1:0] value; //value to add or subtract from amount | |
156 | wire ovf; //overflow - ignore for now | |
157 | ||
158 | //state register holds current amount | |
159 | DFF #(n) amt(clk, next, amount); | |
160 | ||
161 | //select next state from 0, sum, or hold | |
162 | Mux3 #(n) nsmux(amount, sum, {n{1'b0}}, selnext, next); | |
163 | ||
164 | //add or subtract a value from current amount | |
165 | AddSub #(n) add(amount, value, sub, sum, ovf); | |
166 | ||
167 | //select the value to add or subtract | |
168 | //p | |
169 | Mux4 #(n) vmux(price, `NICKEL, `DIME, `QUARTER, selval, value); | |
170 | ||
171 | //comparators | |
172 | wire enough = (amount >= price); | |
173 | wire zero = (amount == 0); | |
174 | endmodule | |
175 | ||
176 | ||
177 | ||
178 | ||
179 | ||
180 | module testVend; | |
181 | reg clk, rst, nickel, dime, quarter, dispense, done; | |
182 | reg [3:0] price; | |
183 | wire serve, change; | |
184 | ||
185 | VendingMachine #(4) vm(clk, rst, nickel, dime, quarter, dispense, done, price, | |
186 | serve, change); | |
187 | ||
188 | //clock with period of 10 units | |
189 | initial begin | |
190 | clk = 1; #5 clk = 0; | |
191 | forever begin | |
192 | $display("%b %h %h %b %b", | |
193 | {nickel, dime, quarter, dispense}, vm.vmc.state, vm.vmd.amount, serve, change); | |
194 | #5 clk = 1; #5 clk = 0; | |
195 | end | |
196 | end | |
197 | ||
198 | //give prompt feedback | |
199 | always @(posedge clk) begin | |
200 | done = (serve | change); | |
201 | end | |
202 | ||
203 | initial begin | |
204 | rst = 1; {nickel, dime, quarter, dispense} = 4'b0; | |
205 | price = `PRICE; | |
206 | #25 rst = 0; | |
207 | #10 {nickel, dime, quarter, dispense} = 4'b1000; //nickel 1 | |
208 | #10 {nickel, dime, quarter, dispense} = 4'b0100; //dime 3 | |
209 | #10 {nickel, dime, quarter, dispense} = 4'b0000; //nothing | |
210 | #10 {nickel, dime, quarter, dispense} = 4'b0001; //try to dispense early | |
211 | #10 {nickel, dime, quarter, dispense} = 4'b0010; //quarter 8 | |
212 | #10 {nickel, dime, quarter, dispense} = 4'b0010; //quarter 13 | |
213 | #10 {nickel, dime, quarter, dispense} = 4'b0000; //nothing | |
214 | #10 {nickel, dime, quarter, dispense} = 4'b0001; //dispense 2 | |
215 | #10 dispense = 0; | |
216 | #100 $stop; | |
217 | end | |
218 | endmodule |