2008年5月6日

混合層架構程式

// file: archdev.v//
date: 4/26/93
//
// Copyright 1993 Mark Arnold
// All rights reserved
//
// include file with modules that simulate devices
// which are the basic architectural building blocks
// used in COSC 4700
//


// This models a synchronous enabled register
// The contents are unchanged unless the enable signal is true
// Examples: 74LS377, 74LS378
module enabled_register(di,do,enable,clk);
parameter SIZE = 1,
DELAY = 0,
SETUP = 0;
input di,enable,clk;
output do;
reg [SIZE-1:0] do;
wire [SIZE-1:0] di;
reg [SIZE-1:0] internal_do;
wire enable;
wire clk;
integer last_change;
integer t_setup, t_clk_to_out; //to allow interactive experiment

initial
begin
last_change = 0;
t_setup = SETUP;
t_clk_to_out = DELAY;
end

always @(posedge clk)
begin
if (enable)
begin
do = 'oxxxx;
internal_do = di;
if ($time-last_change > t_setup)
begin
if (t_clk_to_out>0)
#t_clk_to_out do = internal_do;
else
do = internal_do;
end
else
$display("setup violation, time=",$time);
end
end

always @(enable or di)
begin
if (($time % 100) != 0)
last_change = $time;
endendmodule


// This models a synchronous binary counter register
// The contents are unchanged unless count, load or clr is
// true at the rising edge:
//
// clr load count action
// 1 - - do becomes 0
// 0 1 - do becomes di
// 0 0 1 do becomes do - 1
// 0 0 0 do unchanged
//
// Example: 74LS163


module counter_register(di,do,tc,load,count,clr,clk);
parameter SIZE = 1,
DELAY = 0,
SETUP = 0;
input di,load,count,clr,clk;
output do,tc;
reg [SIZE-1:0] do;
wire [SIZE-1:0] di;
reg [SIZE-1:0] internal_do;
reg tc;
wire load,count,clr;
wire clk;
integer last_change;
integer t_setup, t_clk_to_out;
//to allow interactive experiment

initial
begin
last_change = 0;
t_setup = SETUP;
t_clk_to_out = DELAY;
end

always @(posedge clk)
begin
if (clr load count)
begin
if (clr)
internal_do = 0;
else
begin
if (load)
internal_do = di;
else
begin
if (count)
internal_do = do-1;
end
end
do = 'bx;
tc = 'bx;
if (($time-last_change > t_setup))
begin
if (t_clk_to_out>0)
#t_clk_to_out do = internal_do;
else
do = internal_do;
end
else
$display("setup violation, time=",$time);
tc = 0+do===(1 << SIZE) - 1;
end
end

always @(clr or load or count or di)
begin
if (($time % 100) != 0)
last_change = $time;
end
endmodule


// This models is a purely combinational ALU
// It is a universal logic unit on each bit of b,a when m=1
// It does 16 somewhat arbitrary arithmetic operations when m=0

module alu181(a,b,s,m,cin,cout,f,zero);
parameter SIZE = 1, DELAY = 0;
input a,b,s,m,cin;
output cout,f,zero;
wire [SIZE-1:0] a,b;
wire m,cin;
wire [3:0] s;
reg [SIZE-1:0] f;
reg cout,zero;
integer t;
integer i;
event change;
initial t = DELAY;

always @(a or b or s or m or cin)
start_change;

always @change
begin : change_block
if (t != 0)
#t;
if (m)
cout = 0; //not sure
case ({m,s})
5'b00000: {cout,f} = a + cin;
5'b00001: {cout,f} = (a b) + cin;
5'b00010: {cout,f} = (a (~b)) + cin;
5'b00011: {cout,f} = (1 << SIZE) - 1 + cin;
5'b00100: {cout,f} = a + (a&(~b)) + cin;
5'b00101: {cout,f} = (ab) + (a&(~b)) + cin;
5'b00110: {cout,f} = a - b - 1 + cin;
5'b00111: {cout,f} = (a&(~b)) - 1 + cin;
5'b01000: {cout,f} = a + (a&b) + cin;
5'b01001: {cout,f} = a + b + cin;
5'b01010: {cout,f} = (a(~b)) + (a&b) + cin;
5'b01011: {cout,f} = (a&b) - 1 + cin;
5'b01100: {cout,f} = a + a + cin;
5'b01101: {cout,f} = (a(~b)) + a + cin;
5'b01110: {cout,f} = (ab) + a + cin;
5'b01111: {cout,f} = a - 1 + cin;
5'b10000: f = ~a;
5'b10001: f = ~(ab);
5'b10010: f = (~a)&b;
5'b10011: f = 0;
5'b10100: f = ~(a&b);
5'b10101: f = ~b;
5'b10110: f = a^b;
5'b10111: f = a&(~b);
5'b11000: f = (~a)b;
5'b11001: f = ~(a^b);
5'b11010: f = b;
5'b11011: f = a&b;
5'b11100: f = (1 << SIZE) - 1 + cin;
5'b11101: f = a(~b);
5'b11110: f = ab;
5'b11111: f = a;
default: f = 'bx;
endcase
zero = f == 0;
end
task start_change;
begin
if (t != 0)
begin
f = 'bx;
disable change_block;
#0;
end
-> change;
end
endtaskendmodule


// This model is two input comparator
// Example: 74LS85

module comparator(a_lt_b, a_eq_b, a_gt_b, a, b);
parameter SIZE = 1, DELAY = 0;
output a_lt_b, a_eq_b, a_gt_b;
input a, b;
wire [SIZE-1:0] a,b;
reg a_lt_b, a_eq_b, a_gt_b;
integer t;
event change;

initial
t = DELAY;

always @(a or b)
start_change;

always @change
begin : change_block
if (t != 0)
#t;
a_eq_b = a == b;
a_lt_b = a < b;
a_gt_b = a > b;
end

task start_change;
begin
if (t != 0)
begin
a_eq_b = 'bx;
a_lt_b = 'bx;
a_gt_b = 'bx;
disable change_block;
#0;
end
-> change;
end
endtask
endmodule

沒有留言: