⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 part2.txt

📁 Thomas课本中的verilog例子。Thomas的verilog在可编程期间领域很有名
💻 TXT
📖 第 1 页 / 共 2 页
字号:
/*
Copyright -c- 1996, Kluwer Academic Publishers. All Rights Reserved.

This electronic text file is distributed by Kluwer Academic Publishers with
*ABSOLUTELY NO SUPPORT* and *NO WARRANTY* from Kluwer
Academic Publishers.

Use or reproduction of the information provided in this electronic text file for
commercial gain is strictly prohibited. Explicit permission is given for the
reproduction and use of this information in an instructional setting provided
proper reference is given to the original source. Kluwer Academic Publishers
shall not be liable for damage in connection with, or arising out of, the furnishing,
performance or use of this information.


>From the Authors:
This file contains copies of the miniSim example in chapter 8, and the Verilog
modules supporting the floppy disk exercise in chapter 9 of "The Verilog
Hardware Description Language, Third Edition" by D. E. Thomas and P. R.
Moorby. The two files, good.dat and bad.dat are necessary for the floppy disk
exercise. They are in separate files.

-always
DT, PM
*/






module miniSim;
 
// element types being modeled
`define Nand 0
`define DEdgeFF 1
`define Wire 2
 
// literal values with strength:
//   format is 8 0-strength bits in decreasing strength order
//   followed by 8 1-strength bits in decreasing strength order
`define Strong0 16'b01000000_00000000
`define Strong1 16'b00000000_01000000
`define StrongX 16'b01111111_01111111
`define Pull0   16'b00100000_00000000
`define Pull1   16'b00000000_00100000
`define Highz0  16'b00000001_00000000
`define Highz1  16'b00000000_00000001
 
