Featured post

Top 5 books to refer for a VHDL beginner

VHDL (VHSIC-HDL, Very High-Speed Integrated Circuit Hardware Description Language) is a hardware description language used in electronic des...

Tuesday, 13 December 2011

Finite State Machine (FSM) Coding In Verilog

There is a special Coding style for State Machines in VHDL as well as in Verilog. Let us consider below given state machine which is a “1011” overlapping sequence detector. Output becomes ‘1’ when sequence is detected in state S4 else it remains ‘0’ for other states.
fsm_seq_detector
Verilog Code for FSM:
// 4-State Moore state machine
// A Moore machine's outputs are dependent only on the current state.
// The output is written only when the state changes.  (State
// transitions are synchronous.)
module seq_dect
(
    input    clk, data_in, reset,
    output reg  data_out
);
    // Declare state register
    reg        [2:0]state;
    // Declare states
    parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4;

    // Determine the next state
    always @ (posedge clk or posedge reset) begin
        if (reset)
            state <= S0;
        else
            case (state)
                S0:
                    if (data_in)
                        state <= S1;
                    else
                        state <= S0;
                S1:
                    if (data_in)
                        state <= S1;
                    else
                        state <= S2;
                S2:
                    if (data_in)
                        state <= S3;
                    else
                        state <= S2;
                S3:
                    if (data_in)
                        state <= S4;
                    else
                        state <= S2;
                S4:
                    if (data_in)
                        state <= S1;
                    else
                        state <= S2;
            endcase // case (state)
    end // always @ (posedge clk or posedge reset)
    // Output depends only on the state
    always @ (state) begin
        case (state)
            S0:
                data_out = 1'b0;
            S1:
                data_out = 1'b1;
            S2:
                data_out = 1'b0;
            S3:
                data_out = 1'b1;
            S4:
                data_out = 1'b1;               
            default:
                data_out = 1'b0;
        endcase // case (state)
    end // always @ (state)

endmodule // moore_mac




Finite State Machine (FSM) Coding In VHDL

There is a special Coding style for State Machines in VHDL as well as in Verilog.
Let us consider below given state machine which is a “1011” overlapping sequence detector. Output becomes ‘1’ when sequence is detected in state S4 else it remains ‘0’ for other states.
fsm_seq_detector
 VHDL Code for FSM:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--Sequence detector for detecting the sequence "1011".
--Overlapping type.
entity seq_det is
port(   clk   : in std_logic;      --clock signal
        reset : in std_logic;      --reset signal
        S_in  : in std_logic;      --serial bit Input sequence   
        S_out : out std_logic);    -- Output        
