Google

Lubee's Blog--Digtial IC Fan's Home

WELCOME IC FANS' HOME! --ASIC/IC Design,Logical Design,STA,Digital IC Design,Synthesis, and so on.

2008-05-24

(fwd)Design of a 16bit Synchronous Processor

Design of a 16bit Synchronous Processor

Author : K V Sarma Jonnavithula


When my colleague Mr. Balamurugan Selvaraj asked me to write something as a guest writer for this website, I was pleasantly surprised. I didnt expect it, given the fact that I am not even 1 year old in the industry. So, even before we start, I would like to thank Mr. Balamurugan Selvaraj for being so kind and encouraging. This is my first post on a web site in the internet. I hope it will be useful to you, the all important reader.

My first thoughts about what to write went into something very generic but then I realized that I may not be able to do justice because I myself am not very knowledgeable in this regard. So, after lot of thought, I realized that I should write about my experiences. So, I decided to write about a project I did as a part of one of my courses in my post graduation in BITS, Pilani. The project was "Design of 16 bit Synchronous Processor".

The project was done under Dr. Anu Gupta who was the instructor for the course Advanced VLSI Design. The project was part of the course structure. Initially, there were teams of two. Me and my project mate Nidhi Choudary were to do the Control Path of a 16 bit asynchronous processor while two of my other batch-mates - Sandeep and Ashutosh Tiwari were to design the Data Path of a 16 bit asynchronous processor. We requested Anu ji to club the two parts and make it a single project to be done by four of us. We renamed the poject as Design of a 16 bit Asynchronous processor.

We started with a simple literature survey. We found that 16 bit asynchronous processors do exist but only in the form of ASICs. As a part of our project, we had to demonstrate the work done on an Altera Cyclone II FPGA. A quick search showed that this FPGA cant be used to implement such asynchronous designs. We reported the same to Anu ji and told her our difficulty. She conceded our request to rename the project as "Design of 16 bit Asynchronous Processor". Well thats a bit about the history of the project.

Our first target was to define the targets of the project. The objectives were clear. We have to design a 16 bit synchronous processor core - just the control path and data path, implement the circuit on an FPGA and execute a sample code. Although we wanted to make a board and implement a set of codes, we decided against it due to the time involved.

As a part of one other course called "VLSI Architectures", we had learnt how to design processors. We used Nick Trednick's "Micro Processor Design : The Flow Chart Method" book during that course. Click here to know more about the book. We used the techniques described in the book. Since the processor itself was not very complex, it made sense to use this simple technique, though it might not be used anywhere now. For simplicity, we call the processor "SynchPro".

Fig 1 : Block Diagram of SynchPro

The first step in the design process was to define the resources and the instruction set. We defined that SynchPro will have following resources.

1) Instruction Decoder

2) Control

3) Data Path

4) Counter

5) IRF, IRE latches

  • ID decodes the instruction and selects the state that has to be executed next. It also allocates the count_val to the counter so that it can assert the count_done signal high upon counting the cycles. This is mainly useful to distinguish the normal states and states with external bus activity. In case there is bus activity, the count_val is 0010 i.e., 2 cycles else 0001 i.e., 1 cycle. ID also deciphers the instruction and identifies rx,ry,rz from the instruction which will be used by control unit.

  • Control generates control word. This control word is 36 bit control word. This unit identifies the bus controls and register controls depending upon the state under execution. It also generates the register enables. The bus and register controls are generated depending upon the State under execution because the register number depends upon the instruction and here we make use of the rx,ry,rz generated by instruction decoder.

  • Counter, as has been described above, is what maintains order in the house. It decides when to stop the current state, when to start the next state and is thus crucial. Its o/p is used by datapath as well as instruction decoder. The purposes have already been explained.

  • Datapath is the core execution unit. Its operation is simple and it is the unit where we have all the registers (general purpose(r0 to r7) as well as PC,Do,Di,Ao) and operation units (ALU, Multiplier, Shifter).

Data Path

Fig 2 : Data Path of SynchPro

The different resources of the processor are:

  • Address out register (Ao) of 16-bit

  • Data out register (Do) of 16-bit

  • Data in register (Di) of 16-bit

  • Program Counter register (PC) of 16-bit

  • 8 General Purpose registers (R0-R7) of 16-bit each

  • Two ALU output registers (A & B) of 16-bit each. Two registers have been taken because of the multiplication unit

  • Arithmetic Control Unit to perform all arithmetic and logical operations

  • Shifter to perform all shifting operations

  • Multiplier to perform multiplication of two 16-bit numbers

  • Two buses (a and b) connect all these elements together

Control Path

Fig 3 shows the Control Path of SynchPro. IRF and IRE are shown only for convenience.

Fig 3 : Control Path of SynchPro

  • The Instruction Decoder sends the address of the control word sequence to the control store.

  • The Control Store contains the control word sequences for all the instructions.

  • The State Sequencer steps the Control Store through each control word in the sequence for the instruction.

  • The Control Word Decoder transforms each of the Control Words into specific control signals for the execution unit, register select unit, bus select unit.

Design of Control Path

The design of Control path was done using the hardware flow chart techniques. The control word was generated for all the special purpose registers (pc,do,di,ao) using optimized flow charts. More on that later.

Instruction Set Summary

Instruction Format

The length of the instruction is 16 bits. Five MSB bits are assigned for opcode, next three for destination register and next three for source register. Remaining LSB bits can be used in future for complex instructions.

Addressing Modes

Two types of addressing modes have been used

  • Register Direct

  • Register Indirect

We wanted to define an instruction set rich in terms of the arithmetic instructions. We defined 24 instructions.

Instruction Set

All the instructions are categorized into 4 parts:

  1. Data Movement Instructions

  2. Arithmetic and Logical Instructions

  3. Shift Instructions

  4. Jump Instructions

The details of opcode and instruction formats for these categories are detailed in the following.

Data Movement Instructions

1) MOV Rx, Ry

Move the contents of Ry to Rx

Flags are not effected.

2) MOV @Rx, Ry

Move the contents of Ry to the location denoted by contents of Rx

Flags are not effected.

3) MOV Rx, @Ry

Move the contents of the location denoted by Ry to Rx

Flags are not effected.

Arithmetic & Logic Instructions

1) AND Rx, Ry

Bitwise AND the contents of Rx to the contents of Ry

Flags are not effected.

2) OR Rx, Ry

Bitwise OR the contents of Rx to the contents of Ry

Flags are not effected.

3) XOR Rx, Ry

Bitwise XOR the contents of Rx to the contents of Ry

Flags are not effected.

4) XNOR Rx, Ry

Bitwise XNOR the contents of Rx to the contents of Ry

Flags are not effected.

5) ADD Rx, Ry

Add the contents of Rx to the contents of Ry and save the result into Rx

Flags are effected.

6) ADC Rx, Ry

Add the contents of Rx to the contents of Ry with the previous carry and save the result into Rx

Flags are effected.

7) DEC Rx

Decrement the content of Rx by one and save the result in Rx

Flags are effected.

8) INC Rx

Increment the content of Rx by one and save the result in Rx

Flags are effected.

9) CMP Rx

Complement of Rx and save the result in Rx

Flags are effected.

10) TCMP Rx

Two's complement of Rx and save the result in Rx

Flags are effected.

11) SUB Rx, Ry

Subtract the contents of Ry to the contents of Rx and save the result in Rx

Flags are effected.

12) MUL @ Rx

Multiply the contents of R0 and R1 and save the result to the location denoted by contents of Rx

Flags are not effected.

Shifting Instructions

1) SHL Rx, Ry

Shift the contents of Rx to left by the value denoted by the lower 4 bits of Ry

Flags are not effected.

2) SHR Rx, Ry

Shift the contents of Rx to right by the value denoted by the lower 4 bits of Ry

Flags are not effected.

3) ROL Rx, Ry

Rotate the contents of Rx to the left by the value denoted by the lower 4 bits of Ry

Flags are effected.

4) ROR Rx, Ry

Rotate the contents of Rx to the right by the value denoted by the lower 4 bits of Ry

Flags are not effected.

Jump Instructions

There are two types of Branch instructions. They are Conditional and Unconditional. SynchPro supports two types of the instructions.

1) JMP @Rx (This is Unconditional Jump)

Jump unconditionally to the address given by the contents of Ry

Flags are not effected and not used in this Branching.

2) CJNE Rx, Ry, @Rz

Compare Rx and Ry if not equal, jump to the address given by the contents of Rz

Flags are effected by this instruction and zero flag is used in its execution.

3) DJNZ Rx, @Ry

Decrement the Rx by one and if not equal to zero, jump to the address given by contents of Ry

Flags are effected by this instruction and zero flag is used in its execution.

In addition to these, SynchPro allows for use of no operation instructions useful in creating delays in program.

NOP

No operation

Flags are not effected. This instruction simply increments PC and does not effect any other register.

With these specifications, we went on with the procedures specified in Nick Tredinick's book. Our next step was to make the hardware flowcharts. Making hardware flowcharts is a very old approach. Today, many faster means might be in use. However, as students we had inherent sense of satisfaction in going through the process of making the flow charts, the way we learnt it. You can read the book for more on how to do it. I will summarize it as follows:
  1. Make a list of processor instructions.
  2. Divide them into two parts - the operation jobs and house keeping jobs. An instruction is said to complete it execution cycle only when it has done both the parts operations part and the house keeping part.
  3. List out the necessary resources for each of the parts in two different charts.
  4. Mix the two parts of the charts for each instruction so that there is no conflict in using the resources.
  5. Now that we have the list of resources required for each of the instructions, arrive at control word per state of the instruction. Note that each instruction might have different number of states because the processor is not of RISC type but of CISC type
That marked the end of the a very crucial step in designing the processor. We had the control word ready. We finally arrived at the Control ROM dimensions of 36 bits wide and 32 locations deep. The next step was to modularize and develop RTL. Nidhi handled the Control ROM and Bus Control Generation. Sandeep Handled the Data Path without the multiplier. Multiplier was implemented by Ashutosh and I did the integration of control path as well as final integration of all the modules and also top level simulations. Initially, since we had asynchronous processor as target, we started making a Wallace tree based combinational multiplier but then we changed our target to synchronous processor. We didnt want to redo the complete multiplier looking at the time factor. So, we stuck what we had and that made Multiplier a huge combinational logic. The implementation needed a lot of co-ordination between us in terms of the handshaking and other details. A slightest mis communication wasted precious hours. We had to complete the whole project in 45 days. The first week went away on the literature survey. Next 20 days went on with control word generation. The next 15 days on implementation. Setting up things on FPGA went quite smoothly though. For simualtion purposes, we initially wrote a small program as a test case. This program returned the results we were expecting. The problem was about synthesising on FPGA and demonstrating how things worked. We made a small test bench on FPGA. Even before that we needed to arrive at how to handle instruction and data memory. Should they be on same RAM, i.e., through the same external bus or should there be separate external buses and thus separate RAMs for Data and Instructions. Here, Sandeep's experience with micro controllers and his love for micro controllers came in handy. Though we are talking of a processor, having two external buses meant no harm. Yeah, the question of two external memory controllers made sense but we wanted to just forget about it then. We were afraid however that Anu ji would ask us the same question but then during demonstration, she didnt. This is something that can be altered if two external memory controllers seem to be a bit too costly!!! The question of how to demonstrate on FPGA was a tricky one because we didnt have time to make the board. So, we decided that we will put the test bench with in the FPGA. Something like this Our first attempts to synthesize on FPGA failed miserably. A continuous effort was needed and again, Sandeep's experience and our belief in the work made it possible just in time. The verification of the designs is not vigorous. We wrote some 5-6 sample codes and ran simulations. A vigorous verification would take several weeks, I think. However, that can always be done.


Rules of operation of SynchPro:
  • rst has to be low upon power on and it has to be high during the operation of the processor. During operation, if rst is de-asserted and asserted, then the processor starts execution from 0000h location. This is the first instruction in the code segment. It powers on into "nop" i.e., once we start the processor, it executes a "nop" instruction.
  • There are two external buses. One is for EDBDatain and the other for EDBCodeSeg. EAB and EDBDataOut are o/ps and we assume no buses for the verification. Instead, when data is to be written out, Write pin will go high.
  • The test board we are implementing for demo of SynchPro is specified as TestBoard.vhd in the codes. The address allocation is as follows:

0000h to 0FFFh is Code Segment Address Space

1FFFh to 7FFFh is Data Segment Address Space (read only)