// three-valued logic set
`define Val0 3'd0
`define Val1 3'd1
`define ValX 3'd2
 
parameter file://set  DebugFlags to 1 for message
    DebugFlags =               'b11000,
//                               |||||
//  loading                   <--+||||
//  event value changes      <----+|||
//  wire calculation        <------+||
//  evaluation             <--------+|
//  scheduling           <-----------+
 
    IndexSize = 16,     file://maximum size for index pointers
    MaxElements = 50,   file://maximum number of elements
    TypeSize = 12;      file://maximum number of types
 
reg [IndexSize-1:0]
    eventElement,             file://output value change element
    evalElement,                file://element on fanout
    fo0Index[1:MaxElements],  file://first fanout index of eventElement
    fo1Index[1:MaxElements],  file://second fanout index of eventElement
    currentList,              file://current time scheduled event list
    nextList,                 file://unit delay scheduled event list
    schedList[1:MaxElements]; file://scheduled event list index
reg [TypeSize-1:0]
    eleType[1:MaxElements]; file://element type
reg
    fo0TermNum[1:MaxElements],   file://first fanout input terminal number
    fo1TermNum[1:MaxElements],   file://second fanout input terminal number
    schedPresent[1:MaxElements]; file://element is in scheduled event list flags
reg [15:0]
    eleStrength[1:MaxElements], file://element strength indication
    outVal[1:MaxElements],      file://element output value
    in0Val[1:MaxElements],      file://element first input value
    in1Val[1:MaxElements],      file://element second input value
    in0, in1, out, oldIn0;      file://temporary value storage
 
integer pattern, simTime; file://time keepers
 
initial
  begin
    // initialize variables
    pattern = 0;
    currentList = 0;
    nextList = 0;
 
    $display("Loading toggle circuit");
    loadElement(1, `DEdgeFF, 0, `Strong1,0,0, 4,0,0,0);
    loadElement(2, `DEdgeFF, 0, `Strong1,0,0, 3,0,0,0);
    loadElement(3, `Nand, (`Strong0|`Strong1),
        `Strong0,`Strong1,`Strong1, 4,0,1,0);
    loadElement(4, `DEdgeFF, (`Strong0|`Strong1),
        `Strong1,`Strong1,`Strong0, 3,0,1,0);
 
    // apply stimulus and simulate
    $display("Applying 2 clocks to input element 1");
    applyClock(2, 1);
    $display("Changing element 2 to value 0 and applying 1 clock");
    setupStim(2, `Strong0);
    applyClock(1, 1);
 
    $display("\nLoading open-collector and pullup circuit");
    loadElement(1, `DEdgeFF, 0, `Strong1,0,0, 3,0,0,0);
    loadElement(2, `DEdgeFF, 0, `Strong0,0,0, 4,0,0,0);
    loadElement(3, `Nand, (`Strong0|`Highz1),
        `Strong0,`Strong1,`Strong1, 5,0,0,0);
    loadElement(4, `Nand, (`Strong0|`Highz1),
        `Highz1,`Strong0,`Strong1, 5,0,1,0);
    loadElement(5, `Wire, 0,
        `Strong0,`Strong0,`Highz1, 7,0,1,0);
    loadElement(6, `DEdgeFF, 0, `Pull1,0,0, 7,0,0,0);
    loadElement(7, `Wire, 0,
        `Strong0,`Pull1,`Strong0, 0,0,0,0);
 
    // apply stimulus and simulate
    $display("Changing element 1 to value 0");
    pattern = pattern + 1;
    setupStim(1, `Strong0);
    executeEvents;
    $display("Changing element 2 to value 1");
    pattern = pattern + 1;
    setupStim(2, `Strong1);
    executeEvents;
    $display("Changing element 2 to value X");
    pattern = pattern + 1;
    setupStim(2, `StrongX);
    executeEvents;
  end
 
// Initialize data structure for a given element.
task loadElement;
input [IndexSize-1:0] loadAtIndex; file://element index being loaded
input [TypeSize-1:0] type;         file://type of element
input [15:0] strengthCoercion;     file://strength specification of element
input [15:0] oVal, i0Val, i1Val;   file://output and input values
input [IndexSize-1:0] fo0, fo1;    file://fanout element indexes
input fo0Term, fo1Term;            file://fanout element input terminal indicators
  begin
    if (DebugFlags[4])
        $display(
            "Loading element %0d, type %0s, with initial value %s(%b_%b)",
            loadAtIndex, typeString(type),
            valString(oVal), oVal[15:8], oVal[7:0]);
    eleType[loadAtIndex] = type;
    eleStrength[loadAtIndex] = strengthCoercion;
    outVal[loadAtIndex] = oVal;
    in0Val[loadAtIndex] = i0Val;
    in1Val[loadAtIndex] = i1Val;
    fo0Index[loadAtIndex] = fo0;
    fo1Index[loadAtIndex] = fo1;
    fo0TermNum[loadAtIndex] = fo0Term;
    fo1TermNum[loadAtIndex] = fo1Term;
    schedPresent[loadAtIndex] = 0;
  end
endtask
 
// Given a type number, return a type string
function [32*8:1] typeString;
input [TypeSize-1:0] type;
    case (type)
      `Nand: typeString = "Nand";
      `DEdgeFF: typeString = "DEdgeFF";
      `Wire: typeString = "Wire";
      default: typeString = "*** Unknown element type";
    endcase
endfunction
 
// Setup a value change on an element.
task setupStim;
input [IndexSize-1:0] vcElement; file://element index
input [15:0] newVal;           file://new element value
  begin
    if (! schedPresent[vcElement])
      begin
        schedList[vcElement] = currentList;
        currentList = vcElement;
        schedPresent[vcElement] = 1;
      end
    outVal[vcElement] = newVal;
  end
endtask
 
// Setup and simulate a given number of clock pulses to a given element.
task applyClock;
input [7:0] nClocks;
input [IndexSize-1:0] vcElement;
    repeat(nClocks)
      begin
        pattern = pattern + 1;
        setupStim(vcElement, `Strong0);
        executeEvents;
        pattern = pattern + 1;
        setupStim(vcElement, `Strong1);
        executeEvents;
      end
endtask
 
// Execute all events in the current event list.
// Then move the events in the next event list to the current event
// list and loop back to execute these events. Continue this loop
// until no more events to execute.
// For each event executed, evaluate the two fanout elements if present.
task executeEvents;
reg [15:0] newVal;
  begin
    simTime = 0;
    while (currentList)
      begin
        eventElement = currentList;
        currentList = schedList[eventElement];
        schedPresent[eventElement] = 0;
        newVal = outVal[eventElement];
        if (DebugFlags[3])
            $display(
                "At %0d,%0d Element %0d, type %0s, changes to %s(%b_%b)",
                pattern, simTime,
                eventElement, typeString(eleType[eventElement]),
                valString(newVal), newVal[15:8], newVal[7:0]);
        if (fo0Index[eventElement]) evalFo(0);
        if (fo1Index[eventElement]) evalFo(1);
        if (! currentList) // if empty move to next time unit
          begin
            currentList = nextList;
            nextList = 0;
            simTime = simTime + 1;
          end
      end
  end
endtask
 
// Evaluate a fanout element by testing its type and calling the
// appropriate evaluation routine.
task evalFo;
input fanout; file://first or second fanout indicator
  begin
    evalElement = fanout ? fo1Index[eventElement] :
                           fo0Index[eventElement];
    if (DebugFlags[1])
        $display("Evaluating Element %0d type is %0s",
            evalElement, typeString(eleType[evalElement]));
    case (eleType[evalElement])
      `Nand: evalNand(fanout);
      `DEdgeFF: evalDEdgeFF(fanout);
      `Wire: evalWire(fanout);
    endcase
  end
endtask
 
// Store output value of event element into
// input value of evaluation element.
task storeInVal;
input fanout; file://first or second fanout indicator
  begin
    // store new input value
    if (fanout ? fo1TermNum[eventElement] : fo0TermNum[eventElement])
        in1Val[evalElement] = outVal[eventElement];
    else
        in0Val[evalElement] = outVal[eventElement];
  end
endtask
 
// Convert a given full strength value to three-valued logic (0, 1 or X)
function [1:0] log3;
input [15:0] inVal;
    casez (inVal)
      16'b00000000_00000000: log3 = `ValX;
      16'b???????0_00000000: log3 = `Val0;
      16'b00000000_???????0: log3 = `Val1;
      default:               log3 = `ValX;
    endcase
endfunction
 
// Convert a given full strength value to four-valued logic (0, 1, X or Z),
// returning a 1 character string
function [8:1] valString;
input [15:0] inVal;
    case (log3(inVal))
      `Val0: valString = "0";
      `Val1: valString = "1";
      `ValX: valString = (inVal & 16'b11111110_11111110) ? "X" : "Z";
    endcase
endfunction
 
// Coerce a three-valued logic output value to a full output strength value
// for the scheduling of the evaluation element
function [15:0] strengthVal;
input [1:0] logVal;
    case (logVal)
      `Val0: strengthVal = eleStrength[evalElement] & 16'b11111111_00000000;
      `Val1: strengthVal = eleStrength[evalElement] & 16'b00000000_11111111;
      `ValX: strengthVal = fillBits(eleStrength[evalElement]);
    endcase
endfunction
 
// Given an incomplete strength value, fill the missing strength bits.
// The filling is only necessary when the value is unknown.
function [15:0] fillBits;
input [15:0] val;
  begin
    fillBits = val;
    if (log3(val) == `ValX)
      begin
        casez (val)
  16'b1???????_????????: fillBits = fillBits | 16'b11111111_00000001;
  16'b01??????_????????: fillBits = fillBits | 16'b01111111_00000001;
  16'b001?????_????????: fillBits = fillBits | 16'b00111111_00000001;
  16'b0001????_????????: fillBits = fillBits | 16'b00011111_00000001;
  16'b00001???_????????: fillBits = fillBits | 16'b00001111_00000001;
  16'b000001??_????????: fillBits = fillBits | 16'b00000111_00000001;
  16'b0000001?_????????: fillBits = fillBits | 16'b00000011_00000001;
        endcase
        casez (val)
  16'b????????_1???????: fillBits = fillBits | 16'b00000001_11111111;
  16'b????????_01??????: fillBits = fillBits | 16'b00000001_01111111;
  16'b????????_001?????: fillBits = fillBits | 16'b00000001_00111111;
  16'b????????_0001????: fillBits = fillBits | 16'b00000001_00011111;
  16'b????????_00001???: fillBits = fillBits | 16'b00000001_00001111;
  16'b????????_000001??: fillBits = fillBits | 16'b00000001_00000111;
  16'b????????_0000001?: fillBits = fillBits | 16'b00000001_00000011;
       endcase
     end
  end
endfunction
 
// Evaluate a 'Nand' gate primitive.
task evalNand;
input fanout; file://first or second fanout indicator
  begin
    storeInVal(fanout);
    // calculate new output value
    in0 = log3(in0Val[evalElement]);
    in1 = log3(in1Val[evalElement]);
    out = ((in0 == `Val0) || (in1 == `Val0)) ?
        strengthVal(`Val1) :
        ((in0 == `ValX) || (in1 == `ValX)) ?
            strengthVal(`ValX):
            strengthVal(`Val0);
    // schedule if output value is different
    if (out != outVal[evalElement])
        schedule(out);
  end
endtask
 
// Evaluate a D positive edge-triggered flip flop
task evalDEdgeFF;
input fanout; file://first or second fanout indicator
    // check value change is on clock input
    if (fanout ? (fo1TermNum[eventElement] == 0) :
                 (fo0TermNum[eventElement] == 0))
      begin
        // get old clock value
        oldIn0 = log3(in0Val[evalElement]);
        storeInVal(fanout);
        in0 = log3(in0Val[evalElement]);
        // test for positive edge on clock input
        if ((oldIn0 == `Val0) && (in0 == `Val1))
          begin
            out = strengthVal(log3(in1Val[evalElement]));
            if (out != outVal[evalElement])
              schedule(out);
          end
      end
    else
        storeInVal(fanout); // store data input value
endtask
 
// Evaluate a wire with full strength values
task evalWire;
input fanout;
reg [7:0] mask;
  begin
    storeInVal(fanout);
 
    in0 = in0Val[evalElement];
    in1 = in1Val[evalElement];
    mask = getMask(in0[15:8]) & getMask(in0[7:0]) &
           getMask(in1[15:8]) & getMask(in1[7:0]);
    out = fillBits((in0 | in1) & {mask, mask});
 
    if (out != outVal[evalElement])
        schedule(out);
 
    if (DebugFlags[2])
        $display("in0 = %b_%b\nin1 = %b_%b\nmask= %b %b\nout = %b_%b",
            in0[15:8],in0[7:0], in1[15:8],in1[7:0],
            mask,mask, out[15:8],out[7:0]);
  end
endtask
 
// Given either a 0-strength or 1-strength half of a strength value
// return a masking pattern for use in a wire evaluation.
function [7:0] getMask;
input [7:0] halfVal; file://half a full strength value
    casez (halfVal)
      8'b???????1: getMask = 8'b11111111;
      8'b??????10: getMask = 8'b11111110;
      8'b?????100: getMask = 8'b11111100;
      8'b????1000: getMask = 8'b11111000;
      8'b???10000: getMask = 8'b11110000;
      8'b??100000: getMask = 8'b11100000;
      8'b?1000000: getMask = 8'b11000000;
      8'b10000000: getMask = 8'b10000000;
      8'b00000000: getMask = 8'b11111111;
    endcase
endfunction
 
// Schedule the evaluation element to change to a new value.
// If the element is already scheduled then just insert the new value.
task schedule;
input [15:0] newVal; // new value to change to
  begin
    if (DebugFlags[0])
        $display(
            "Element %0d, type %0s, scheduled to change to %s(%b_%b)",
            evalElement, typeString(eleType[evalElement]),
            valString(newVal), newVal[15:8], newVal[7:0]);
    if (! schedPresent[evalElement])
      begin
        schedList[evalElement] = nextList;
schedPresent[evalElement] = 1;
        nextList = evalElement;
      end
    outVal[evalElement] = newVal;
  end
endtask
endmodule
file://example 8.1


//  simulation interface module
//  by Tom Martin, February, 1995 
//  for 18-360 project 1.
//  
//  This module should be listed first on the command line, so that
//  the timescale directive will apply to all other modules, i.e.,
//  verilog simint.v blah1.v blah2.v blah3.v
//  
//  I think the simulator will die if the timescale directive is not
//  in the first module, but is in later ones.

`timescale      10 ns/1 ns
  
module simint(go, count, done, err);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -