Tuesday, June 26, 2012

Mixing VHDL and verilog modules

INTRO
I have successfully been able to mix both VHDL modules and Verilog modules together.  Honestly it is a lot easier then I had thought it would be.  Since I could not find detailed examples of this phenomenon, I had to experiment with how it would work out.  The examples that I found were all wrong, but they gave enough of a hint to figure it out on my own.  I'm quite sure there are many people that need to know this so if you are here, you are in a good place.

ABSTRACT
A simple Verilog top module was crafted as a 2 bit full adder.  The internal components would be a verilog one bit adder and VHDL one bit adder.  They got connected in the verilog top module and were successfully testbenched and synthesized.  Did I mention that I used a testbench written in vhdl to test the 2 bit FA verilog top module?

Also as a second pass, I created a simple VHDL top module that was crafted as a 2 bit full adder.  The internal components would ALSO be a verilog 1 bit full adder and vhdl 1 bit full adder.  They got connected in the vhdl top module and they successfully testbenched and synthesized.

CODE
Below is the code that was used to create the described 2 bit adders.  Hopefully it will demonstrate how easy it is to go from one language to the other.
=====================
-- 1 bit FA in VHDL
--------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity FA_VHDL is
    Port ( A,B,CIN : in  STD_LOGIC;
           COUT,S : out  STD_LOGIC);
end FA_VHDL;
architecture Behavioral of FA_VHDL is
begin
--concurrent implementation of a 1 bit full adder.
--Statements outside of a process are considered concurrent
S <= A xor B xor CIN;
COUT <= (A and B) or (A and CIN) or (B and CIN);

--Alternative implementation with a use of sensitivity list.
--This block will only execute when the items in the sensitivity list change
-- FA : process (A,B,CIN)
-- begin
-- S <= A xor B xor CIN;
-- COUT <= (A and B) or (A and CIN) or (B and CIN);
-- end process;
end Behavioral;



=====================
--1 bit FA in verilog
--------------------------------

`timescale 1ns / 1ps
module FA_v(
A,B,CIN,
COUT,S);
//------------
input A,B,CIN;
output COUT, S;
// reg COUT,S; // uncomment if using "always block"
//----
//This makes the logic happen continuously
assign S = A ^ B ^ CIN;
assign COUT =  (A & B)  | (A & CIN) | (B & CIN);

//Alternative implementation with a use of sensitivity list.
//This "always block" will only execute when the items in the sensitivity list change
// always @ (A or B or CIN)
// begin
// S <= A ^ B ^ CIN;
// COUT <=  (A & B)  | (A & CIN) | (B & CIN);
// end
endmodule


=====================
--2 bit FA in verilog with internal components: 1 bit verilog fa and 1 bit vhdl fa
--------------------------------

`timescale 1ns / 1ps
`default_nettype none

module Verilog_2bit_adder(
A2b,B2b,CIN2b,
COUT2b,S2b
);
//define pins
input [1:0] A2b,B2b;
input CIN2b;
//define ports
output COUT2b;
output [1:0] S2b;
//Specify internal wire
wire carry_w;
FA_v verilog_full_adder(
.A    (A2b[0]), // ".A" specifies the Pin of the component. "A2b[0]" specifies the thing that is connecting to that pin
.B    (B2b[0]),
.CIN  (CIN2b),
.COUT (carry_w),
.S    (S2b[0])
); //for bit0
FA_VHDL VHDL_full_adder(
.A    (A2b[1]),
.B    (B2b[1]),
.CIN  (carry_w),
.COUT (COUT2b),
.S    (S2b[1])
);//for bit1
endmodule


=====================
--2 bit FA in VHDL with internal components: 1 bit verilog fa and 1 bit vhdl fa
--------------------------------

library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;

entity VHDL_2bit_adder is
   port ( A2b    : in    std_logic_vector (1 downto 0);
          B2b    : in    std_logic_vector (1 downto 0);
          CIN2b  : in    std_logic;
          COUT2b : out   std_logic;
          S2b    : out   std_logic_vector (1 downto 0));
end VHDL_2bit_adder;

architecture BEHAVIORAL of VHDL_2bit_adder is
   signal carry_s : std_logic;
   component FA_v
      port ( A    : in    std_logic;
             B    : in    std_logic;
             CIN  : in    std_logic;
             COUT : out   std_logic;
             S    : out   std_logic);
   end component;
 
   component FA_VHDL
      port ( A    : in    std_logic;
             B    : in    std_logic;
             CIN  : in    std_logic;
             COUT : out   std_logic;
             S    : out   std_logic);
   end component;
 
begin
   verilog_full_adder : FA_v
      port map (
               A=>A2b(0),
               B=>B2b(0),
               CIN=>CIN2b,
               COUT=>carry_s,
               S=>S2b(0)
);
 
   VHDL_full_adder : FA_VHDL
      port map (
               A=>A2b(1),
               B=>B2b(1),
               CIN=>carry_s,
               COUT=>COUT2b,
               S=>S2b(1)
);
 
end BEHAVIORAL;




=====================
--vhdl test bench
--------------------------------

-- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY VHDL_two_bit_adder_TB IS
END VHDL_two_bit_adder_TB;

ARCHITECTURE behavior OF VHDL_two_bit_adder_TB IS
    -- Component Declaration for the Unit Under Test (UUT)
    --COMPONENT Verilog_2bit_adder --testing uncomment to test verilog
COMPONENT VHDL_2bit_adder
    PORT(
         A2b : IN  std_logic_vector(1 downto 0);
         B2b : IN  std_logic_vector(1 downto 0);
         CIN2b : IN  std_logic;
         COUT2b : OUT  std_logic;
         S2b : OUT  std_logic_vector(1 downto 0)
        );
    END COMPONENT;
   --Inputs
   signal A2b : std_logic_vector(1 downto 0) := (others => '0');
   signal B2b : std_logic_vector(1 downto 0) := (others => '0');
   signal CIN2b : std_logic := '0';

  --Outputs
   signal COUT2b : std_logic;
   signal S2b : std_logic_vector(1 downto 0);

signal clock : std_logic := '0';
   constant clock_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)
--      uut: Verilog_2bit_adder PORT MAP ( --uncomment if using verilog component
        uut: VHDL_2bit_adder PORT MAP ( -- uncomment if using VHDL component
          A2b => A2b,
          B2b => B2b,
          CIN2b => CIN2b,
          COUT2b => COUT2b,
          S2b => S2b
        );

   -- Clock process definitions
   clock_process :process
   begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin
      -- hold reset state for 100 ns.
      wait for 100 ns;
A_loop: for A in 0 to 3 loop
B_loop: for B in 0 to 3 loop
CIN_loop: for CIN in 0 to 1 loop
A2b <= conv_std_logic_vector(A, 2);
B2b <= conv_std_logic_vector(B, 2);
if CIN = 1 then
CIN2b <= '1';
else
CIN2b <= '0';
end if;
wait for clock_period;
assert (A+B+CIN = conv_integer(COUT2b&S2b)) report "This isn't right" severity error;
end loop CIN_loop;
end loop B_loop;
end loop A_loop;
      -- insert stimulus here

      wait;
   end process;

END;









No comments:

Post a Comment