8FFFh to FFFFh is Data Segment Address Space (write only) i.e., this goes as EDBDataOut

Synthesis was done on Altera Cyclone II FPGA EP1C6Q240C8. As expected, multiplier was on critical path and the maximum clock frequency was 19.51 MHz. Replacing the Wallace Tree Multiplier with a Booth's Algorithm implementation must result in better performance. Area didnt matter as a parameter because synthesis target was FPGA. To summarize, I would like to say that, due to some very innovative and interesting ideas at different points of time through the project we could make SynchPro which is
  • a processor core that has a rich instruction set
  • a multiplier
  • a rich arithmetic and logical instruction set
  • three jump statements - one unconditional and two conditional
We cannot guarantee how SynchPro will fare as an ASIC, but if interrupts and exceptions are added to the current design, then SynchPro will definitely suite the needs of a small micro controller on an FPGA. The complete report on the processor is available on internet - thanks to google docs and spreadsheets. Click here to look at the document. If you are interested in trying out SynchPro for your designs, we can provide you the codes. Please do contact me at vividvivek@gmail.com for the codes/suggestions/comments of any kind. Our instructor Anu ji has been guiding a lot of students like us for more than a decade. Many other students did many projects under her guidance like us. At BITS, Pilani, we even have a repository of the work done. These projects include many types of MACs, different types of memory sub-system elements and also various analog blocks including several kinds of op-amps, different kinds of PLLs, several types of filters etc. You may contact her at anug@bits-pilani.ac.in

Labels: , ,

2008-05-17

systemverilog_example:Parity

//-----------------------------------------------------
// Design Name : parity_using_assign
// File Name : parity_using_assign.sv
// Function : Parity using assign
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module parity_using_assign (
input wire [7:0] data_in , // 8 bit data in
output wire parity_out // 1 bit parity out
);
//--------------Code Starts Here-----------------------
assign parity_out = (data_in[0] ^ data_in[1]) ^
(data_in[2] ^ data_in[3]) ^
(data_in[4] ^ data_in[5]) ^
(data_in[6] ^ data_in[7]);

endmodule

Using function- I

space.gif




1 //-----------------------------------------------------
2 // Design Name : parity_using_function
3 // File Name : parity_using_function.sv
4 // Function : Parity using function
5 // Coder : Deepak Kumar Tala
6 //-----------------------------------------------------
7 module parity_using_function (
8 input wire [7:0] data_in , // 8 bit data in
9 output wire parity_out // 1 bit parity out
10 );
11 //--------------Code Starts Here-----------------------
12 function parity;
13 input [31:0] data;
14 begin
15 parity = (data_in[0] ^ data_in[1]) ^
16 (data_in[2] ^ data_in[3]) ^
17 (data_in[4] ^ data_in[5]) ^
18 (data_in[6] ^ data_in[7]);
19 end
20 endfunction
21
22 assign parity_out = parity(data_in);
23
24 endmodule
You could download file sv_examples here

space.gif

../../images/main/bulllet_4dots_orange.gif Using function- II

space.gif




1 //-----------------------------------------------------
2 // Design Name : parity_using_function2
3 // File Name : parity_using_function2.v
4 // Function : Parity using function
5 // Coder : Deepak Kumar Tala
6 //-----------------------------------------------------
7 module parity_using_function2 (
8 input wire [31:0] data_in , // 8 bit data in
9 output reg parity_out // 1 bit parity out
10 );
11 //--------------Code Starts Here-----------------------
12 function parity;
13 input [31:0] data;
14 integer i;
15 begin
16 parity = 0;
17 for (i = 0; i < id="sc"> = i + 1) begin
18 parity = parity ^ data[i];
19 end
20 end
21 endfunction
22
23 always_comb
24 begin
25 parity_out = parity(data_in);
26 end
27
28 endmodule
You could download file sv_examples here

space.gif

../../images/main/bulllet_4dots_orange.gif And the Practical One

space.gif




1 //-----------------------------------------------------
2 // Design Name : parity_using_bitwise
3 // File Name : parity_using_bitwise.sv
4 // Function : Parity using bitwise xor
5 // Coder : Deepak Kumar Tala
6 //-----------------------------------------------------
7 module parity_using_bitwise (
8 input wire [7:0] data_in , // 8 bit data in
9 output wire parity_out // 1 bit parity out
10 );
11 //--------------Code Starts Here-----------------------
12 assign parity_out = ^data_in;
13
14 endmodule

