Search code examples
compiler-errorsvhdllattice-diamond

VHDL - "Net pwr is constantly driven"


I am attempting to learn VHDL and as an exercise I am trying to construct a very simple serial port that uses RS-232 style signalling (8N1 format).

Here's the code for both of the vhdl files in the small project...

"glue.vhd"... (top level module)

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use ieee.std_logic_unsigned.all;
library MACHXO2;
use MACHXO2.components.all;

entity Glue is
    port(
        tx : out std_logic := '1' --idle high
        );
end entity Glue;

architecture behavioural of Glue is
    SIGNAL clk  : STD_LOGIC;
    signal divider : std_logic_vector(23 downto 0);

--internal oscillator
    COMPONENT OSCH
      GENERIC(
            NOM_FREQ: string
            );
      PORT( 
            STDBY    : IN  STD_LOGIC;
            OSC      : OUT STD_LOGIC;
            SEDSTDBY : OUT STD_LOGIC);
    END COMPONENT;
begin
--internal oscillator
   OSCInst0: OSCH
      GENERIC MAP (NOM_FREQ  => "3.69")
      PORT MAP (STDBY => '0', OSC => clk, SEDSTDBY => OPEN);

    ser : entity SerialTX
    port map (baud_clk => divider(5),
            byte_to_transmit => "00101001",
            transmit_now => divider(16),
            busy => OPEN,
            serial_out => tx);

    clocker : process (clk)
    begin
        IF(clk'event and clk='1') then
            divider <= divider + 1;
        END IF;
    end process clocker;

end architecture behavioural;

SerialTX.vhd... (invoked by glue.vhd)

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity SerialTX is
    port (
        baud_clk         : in  std_logic;
        byte_to_transmit : in  std_ulogic_vector(7 downto 0); --the byte that we want to transmit
        transmit_now     : in  std_logic;                    --a rising edge causes the byte to be sent out
        busy             : out std_logic;                    --wait for this to go low before transmiting more data
        serial_out       : out std_logic                     --the RS232 serial signal
        );
end SerialTX;

architecture behavioural of SerialTX is
    signal bit_buf : unsigned(9 downto 0); --(STOP bit) & (8 data bits) & (START bit)
    signal internal_busy : std_logic := '0';
begin
    busy <= internal_busy;  

    initialise_transmit : process(transmit_now, internal_busy) is
    begin
        if(transmit_now'event and (transmit_now = '1')) then
            if((internal_busy = '0')) then
                internal_busy <= '1'; --causes the "transmit_bits" process below to begin shifting out bits
                bit_buf <= unsigned('1' & byte_to_transmit & '0'); --latch in the byte to our internal copy
            end if;
        end if;
    end process initialise_transmit;    

    transmit_bits : process(internal_busy, baud_clk) is
        variable bit_counter : integer range 0 to 10 := 0;
    begin
        if(baud_clk'event and (baud_clk = '1')) then
            if(internal_busy = '1') then
                serial_out <= bit_buf(0);
                bit_buf <= bit_buf srl 1;
                bit_counter := bit_counter + 1;

                if(bit_counter = 10) then
                    internal_busy <= '0'; --finished sending
                    bit_counter := 0;
                end if;
            end if;
        end if;            -- ------------------------------ERROR HERE
    end process transmit_bits;
end behavioural;

The VHDL code that uses this module provides it with a baud-rate clock, the 8 bits of data to send and a rising edge to signal that the transmission should begin.

To test this I will attach a logic analyser to the "tx" pin to see the output from the serial signal. I've hard-coded the byte to be the letter 'A' (000101001) so I can prove that the basic concept works.

The problem... The toolchain (Lattice Diamond 3.9) fails to synthesize this design as it stands, so clearly I have made a mistake in the structure of the objects.

Individually the two files both have no syntax warnings or errors at all. There are no other VHDL files in the project besides the built-in dependencies provided by the Lattice and IEEE libraries.

The output from running the "Lattice Synthesis Engine" process is as follows...

Analyzing Verilog file C:/lscc/diamond/3.9_x64/ispfpga/userware/NT/SYNTHESIS_HEADERS/machxo2.v. VERI-1482
Compile design.
Compile Design Begin
INFO - The default VHDL library search path is now "C:/Users/XXXXXXXXXXXX.XXXXXXXXXXXX/Documents/Lattice/impl1". VHDL-1504
Analyzing VHDL file c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/serialtx.vhd. VHDL-1481
INFO - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/serialtx.vhd(5): analyzing entity serialtx. VHDL-1012
INFO - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/serialtx.vhd(15): analyzing architecture behavioural. VHDL-1010
unit Glue is not yet analyzed. VHDL-1485
Analyzing VHDL file c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/glue.vhd. VHDL-1481
INFO - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/glue.vhd(8): analyzing entity glue. VHDL-1012
INFO - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/glue.vhd(14): analyzing architecture behavioural. VHDL-1010
unit Glue is not yet analyzed. VHDL-1485
WARNING - Net pwr has following drivers :
unit Glue is not yet analyzed. VHDL-1485
c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/glue.vhd(8): executing Glue(behavioural)

WARNING - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/glue.vhd(12): replacing existing netlist Glue(behavioural). VHDL-1205
Top module name (VHDL): Glue
Last elaborated design is Glue(behavioural)
Loading NGL library 'C:/lscc/diamond/3.9_x64/ispfpga/xo2c00a/data/xo2alib.ngl'...
Loading NGL library 'C:/lscc/diamond/3.9_x64/ispfpga/xo2c00/data/xo2clib.ngl'...
Loading NGL library 'C:/lscc/diamond/3.9_x64/ispfpga/mg5g00/data/mg5glib.ngl'...
Loading NGL library 'C:/lscc/diamond/3.9_x64/ispfpga/or5g00/data/orc5glib.ngl'...
Loading device for application map from file 'xo2c1200.nph' in environment: C:/lscc/diamond/3.9_x64/ispfpga.
Package Status:                     Final          Version 1.42.
Top-level module name = Glue.
WARNING - Initial value found on net tx will be ignored due to unrecognized driver type
WARNING - Net pwr has following drivers :
     instance i2

     instance internal_busy_28



ERROR - c:/users/XXXXXXXXXXXX.XXXXXXXXXXXX/documents/lattice/serialtx.vhd(45): net pwr is constantly driven from multiple places at instance internal_busy_28, on port q. VDB-1000
Done: error code 2

"net pwr is constantly driven from multiple places" on line 45 (indicated by a comment "ERROR HERE" in the code listing).

I don't understand what is wrong here, to my inexperienced eye it looks like the internal_busy signal is low until driven high after it gets a rising edge on transmit_now.

What am I doing wrong?


Solution

  • The error message is not very helpful, but looking at your SerialTx.vhd file, you have driven the signal internal_busy from two different processes. A signal can only be driven in one process in order for the design to be synthesis-eligible.

    Another error I can see is here: tx : out std_logic := '1' --idle high. This does not do what you think it does. You can set an initial value for a signal where its driver is, but setting such a value at some other point in the hierarchy does not do anything. If you need a signal to idle in a certain state, you must write code that puts the signal in that state when it is idle.

    It is also better to replace clock detection conditions such as baud_clk'event and (baud_clk = '1') with rising_edge(baud_clk).