Date: February 2/3
Lecture: 11
Homework HW #8
Status Complete
Code lec11.vhdl
Lesson SlidesECE_383_Lec11.pptx

Datapath and control - timing

There are several important reasons to examine the timing behavior of a datapath and control circuit. First, so that we can make informed predictions about the expected clocking frequency of our circuits. Second, so that we can identify critical paths in our circuit. Third, so that we can develop our intuition about the operation of these complex circuits.

To facilitate a discussion of the timing behavior of the datapath and control circuit, lets examine the circuit from last lecture, the search algorithm for a minimum shown below.

Like we did in our last lecture, we will examine the time its takes, starting from a positive clock edge, to get the next state setup on the flip flops in the FSM. The positive clock edge has two primary effects: It causes the FSM to transition into a new state and it causes the registers in the datapath to latch new values. The propagation delay of the flip flops is referred to as Tp(A). Since the datapath requires a valid control word before it can begin, the critical path includes the output equation logic.

The D flip flops which store the state of the control unit are the input of the OEs. The delay between the application of a valid Q to when the OEs assert their new values is referred to as Tp(B).

The OEs of the FSM are the control word to the datapath telling the elements in the datapath what operation to perform. Sequential logic components do not actually perform their instructed operations until the next clock edge arrives. On the other hand, combinational logic components perform their operations immediately. It is easy to construct datapath instances where the control word effects the status input to the control unit. For example, the control word selects an input of a mux, whose output is routed to a comparator, whose status output is sent to the control unit. Thus, the combinational logic is on the critical path because its delay constrains the maximum clocking frequency. The time difference between the application of a valid control word to the datapath and the status input to the control unit becoming valid is referred to as Tp(C).

The status input to the control unit are routed to the MIE logic. The delay between the status inputs becoming valid and the MIEs becoming valid is referred to as Tp(D).

Once the memory inputs have stabilized, they must be allowed some setup time before the next clock edge. The setup time is referred to as Tp(E).

VHDL Instantiation

There are two important points that need to be made regarding VHDL instantiation.

The term "binding" is used to refer to the technique of assigning signals in the top-level entity (caller) to the signals in the instance. Up till now we have been using a verbose binding technique where the signals in the top-level and instance are explicitly related. For example, in lecture 10, we used the following instantiation to bind the signals of a generic counter to the testbench.
   uut: lec10 
        Generic map(5)
        PORT MAP (
          clk => clk,
          reset => reset,
          crtl => crtl,
          D => loadInput,
          Q => cntOutput);
In this case, the signals clk, reset, crtl, D and Q were defined inside the lec10 component. The signals clk, reset, crtl, loadInput, and cntOutput were defined as signals in the higher-level testbench. However, we could shorten this instantiation by using the default binding calling convention shown in the code below.
   uut: lec10 
        Generic map(5)
        PORT MAP (clk, reset, crtl, loadInput, cntOutput);
The important point to make here is that when you use the default binding, the order of the signals must match the exact same order that is defined in the entity description. This generates a more compact instantiation statement.

Unused outputs and the OPEN keyword
There will be cases where you have a component that you would like to instantiate, but do not need all the output signals. A good example is given by the comparator below.
entity compare is
    generic(N: integer := 4);
    port(x,y : in unsigned(N-1 downto 0);
         g,l,e: out std_logic);
end compare;
Note that g=1 when x > y, and l=1 when x < y, and e=1 when x=y. If you wanted to know if 2 signals (say A and B) were equal to one another but did not care about less and greater, then you could use the following component instantation.
    example: compare port map (A,B,OPEN, OPEN, equal);
This notifies the synthesis engine that it can remove the logic associated with any of the OPEN signals and reduce the resources used on the FPGA.

