And Gate Example

Below we will discuss the component that implements Rapid HDL And Gates.

Code

using System;

namespace RapidHDL
{

	public class AndGate : TruthTableComponent
	{
		public NodeVector InputNodes;
		public NodeVector OutputNodes;

		int iInputWidth;

		public AndGate(Component poParentComponent, string psName, int piInputWidth) : base (poParentComponent,psName)
		{
			iInputWidth = piInputWidth;
			this.GetTruthTable("AndGate",iInputWidth,1);
			InputNodes = this.CreateNodeVector("In",iInputWidth,NodeFlowType.Sink);
			OutputNodes = this.CreateNodeVector("Out",1,NodeFlowType.Source);
		}

		protected override void GenerateTruthTable()
		{
			string sInput;

			this.TruthTable.AddTableEntry("default","0");
			sInput = "";
			sInput = sInput.PadRight(iInputWidth,'1');
			this.TruthTable.AddTableEntry(sInput,"1");

            this.TruthTable.AddTableEntry("default-X*0", "0"); // undefined with any zero is always 0
		}

		public override bool TransformStructureToVerilog()
		{
			WriteVerilogLookupTable();
			return true;
		}
     }

Discussion

Inheritance

The AndGate class is derived from the TruthTable class. The TruthTable class inherits the Component class. At a minimum, the constructor for a class inheriting the Component class must specify a parent component and an instance name. Below, we see these parameters passed to the base constructor.

		public AndGate(Component poParentComponent, string psName, int piInputWidth) : base (poParentComponent,psName)
		{

Node Vector inputs and outputs

The and gate has inputs and outputs. They are publicly exposed so that the nodevectors can be used to connect this component to other components in the hierarchy.

		public NodeVector InputNodes;
		public NodeVector OutputNodes;

In the class constructor, the node vectors are instantiated. The input nodevector is a sink. The output nodevector is a source. (By default, nodevectors are created as passthrough.) The CreateNodeVector method is available in any class that inherits Component. Calling this method ensures the proper parent relationship between the component and the nodevector is maintained.

Important: NodeVectors that will be exposed to other components for interconnection purposes should be instantiated in the constructor. This ensures that they will not be a null value when the connection is defined.

Nodevector instance names must be unique within a parent component. Notice that the instance name does not match the exposed property name (i.e. "In" <> "InputNodes"). When Verilog is generated, the signal will be named "In", not "InputNodes."

Also, the input width is dynamically specified as a width parameter in the constructor. This And Gate implementation combines all of the inputs into a single output.

		InputNodes = this.CreateNodeVector("In",iInputWidth,NodeFlowType.Sink);
		OutputNodes = this.CreateNodeVector("Out",1,NodeFlowType.Source);

Truth Table

A truth table only needs to be defined once, although it may be shared by multiple components.

Truth tables are uniquely identified by a name. In this case, the truth table name for all And Gates of this type are named "AndGate". Truth tables having the same name may have different input widths. For example, the truth table for a 5 input And Gate will be different from a 3 input And Gate.

In the constructor, we set the truth table to be used by this component using the GetTruthTable method that was inherited from the TruthTableComponent class. The parameters to this method are the truth table name, the truth table input width, and the truth table output width.

this.GetTruthTable("AndGate",iInputWidth,1);

Defining The Truth Table

If a truth table has not yet been defined, the virtual GenerateTruthTable() method will be called. The truth table for an AndGate is relatively simple, but very complex truth tables may be generated using for next loops and the all of the power of C#.

The TruthTable.AddTableEntry() method adds entries to the truth table. The first parameter is a binary input string, and the second parameter is the corresponding binary output string.

Binary strings may use the characters '1','0','X'. A default output may be specified by using the "default" input string.


Simulation Only: By default, if any input is undefined, 'X', then the output will also be undefined 'X'. However, the output of an And Gate will always be 0 if at least one input is 0. So, we use the "default-X" notation. For the And Gate, the "default-X*0" input string sets the output of the gate if at least one input is 0.

		protected override void GenerateTruthTable()
		{
			string sInput;

			this.TruthTable.AddTableEntry("default","0");
			sInput = "";
			sInput = sInput.PadRight(iInputWidth,'1');
			this.TruthTable.AddTableEntry(sInput,"1");

            this.TruthTable.AddTableEntry("default-X*0", "0"); // undefined with any zero is always 0
		}

Verilog Generation

During Verilog file generation, the virtual TransformStrutureToVerilog() method may be overridden to script the verilog logic for the component. Only the logic needs to be scripted, because Rapid HDL automatically handles the module definition, inputs and outputs, and the routings between various components in the hierarchy.

In this code, we call the WriteVerilogLookupTable() method, which is inherited from the TruthTableComponent class. This method will cause the truth table of our component to be written as Verilog.

		public override bool TransformStructureToVerilog()
		{
			WriteVerilogLookupTable();
			return true;
		}

Consuming the And Gate

A 2 input AndGate might be used in the following manner:

      AndGate oAndGate = new RapidHDL.AndGate(this,"busy",2);

Output Verilog Module

The Verilog generated for a 2 input and gate might look like the Verilog below.

module rhdl_AndGate4
   (In,
   Out);

      input [1:0] In;

      output Out;


      wire In_s1_e1;
      wire In_s0_e0;



//*****  Redundant Wiring  *****

         assign In_s1_e1 = {In[1]};
         assign In_s0_e0 = {In[0]};

//*****  Subcomponet Declarations  *****


         reg Out;

always @(In)
begin
   case ({In})
         2'b11 : {Out} = 1'b1;
         default : {Out} = 1'b0;
   endcase
end

endmodule

Last edited Sep 9, 2009 at 6:27 PM by allen248, version 2

Comments

No comments yet.