Labels:

2008-05-13

FPGA Overview

Field Programmable Gate Arrays are two dimensional array of logic blocks and flip-flops with a electrically programmable interconnections between logic blocks.

The interconnections consist of electrically programmable switches which is why FPGA differs from Custom ICs, as Custom IC is programmed using integrated circuit fabrication technology to form metal interconnections between logic blocks.

In an FPGA logic blocks are implemented using mutliple level low fanin gates, which gives it a more compact design compared to an implementation with two-level AND-OR logic. FPGA provides its user a way to configure:

  1. The intersection between the logic blocks and
  2. The function of each logic block.

Logic block of an FPGA can be configured in such a way that it can provide functionality as simple as that of transistor or as complex as that of a microprocessor. It can used to implement different combinations of combinational and sequential logic functions. Logic blocks of an FPGA can be implemented by any of the following:

  1. Transistor pairs
  2. combinational gates like basic NAND gates or XOR gates
  3. n-input Lookup tables
  4. Multiplaexers
  5. Wide fanin And-OR structure.

test

Figure 1: Simplefied version of FPGA internal architecture.

Routing in FPGAs consists of wire segments of varying lengths which can be interconnected via electrically programmable switches. Density of logic block used in an FPGA depends on length and number of wire segments used for routing. Number of segments used for interconnection typically is a tradeoff between density of logic blocks used and amount of area used up for routing.

The ability to reconfigure functionality to be implemented on a chip gives a unique advantage to designer who designs his system on an FPGA It reduces the time to market and significantly reduces the cost of production.

Why do we need FPGAs ?

By the early 1980’s Large scale integrated circuits (LSI) formed the back bone of most of the logic circuits in major systems. Microprocessors, bus/IO controllers, system timers etc were implemented using integrated circuit fabrication technology. Random “glue logic” or interconnects were still required to help connect the large integrated circuits in order to :

  1. generate global control signals (for resets etc.)
  2. data signals from one subsystem to another sub system.

Systems typically consisted of few large scale integrated components and large number of SSI (small scale integrated circuit) and MSI (medium scale integrated circuit) components.

Intial attempt to solve this problem led to development of Custom ICs which were to replace the large amount of interconnect. This reduced system complexity and manufacturing cost, and improved performance.However, custom ICs have their own disadvantages. They are relatively very expensive to develop, and delay introduced for product to market (time to market) because of increased design time. There are two kinds of costs involved in development of Custom ICs:
1. cost of development and design
2. cost of manufacture
( A tradeoff usually exists between the two costs)

Therefore the custom IC approach was only viable for products with very high volume, and which were not time to market sensitive.

FPGAs were introduced as an alternative to custom ICs for implementing entire system on one chip and to provide flexibility of reporogramability to the user. Introduction of FPGAs resulted in improvement of density relative to discrete SSI/MSI components (within around 10x of custom ICs). Another advantage of FPGAs over CustomICs is that with the help of computer aided design (CAD) tools circuits could be implemented in a short amount of time (no physical layout process, no mask making, no IC manufacturing)
test

Figure 2: FPGA comparative analysis.

Labels:

2008-05-08

systemverilog code example_2:up_counter

//-----------------------------------------------------
// Design Name : up_counter
// File Name : up_counter.sv
// Function : Up counter
// Coder : Deepak
//-----------------------------------------------------
module up_counter (
output reg [7:0] out , // Output of the counter
input wire enable , // enable for counter
input wire clk , // clock Input
input wire reset // reset Input
);
//-------------Code Starts Here-------
always_ff @(posedge clk)
if (reset) begin
out <= 8'b0 ;
end else if (enable) begin
out ++;
end

endmodule

2008-05-05

systemverilog code example_1:MUX

Mux : Using assign Statement

//-----------------------------------------------------
// Design Name : mux_using_assign
// File Name : mux_using_assign.sv
// Function : 2:1 Mux using Assign
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module mux_using_assign (
input wire din_0 , // Mux first input
input wire din_1 , // Mux Second input
input wire sel , // Select input
output wire mux_out // Mux output
);
//-------------Code Start-----------------
assign mux_out = (sel) ? din_1 : din_0;