Subvectors and concatenation
There are times when we will need to rebuild a std_logic_vector from pieces of other vectors. In order to accomplish this you will need to understand subvectors and the concatenation operation. Since vector is defined as signal(7 downto 0), you can replace the limits with anything in between to get a small subvector. So, for example, you could ask for signal(5 downto 2) for a 4-bit sub-vector of signal.
The concatination operation, &, is a way to "glue" two vectors together. So for example, to build a 8-bit vector you could legally write in VHDL signal(3 downto 1) & signal (7 downto 3);
These two concepts come together in the shift register used in the lecture 11 code, which contains the following line of VHDL code.
shiftReg <= kbData & shiftReg (10 downto 1);                    

Keyboard serial to parallel converter

Nomenclature: PS/2 Keyboard
Data Input: none
Data Output: 1-bit data, nominally logic 1
Control: none
Status: none
Others: 1-bit clk, nominally logic 1
Physical Input: key press and key release events
Physical Output: none
Behavior: When a key is pressed, its 8-bit make code is transmitted. When a key is released, an 8-bit break code is transmitted, immediately followed by the key's 8-bit scan code.
While the table implies a keyboard is an output-only device, the truth is the clock and data lines are open collector signals. In other words, the clock and data lines can safely be manipulated by the external world to configure a keyboard. A common example of such bidirectional communication occurs every time the Caps Lock key is pressed on a keyboard. When this happens, the keyboard sends the Caps Lock scan code to the PC and the PC in return writes a Toggle Caps Lock LED command to the keyboard. Since the keyboard scan code reader does not write to the keyboard, it assumes that the clock and data signals are outputs from the keyboard. When a keyboard key is pressed, the keyboard sends one packet of information as shown at the top of Figure 9.14. The 8-bit data contained in this make code is the scan code of the key pressed. The relationship between the keys and their scan codes is not at all obvious and is not based on ASCII. The exact codes are immaterial to the discussion; the curious reader can perform a quick Internet search on PS/2 keyboard scan codes to get a complete listing. When a key is released, two packets are transmitted as shown at the top of Figure 9.14. The break code is almost always equal to 0xF0. The final packet is the scan code of the released key.

While there is a scan code for "a" key, there is not a scan code for "A". The device reading the keyboard interprets the make code for shift, and then sees a make code for "a". From this, the device reading the keyboard should understand that the user wants a capital "A". More than likely, the user will release the "a", first causing its break code and scan code to be transmitted, followed by the break and scan code for the "shift" key. Each of these packets consists of 11 bits as shown in the lower half of Figure 9.14. The data from the keyboard is always valid on the falling edge of the clock signal. The keyboard asserts new data on or around the rising edge of the clock. The 11-bit data packet always begins with a start bit equal to 0. Following the start bit are 8-bits of data, transmitted least-significant bit first. Following the data bits is an odd-parity bit, whose value is set by the keyboard so that the total number of 1s transmitted in the eight data bits plus the parity bit equals an odd number. For example, if the eight data bits are 01100011, then the parity bit would equal 1 so that the total number of 1s would be an odd number, in this case 5. By adding some additional circuitry, the parity bit can be used to detect errors in transmission. Following the parity bit, the final bit of the data packet, the stop bit, is sent and is always equal to 1.
Nomenclature: Keyboard scan code reader
Data Input: 1-bit kd data, nominally logic 1 1-bit kd clk, nominally logic 1
Data Output: 8-bit scan code
Control: none
Status: 1-bit busy, nominally logic 0
Others: 1-bit clk, nominally logic 1
Behavior: Interprets the PS/2 keyboard clk and data signal from a keypress event and outputs the associated scan code. The busy signal goes high when the first data bit arrives and stays high until the last data bit is received. Busy is low only when there is a valid scan code on the output.
Looking at the timing diagram and the description above, I came up with the following algorithm.
1. while(1) {
2.     busy=0;
3.     while (kb_clk == 1);
4.     busy=1;
5.     for (count=0 count<33; count++) {
6.         while(kb_clk == 1);
7.         shift = (shift << 1) | kb_data;
8.         while(kb_clk == 0);
9.     } // end for
10.     scan = shift[9-2]
11. } // end while 1
Now lets build the datapath and control using the technique learned in lecture 10. Your homework is to build the control unit for the keyboard scancode reader.