end seq_det;
architecture Behavioral of seq_det is
--Defines the type for states in the state machine
type state_type is (S0,S1,S2,S3,S4);
--Declare the signal with the corresponding state type.
signal Current_State, Next_State : state_type;
begin
-- Synchronous Process
process(clk)
begin
    if( reset = '1' ) then                 --Synchronous Reset
        Current_State <= 'S0';
    elsif (clk'event and clk = '1') then   --Rising edge of Clock
        Current_State <= Next_State
    end if;
end process;
-- Combinational Process
Process(Current_State, S_in)
    begin
        case Current_State is
            when S0 =>                     
                S_out <= '0';
                if ( s_in = '0' ) then
                    Next_State <= S0;
                else   
                    Next_State <= S1;
                end if;
            when S1 =>
                S_out <= '1';  
                if ( S_in = '0' ) then
                    Next_State <= S3;
                else   
                    Next_State <= S2;
                end if;
            when S2 =>
                S_out <= '0';  
                if ( S_in = '0' ) then
                    Next_State <= S0;
                else   
                    Next_State <= S3;
                end if;
            when S3 =>
                S_out <= '1';  
                if (S_in = '0' ) then
                    Next_State <= S2;
                else   
                    Next_State <= S4;
                end if;
            when S4 =>
                S_out <= '1';  
                if ( S_in = '0' ) then
                    Next_State <= S2;
                else   
                    Next_State <= S1;
                end if;
            when others =>
                NULL;
        end case;
    end if;
end process;   










Thursday, 8 December 2011

Verilog Design With VHDL Testbench

// Two bit adder design in Verilog

module adder (a,b,carry,sum);
   //Port Declarations
   input [1:0] a;
   input [1:0] b;
   output [1:0] sum;
   output  carry;
   //Drivers for output signals
   reg [1:0]  sum;
   reg   carry;  
   // combination Logic for adder
   always @ (a or b) //Sensitive to inputs a or b
     begin
         {carry,sum} = a+b; 
     end
endmodule

 

--VHDL test bench for Verilog adder

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity ADDER_TB is      --Top level entity dosen't have any port
end ADDER_TB;

architecture TB of ADDER_TB is

    component ADDER is
    port( A: in std_logic_vector(1 downto 0);
  B: in std_logic_vector(1 downto 0); 
  carry: out std_logic;     
  sum: out std_logic_vector(1 downto 0)
    );
    end component;

    signal A, B: std_logic_vector(1 downto 0);
    signal carry: std_logic;
    signal sum:  std_logic_vector(1 downto 0);

    begin
        DUT: ADDER port map (A, B, carry, sum);
    process  
variable err_cnt: integer :=0;
    begin -- Generating test vectors
-- case 1
A <= "00";      
B <= "00";
wait for 10 ns;
assert (sum="00") report "Sum Error!" severity error;
assert (carry='0') report "Carry Error!" severity error;
if (sum/="00" or carry/='0') then
     err_cnt:=err_cnt+1;
end if;
  -- case 2  
A <= "11";
B <= "11";
wait for 10 ns;  
assert (sum="10") report "Sum Error!" severity error; 
assert (carry='1') report "Carry Error!" severity error;
if (sum/="10" or carry/='1') then
     err_cnt:=err_cnt+1;
end if;
-- case 3
A <= "01";
B <= "10";
wait for 10 ns;  
assert (sum="11") report "Sum Error!" severity error; 
assert (carry='0') report "Carry Error!" severity error;
if (sum/="11" or carry/='0') then
     err_cnt:=err_cnt+1;
end if;
-- case 4
A <= "10";
B <= "01";
wait for 10 ns;   
assert (sum="11") report "Sum Error!" severity error; 
assert (carry='0') report "Carry Error!" severity error;
if (sum/="11" or carry/='0') then
     err_cnt:=err_cnt+1;
end if;
-- case 5
A <= "01";
B <= "01";
wait for 10 ns;
assert (sum="10") report "Sum Error!" severity error;
assert (carry='0') report "Carry Error!" severity error;
if (sum/="10" or carry/='0') then
     err_cnt:=err_cnt+1;
end if;
-- summary of testbench
if (err_cnt=0) then
     assert false
     report "Test completed successfully for adder!"
     severity note;
else
     assert true
     report "ERROR - Expected and received results are wrong"
     severity error;
end if;
wait;
    end process;
end TB;

VHDL Design With Verilog Testbench

--VHDL Design for 4:1 multiplexor

library ieee;
use ieee.std_logic_1164.all;
entity Mux is
  port(I3  : in  std_logic_vector(2 downto 0);
        I2 : in  std_logic_vector(2 downto 0);
        I1 : in  std_logic_vector(2 downto 0);
        I0 : in  std_logic_vector(2 downto 0);
        S  : in  std_logic_vector(1 downto 0);
        O  : out std_logic_vector(2 downto 0)
        );
end Mux;
architecture behv1 of Mux is
begin
  process(I3, I2, I1, I0, S)
  begin
    -- use case statement
    case S is
      when "00"   => O <= I0;
      when "01"   => O <= I1;
      when "10"   => O <= I2;
      when "11"   => O <= I3;
      when others => O <= "ZZZ";
    end case;
  end process;
end behv1;

 

//Verilog Test Bench for 4:1 VHDL multiplexer

module mux_tb (i3,i2,i1,i0,s,o);
   input  [2:0] o;
   output [2:0] i3;
   output [2:0] i2;
   output [2:0] i1;
   output [2:0] i0;
   output [1:0]  s;
   //Drivers for output
   reg [2:0] i3;
   reg [2:0] i2;
   reg [2:0] i1;
   reg [2:0] i0;
   reg [1:0] s;
   //Error counter
   integer   error_count;
   //Generatiin test cases
   initial
     begin
error_count = 0;
//Assigning different values for different signals
i3 = 3'h4;
i2 = 3'h7;
i1 = 3'h0;
i0 = 3'h5;
        //Case1
s  = 2'b00;
#2 //wait for 2 delays
if (o != 3'h5)
   begin
      $display("Error in case 1\n");
      error_count = error_count + 1;     
          end
        //Case2
s  = 2'b01;
#2 //wait for 2 delays
if (o != 3'h0)
   begin
      $display("Error in case 2\n");
      error_count = error_count + 1;     
          end
        //Case3
s  = 2'b10;
#2 //wait for 2 delay
if (o != 3'h7)
   begin
      $display("Error in case 3\n");
      error_count = error_count + 1;     
          end
        //Case4
s  = 2'b11;
#2 //wait for 2 delay
if (o != 3'h4)
   begin
      $display("Error in case 4\n");
      error_count = error_count + 1;     
          end
//Test Summary
if(error_count)
   $display("ERROR in the design");
else
   $display("All test cases are passed");
     end
//mux instantiation and port mapping
   mux one(.i3(i3),.i2(i2),.i1(i1),.i0(i0),.s(s),.o(o));
endmodule

Mixed Language Simulation In VLSI

Most of Simulation Tools supports mixed language project files and mixed language simulation. This enables you to include Verilog modules in a VHDL design, and vice versa. Some restrictions do apply:

  • Mixing VHDL and Verilog is restricted to the module instance or component only. A VHDL design can instantiate Verilog modules and a Verilog design can instantiate VHDL components. Any other kind of mixing between VHDL and Verilog is not supported.
  • A Verilog hierarchical reference cannot refer to a VHDL unit nor can a VHDL expanded/selected name refer to a Verilog unit.
  • Only a small subset of VHDL types, generics and ports are allowed on the boundary to a Verilog module. Similarly, a small subset of Verilog types, parameters and ports are allowed on the boundary to VHDL design unit.
  • Component instantiation-based default binding is used for binding a Verilog module to a VHDL design unit. Specifically, configuration specification, direct instantiation and component configurations are not supported for a Verilog module instantiated inside a VHDL design unit.

Examples:

1. VHDL Design With Verilog Testbench

2. Verilog Design With VHDL Testbench

Tuesday, 29 November 2011

Verilog Always Block

Contains one or more statements (procedural assignments, task enables, if, case and loop statements), which are executed repeatedly throughout a simulation run, as directed by their timing controls.

Syntax
always
    Statement

Or

always
    begin
    Statements
    end

 

Where to use:
module
-<HERE>-endmodule

Rules for Using always Statement:
Only registers (reg, integer, real, time, realtime) may be assigned in an
always.

Every always starts executing at the start of simulation, and continues executing throughout simulation; when the last statement in the always is reached, execution continues from the top of the always.

  • An always containing more than one statement must enclose the statements in a begin-end or fork-join block.
  • An always with no timing controls will loop forever.

Synthesis:
always is one of the most useful Verilog statements for synthesis, yet an always is often unsynthesizable. For best results, code should be restricted to one of the following templates:

always @(Inputs) // All the inputs
begin
... // Combinational logic
end

always @(Inputs) // All the inputs
if (Enable)
begin
... // Latched actions
end

always @(posedge Clock) // Clock only
begin
... // Synchronous actions
end

always @(posedge Clock or negedge Reset)
// Clock and Reset only
begin
if (!Reset) // Test active level of asynchronous reset
... // Asynchronous actions
else
... // Synchronous actions
end // Gives flipflops + logic

Monday, 28 November 2011

Cyclic Redundancy Checking (CRC)

Error detection is an important part of communication systems when there is a chance of data getting corrupted. Whether it’s a piece of stored code or a data transmission, you can add a piece of redundant information to validate the data and protect it against corruption. Cyclic redundancy checking is a robust error-checking algorithm, which is commonly used to detect errors either in data transmission or data storage. In this multipart article we explain a few basic principles.

Modulo two arithmetic is simple single-bit binary arithmetic with all carries or borrows ignored. Each digit is considered independently. This article talks about how modulo two addition is equivalent to modulo two subtraction, and can be performed using an exclusive OR operation followed by a brief on Polynomial division where remainder forms the CRC checksum.
For example, we can add two binary numbers X and Y as follows:

10101001 (X) + 00111010 (Y) = 10010011 (Z)

From this example the modulo two addition is equivalent to an exclusive OR operation. What is less obvious is that modulo two subtraction gives the same results as an addition.
From the previous example let’s add X and Z:

10101001 (X) + 10010011 (Z) = 00111010 (Y)

In our previous example we have seen how X + Y = Z therefore Y = Z – X, but the example above shows that Z+X = Y also, hence modulo two addition is equivalent to modulo two subtraction, and can be performed using an exclusive OR operation.

In integer division dividing A by B will result in a quotient Q, and a remainder R. Polynomial division is similar except that when A and B are polynomials, the remainder is a polynomial, whose degree is less than B.

The key point here is that any change to the polynomial A causes a change to the remainder R. This behavior forms the basis of the cyclic redundancy checking.
If we consider a polynomial, whose coefficients are zeros and ones (modulo two), this polynomial can be easily represented by its coefficients as binary powers of two.

In terms of cyclic redundancy calculations, the polynomial A would be the binary message string or data and polynomial B would be the generator polynomial. The remainder R would be the cyclic redundancy checksum. If the data changed or became corrupt, then a different remainder would be calculated.

Although the algorithm for cyclic redundancy calculations looks complicated, it only involves shifting and exclusive OR operations. Using modulo two arithmetic, division is just a shift operation and subtraction is an exclusive OR operation.

Cyclic redundancy calculations can therefore be efficiently implemented in hardware, using a shift register modified with XOR gates. The shift register should have the same number of bits as the degree of the generator polynomial and an XOR gate at each bit, where the generator polynomial coefficient is one.

Augmentation is a technique used to produce a null CRC result, while preserving both the original data and the CRC checksum. In communication systems using cyclic redundancy checking, it would be desirable to obtain a null CRC result for each transmission, as the simplified verification will help to speed up the data handling.

Traditionally, a null CRC result is generated by adding the cyclic redundancy checksum to the data, and calculating the CRC on the new data. While this simplifies the verification, it has the unfortunate side effect of changing the data. Any node receiving the data+CRC result will be able to verify that no corruption has occurred, but will be unable to extract the original data, because the checksum is not known. This can be overcome by transmitting the checksum along with the modified data, but any data-handling advantage gained in the verification process is offset by the additional steps needed to recover the original data.


Augmentation allows the data to be transmitted along with its checksum, and still obtain a null CRC result. As explained before when obtain a null CRC result, the data changes, when the checksum is added. Augmentation avoids this by shifting the data left or augmenting it with a number of zeros, equivalent to the degree of the generator polynomial. When the CRC result for the shifted data is added, both the original data and the checksum are preserved.

In this example, our generator polynomial (x3 + x2 + 1 or 1101) is of degree 3, so the data (0xD6B5) is shifted to the left by three places or augmented by three zeros.

0xD6B5 = 1101011010110101 becomes 0x6B5A8 = 1101011010110101000.

Note that the original data is still present within the augmented data.
0x6B5A8 = 1101011010110101000
Data = D6B5 Augmentation = 000

Calculating the CRC result for the augmented data (0x6B5A8) using our generator polynomial (1101), gives a remainder of 101 (degree 2). If we add this to the augmented data, we get:

0x6B5A8 + 0b101 = 1101011010110101000 + 101
= 1101011010110101101
= 0x6B5AD

As discussed before, calculating the cyclic redundancy checksum for 0x6B5AD will result in a null checksum, simplifying the verification. What is less apparent is that the original data is still preserved intact.

0x6B5AD = 1101011010110101101
Data = D6B5 CRC = 101

The degree of the remainder or cyclic redundancy checksum is always less than the degree of the generator polynomial. By augmenting the data with a number of zeros equivalent to the degree of the generator polynomial, we ensure that the addition of the checksum does not affect the augmented data.

In any communications system using cyclic redundancy checking, the same generator polynomial will be used by both transmitting and receiving nodes to generate checksums and verify data. As the receiving node knows the degree of the generator polynomial, it is a simple task for it to verify the transmission by calculating the checksum and testing for zero, and then extract the data by discarding the last three bits.

Thus augmentation preserves the data, while allowing a null cyclic redundancy checksum for faster verification and data handling.