endmodule //End Of Module mux


//-----------------------------------------------------
// Design Name : mux_using_if
// File Name : mux_using_if.sv
// Function : 2:1 Mux using If
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module mux_using_if(
input wire din_0 , // Mux first input
input wire din_1 , // Mux Second input
input wire sel , // Select input
output reg mux_out // Mux output
);
//-------------Code Starts Here---------
always_comb
begin : MUX
if (sel == 1'b0) begin
mux_out = din_0;
end else begin
mux_out = din_1 ;
end
end

endmodule //End Of Module mux


//-----------------------------------------------------
// Design Name : mux_using_case
// File Name : mux_using_case.sv
// Function : 2:1 Mux using Case
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module mux_using_case(
input wire din_0 , // Mux first input
input wire din_1 , // Mux Second input
input wire sel , // Select input
output reg mux_out // Mux output
);
//-------------Code Starts Here---------
always @ (*)
MUX : begin
case (sel)
1'b0 : mux_out = din_0;
1'b1 : mux_out = din_1;
endcase
end

endmodule //End Of Module mux


Labels:

2008-05-04

systemverilog code example_1:Encoder

Encoder - Using if-else Statement
//-----------------------------------------------------
// Design Name : encoder_using_if
// File Name : encoder_using_if.sv
// Function : Encoder using If
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module encoder_using_if(
output reg [3:0] binary_out , // 4 bit binary Output
input wire [15:0] encoder_in , // 16-bit Input
input wire enable // Enable for the encoder
);
//--------------Code Starts Here-----------------------
always_comb
begin
binary_out = 0;
if (enable) begin
if (encoder_in == 16'h0002) begin
binary_out = 1;
end if (encoder_in == 16'h0004) begin
binary_out = 2;
end if (encoder_in == 16'h0008) begin
binary_out = 3;
end if (encoder_in == 16'h0010) begin
binary_out = 4;
end if (encoder_in == 16'h0020) begin
binary_out = 5;
end if (encoder_in == 16'h0040) begin
binary_out = 6;
end if (encoder_in == 16'h0080) begin
binary_out = 7;
end if (encoder_in == 16'h0100) begin
binary_out = 8;
end if (encoder_in == 16'h0200) begin
binary_out = 9;
end if (encoder_in == 16'h0400) begin
binary_out = 10;
end if (encoder_in == 16'h0800) begin
binary_out = 11;
end if (encoder_in == 16'h1000) begin
binary_out = 12;
end if (encoder_in == 16'h2000) begin
binary_out = 13;
end if (encoder_in == 16'h4000) begin
binary_out = 14;
end if (encoder_in == 16'h8000) begin
binary_out = 15;
end
end
end

endmodule


Encoder - Using case Statement
//-----------------------------------------------------
// Design Name : encoder_using_case
// File Name : encoder_using_case.sv
// Function : Encoder using Case
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module encoder_using_case(
output reg [3:0] binary_out , // 4 bit binary Output
input wire [15:0] encoder_in , // 16-bit Input
input wire enable // Enable for the encoder
);
//--------------Code Starts Here-----------------------
always_comb
ENCODER : begin
binary_out = 0;
if (enable) begin
case (encoder_in)
16'h0002 : binary_out = 1;
16'h0004 : binary_out = 2;
16'h0008 : binary_out = 3;
16'h0010 : binary_out = 4;
16'h0020 : binary_out = 5;
16'h0040 : binary_out = 6;
16'h0080 : binary_out = 7;
16'h0100 : binary_out = 8;
16'h0200 : binary_out = 9;
16'h0400 : binary_out = 10;
16'h0800 : binary_out = 11;
16'h1000 : binary_out = 12;
16'h2000 : binary_out = 13;
16'h4000 : binary_out = 14;
16'h8000 : binary_out = 15;
endcase
end
end

endmodule

Labels:

2008-05-02

tristate verilog code

module tristate (T, In, Out);
input T, In;
output Out;
reg Out;

always @(T or In)
begin
if (~T)
Out = In;
else
Out = 1'bZ;
end
endmodule

Labels: