/// Code for LSU EE 4702 Spring 2001
/// Calculator Example
module calc(display_val,key_code);
input [5:0] key_code;
output display_val;
`include "calc_keys.v"
parameter kty_digit = 6'd30;
parameter kty_arith = 6'd31;
parameter kty_any = 6'bx;
reg [2:0] state, next_state;
parameter st_0N = 3'd0;
parameter st_0P = 3'd1;
parameter st_0C = 3'd2;
parameter st_1N = 3'd3;
parameter st_1P = 3'd4;
parameter st_xx = 3'bxxx;
parameter buffer_max = 'h7fffffff;
reg [31:0] buffer, acc;
reg [5:0] pending_op, key_type;
wire [31:0] display_val = buffer;
task add_digit;
begin
if( buffer < buffer_max )
buffer = buffer * 10 + key_code - key_0;
end
endtask // add_digit
function [31:0] do_op;
input dummy;
begin
case( pending_op )
key_plus : do_op = acc + buffer;
key_minus : do_op = acc - buffer;
key_times : do_op = acc * buffer;
key_divide : do_op = buffer ? acc / buffer : 0;
endcase // case( pending_op )
end
endfunction // do_op
task fatal;
input [319:0] message;
begin
$display("Error in behavioral description: %s",message);
$display("Execution stopping.");
$stop;
end
endtask // fatal
task do_beep;
$display("Beeeeeep!!! %d",state);
endtask
always @( key_code ) if( key_code != key_none ) begin
case( key_code )
key_0,key_1,key_2,key_3,key_4,key_5,key_6,key_7,key_8,key_9:
key_type = kty_digit;
key_plus,key_minus,key_times,key_divide:
key_type = kty_arith;
default:
key_type = key_code;
endcase // case( key_code )
casex( {state,key_type} )
{st_xx,key_clear}: begin acc = 0; buffer = 0; next_state = st_0N; end
{st_0N,kty_digit}: begin add_digit; next_state = st_0P; end
{st_0P,kty_digit}: begin add_digit; next_state = state; end
{st_0P,kty_arith}:
begin
pending_op = key_code;
acc = buffer;
buffer = 0;
next_state = st_1N;
end
{st_0C,kty_digit}:
begin
buffer = 0;
add_digit;
next_state = st_0P;
end
{st_0C,kty_arith}:
begin
pending_op = key_code;
acc = buffer;
buffer = 0;
next_state = st_1N;
end
{st_1N,kty_digit}: begin add_digit; next_state = st_1P; end
{st_1P,kty_digit}: begin add_digit; next_state = state; end
{st_1P,key_equal}:
begin
buffer = do_op(0);
next_state = st_0C;
end
{st_1P,kty_arith}:
begin
acc = do_op(0);
pending_op = key_code;
buffer = 0;
next_state = st_1N;
end
{st_0N,kty_any}, {st_0C,kty_any}, {st_0P,kty_any},
{st_1N,kty_any}, {st_1P,kty_any}:
begin do_beep; next_state = state; end
default: begin
$display("Behavioral code error, unexpected state.");
$display("Stopping.");
end
endcase
state <= next_state;
end // if ( key_code != key_none )
endmodule // calc
module demo_calc();
wire [31:0] display;
reg [5:0] key;
calc c1(display,key);
`include "calc_keys.v"
task command;
input [799:0] cmd;
integer initialized;
integer c;
reg [5:0] to_key [0:255];
begin
if( initialized === 'bx ) begin
for( c = 0; c < 256; c = c + 1 ) to_key[c] = key_never;
for( c = 0; c < 10; c = c + 1 ) to_key[ "0" + c ] = key_0 + c;
to_key["+"] = key_plus;
to_key["-"] = key_minus;
to_key["/"] = key_divide;
to_key["*"] = key_times;
to_key["="] = key_equal;
to_key["c"] = key_clear;
to_key[" "] = key_none;
to_key[0] = key_none;
initialized = 1;
end // if ( initialized === 'bx )
while( cmd ) begin:COMMAND_LOOP
reg [7:0] c;
c = cmd[799:792];
key = to_key[ c ];
if( key == key_never ) begin
$display("Testbench error: illegal key in command, %s (%d)",c,c);
$stop;
end
#1;
if( key != key_none ) $display("Key %s Display %d",c,display);
key = key_none;
#1;
cmd = cmd << 8;
end // block: COMMAND_LOOP
end
endtask // command
initial begin
command("c 5 c 12 + 34 = ");
command(" 1 + 2 + 3 + 4 = - 10 = ");
end
endmodule // demo_calc