clash-lang / clash-compiler

Haskell to VHDL/Verilog/SystemVerilog compiler
https://clash-lang.org/
Other
1.44k stars 154 forks source link

"resetsynchronizer" is used but not declared #1565

Closed paddytheplaster closed 3 years ago

paddytheplaster commented 4 years ago

Hello again,

I am having some problems with a communication circuit. I suspect this is related to a clock issue. To make sure everything works properly, I just tried to compile the Blinker example and I got an error when I tried to compile the generated VHDL. (I just pulled the most recent development version from github.)

I downloaded the Blinker sources for the highest (1.0) Clash version on the tutorial site. This is how I got to the tutorial site.

https://clash-lang.org/ -> [Click Documentation] -> https://clash-lang.org/documentation/ -> [Click Tutorial] -> http://hackage.haskell.org/package/clash-prelude-1.2.4/docs/Clash-Tutorial.html

My quartus compiler gives:

Error (10482): VHDL error at blinker.vhdl(106): object "resetsynchronizer" is used but not declared
Error (10815): VHDL Scope error at blinker.vhdl(106): design unit "resetsynchronizer" is not visible in the present scope - you must refer to it with an expanded name such as "work.resetsynchronizer"
Error: Quartus Prime Analysis & Synthesis was unsuccessful. 2 errors, 1 warning
    Error: Peak virtual memory: 440 megabytes
    Error: Processing ended: Sun Nov  1 16:14:00 2020
    Error: Elapsed time: 00:00:16
    Error: Total CPU time (on all processors): 00:00:39
Error (293001): Quartus Prime Full Compilation was unsuccessful. 4 errors, 1 warning

(The blinker.hs in (git development) clash-compiler/examples/ also throws this error. Aren't the files in that directory unit tested?)

I note that clash still overwrites my .sdc file which has a 'derive_pll_clocks' statement in it.

Any suggestions?

Paddy

martijnbastiaan commented 4 years ago

Did you include resetsynchronizer.vhdl?

paddytheplaster commented 4 years ago

Hi Martijn,

No. I wasn't suspecting that. I started with 'Blinker.hs', and then ran 'clash --vhdl Blinker.hs'.

Should I have added the function? If yes, where do i find it, please? The latter may seem a silly question cause I can use find. However I don't want to have to run find every time I pull clash (and there's a chance the function has changed).

TIA

Paddy

paddytheplaster commented 4 years ago

Hi again.

I notice there is a file 'resetsynchronizer.vhdl' which is generated by clash. If I tell my quartus IDE it should consider it part of the project I get a different error. I may get back about that as it looks it's an error in the generated VHDL.

Regards,

Paddy

paddytheplaster commented 4 years ago

Did you include resetsynchronizer.vhdl?

Hi again,

First of all, IMO Clash should not cache by default as this is dangerous behaviour and may result in errors, which are difficult to find. I just happended to notice that Clash output Using cached result. When I run with -fclash-no-cache Clash generates some additional files which are needed to compile propoerly.

[nix-shell:~/Altera/Blinker-Clash-1.2.4]$ clash --vhdl Blinker.hs GHC: Parsing and optimising modules took: 2.798s GHC: Loading external modules from interface files took: 0.000s GHC: Parsing annotations took: 0.001s Clash: Parsing and compiling primitives took 0.088s GHC+Clash: Loading modules cumulatively took 3.275s Clash: Compiling Blinker.topEntity Clash: Using cached result for: Blinker.topEntity Clash: Total compilation took 3.285s

[nix-shell:~/Altera/Blinker-Clash-1.2.4]$ clash --vhdl Blinker.hs -fclash-no-cache GHC: Parsing and optimising modules took: 2.584s GHC: Loading external modules from interface files took: 0.000s GHC: Parsing annotations took: 0.001s Clash: Parsing and compiling primitives took 0.086s GHC+Clash: Loading modules cumulatively took 3.043s Clash: Compiling Blinker.topEntity Clash: Ignoring .manifest files Clash: Normalisation took 0.022s Clash: Netlist generation took 0.002s Clash: Total compilation took 3.186s

This now also generates a file altpllE588ED61A4853C9C.qsys. When I include it in my quartus project, my IDE want me to launch an IP upgrade tool. If I run the tool and automatically upgrade, everything compiles fine. When I execute the netlist it also works.

For me this workflow is extremely unsatisfactory as I compile the VHDL from the command line and it's not clear whether I should upgrade IP automatically. All I get is a "it no longer works" error and I have to get back to the Blinker example to check the workflow. Is there a way around this, please?

I now get a warning:

Critical Warning (332168): The following clock transfers have no clock uncertainty assignment. For more accurate results, apply clock uncertainty assignments or use the derive_clock_uncertainty command.
    Critical Warning (332169): From CLOCK_50 (Rise) to CLOCK_50 (Rise) (setup and hold)

I already mentioned Clash overwrites my .sdc file, which had a 'derive_clock_uncertainty' in it. Do I need to worry about this?

Regards,

Paddy

christiaanb commented 4 years ago

With regards to the "IP upgrade": I've been able to compile projects without doing the IP upgrade. Quartus only complains about it because we don't include the Quartus version string in the .qsys file; and I feel adding a flag to Clash to specify the Quartus version we're generating HDL for is taking it a bit far....

With regards to the .sdc file being overwritten, it's somewhat annoying to try to distinguish between the .sdc file clash previously generated from a user-provided .sdc file put in the same spot. It's probably best not to put any of your own files in the directories where Clash puts generated files.

alex-mckenna commented 4 years ago

@paddytheplaster, the SDC files generated by clash are always named <component>.sdc for any components that have them generated. If you name yours something else hopefully that should be fine as a workaround.

As for the issue with -fclash-cache, I think that should only be a problem when a blackbox is used which renders additional files (like the .qsys files for Altera/Intel clock gen). I think at the very least clash should print a warning if a cached result would render an additional file like that. It may also be reasonable to change -fclash-cache from a boolean flag to something more like -fclash-cache=Always|Auto|Never, where Auto never caches a component that uses a blackbox that renders other files for safety. Always and Never would preserve the current behaviour.

alex-mckenna commented 4 years ago

@paddytheplaster, I've been unable to reproduce the issue locally. From a clean environment when I run

cabal run -- clash --vhdl examples/Blinker.hs

I get the expected output, including the .qsys file for the altpll. I can also build with -fclash-edalize and then use edalize to build Blinker using quartus... Can you give any more info that might help me see if there's anything we can do: clash version, quartus version and commands etc.?

paddytheplaster commented 4 years ago

@paddytheplaster, I've been unable to reproduce the issue locally. From a clean environment when I run

cabal run -- clash --vhdl examples/Blinker.hs

I get the expected output, including the .qsys file for the altpll. I can also build with -fclash-edalize and then use edalize to build Blinker using quartus... Can you give any more info that might help me see if there's anything we can do: clash version, quartus version and commands etc.?

Hi Alex,

Maybe this is related to me using a "stale" project environment.

I pulled Clash from github yesterday and rebuilt. Quartus: 20.1.0 Build 711 06/05/2020 SJ Standard Edition.

Before I start, please let me know what you mean by clean: which quartus files should I include and which not. At the moment I'm providing: altpll50.* clash-generated files, blinker.qpf, blinker.qsf, blinker.sdc. If you could attach your environment for the Blinker project then that may also be useful.

I've never used edalize.

Regards,

Paddy

paddytheplaster commented 4 years ago

With regards to the "IP upgrade": I've been able to compile projects without doing the IP upgrade. Quartus only complains about it because we don't include the Quartus version string in the .qsys file; and I feel adding a flag to Clash to specify the Quartus version we're generating HDL for is taking it a bit far....

With regards to the .sdc file being overwritten, it's somewhat annoying to try to distinguish between the .sdc file clash previously generated from a user-provided .sdc file put in the same spot. It's probably best not to put any of your own files in the directories where Clash puts generated files.

Thanks.

Since I started working with the Blinker project again (since yesterday), I've had to upgrade a few times. I suspect this is related to the generated altpll files. Another problem is that it's not clear which Clash-generated files I should add to my quartus project. E.g. these files may change from Clash version to Clash version. It would help if a list of these files could be output (using some Clash flag e.g.).

I don't agree about the .sdc file. If a user already has a file, you can't just silently overwrite the user's file. If Clash insists on using a file with the same name as that of an existing file, the least thing Clash should do is bail out and request the user rename their file. BTW: I still don't know whether I can trust the newly generated .sdc file. Please see my previous post.

Using a different directory for user-defined/user-owned files is a reasonable solution.

Regards,

Paddy

paddytheplaster commented 4 years ago

@paddytheplaster, I've been unable to reproduce the issue locally. From a clean environment when I run

cabal run -- clash --vhdl examples/Blinker.hs

I get the expected output, including the .qsys file for the altpll. I can also build with -fclash-edalize and then use edalize to build Blinker using quartus... Can you give any more info that might help me see if there's anything we can do: clash version, quartus version and commands etc.?

Hi Alex,

Maybe this is related to me using a "stale" project environment.

I pulled Clash from github yesterday and rebuilt. Quartus: 20.1.0 Build 711 06/05/2020 SJ Standard Edition.

Before I start, please let me know what you mean by clean: which quartus files should I include and which not. At the moment I'm providing: altpll50.* clash-generated files, blinker.qpf, blinker.qsf, blinker.sdc. If you could attach your environment for the Blinker project then that may also be useful.

I've never used edalize.

Regards,

Paddy

I just noticed your post does provide enough context to define a clean project. I'll have a look (but this may take a while).

alex-mckenna commented 4 years ago

Hi Paddy,

Just to be completely precise because I wasn't before. My clean environment is just clash built from master, and no vhdl directory with previous compiler runs in. Hope that helps

paddytheplaster commented 4 years ago

Hi Paddy,

Just to be completely precise because I wasn't before. My clean environment is just clash built from master, and no vhdl directory with previous compiler runs in. Hope that helps

Hi Alex,

I managed to run 'clash --vhdl' on the Blinker.hs in the examples directory and that worked. (Running 'cabal' doesn't work for me.) I then started my quartus IDE, created a new project, added the generated files to it, and the first thing I needed to do was upgrade IP for the generated altplllXYZ file. After this I could compile the project without errors.

This leaves me with more questions. I'd be much obliged if you could answer:

* Previous tutorials required-user supplied altpll files. Are these no longer needed? If not, that looks great but it may be useful to explain this in some tutorial.
* I notice the input and output ports of the topEntity are annotated with pin names. This suggests you don't have to do this in your .qsf file. Is this correct? If yes, that'd be wonderful. Is this described somewhere?

Regards,

Paddy

alex-mckenna commented 4 years ago

Hi Paddy,

Clash generates the qsys file for at least the altpll black box now (it is possible to generate additional files in a black box, this should probably be added to the tutorial / docs). So no need to supply your own for blinker, but you may need to for any other IP you have.

As for setting pin names I believe you can do it with port annotations (I hope so, that's the name that sprung to mind.) Hopefully someone else knows where to find information about that

martijnbastiaan commented 4 years ago
  • I notice the input and output ports of the topEntity are annotated with pin names. This suggests you don't have to do this in your .qsf file. Is this correct? If yes, that'd be wonderful. Is this described somewhere?

I believe that's correct. It goes by different names for different HDLs, but for VHDL this would be the chip_pin synthesis attributes. You can set attributes using Clash.Annotations.SynthesisAttributes. As you've noticed, Blinker.hs is an example of a design using it.

paddytheplaster commented 4 years ago

Hi Paddy,

Just to be completely precise because I wasn't before. My clean environment is just clash built from master, and no vhdl directory with previous compiler runs in. Hope that helpsHi again,

If I use the Blinker.hs from the examples directory, I am pretty sure there are two separate problems, one of which is new. (When I wrote that I had tried examples/Blinker.hs earlier, I had just copied an pasted the code of the topEntity.)

The first problem is related to the pin name annotations. Clash generates names like 'Pin_A15', which aren't accepted. If I remove the annotations from Blinker.hs and hard code pin assignments like 'PIN_A15' in my .qsf file, the problem with the pin names disappears.

The second problem is related to the altpll-realted code. Quartus doesn't like it and insists I run the IP upgrade tool. Once that's done, Quartus inserts a line along the following in the .qsf file and all is hunky-dory. You can convince Quartus it should use the generated black box code for the altpll by adding a "QSYS_FILE" entry in the .qsf file. (See below.)

set_global_assignment -name QSYS_FILE altpllE588ED61A4853C9C.qsys

I solved the second problem by using the following script, which assumes there are no pin annotations in 'Blinker.hs'. The script assumes the .qsf file has proper pin assignment lines.

# ----------------------------%<---------------------------------
#!/bin/bash

set -x
set -e

function report( ) {
    echo "${1}" 1>&2
}

function abandon( ) {
    report "${1}"
    exit 1
}

EXT=hs
TOP=Blinker
SRC=./examples
SOURCE=${SRC}/${TOP}.${EXT}

[ -f ${SOURCE} ] \
  || abandon "${SOURCE} not found"

PROJECT=$( sed -n -e 's/^.*t_name *= *"\(.*\)" *$/\1/p' ${SOURCE} )

[ -n "${PROJECT}" ] \
  || abandon "Can't find 't_name=\"project name\"' on single line in ${SOURCE}"

QUARTUS_DIR=./vhdl/${TOP}/${PROJECT}

[ -d ${QUARTUS_DIR} ] \
  || abandon "Error: ${QUARTUS_DIR} does not exist !"

rm -rf ${QUARTUS_DIR}/*.qsys

clash --vhdl ${SOURCE} -fclash-no-cache

cd ${QUARTUS_DIR}

# =======================================================================
# Test if the project files needed exists
# =======================================================================
# .qsf

for EXT in qsf qpf sdc; do
    [ -e ${PROJECT}.${EXT} ] \
        || abandon "Error: ${PROJECT}.${EXT} not found"
done

# =======================================================================
# Sanitise .qsf file
# =======================================================================

echo >> ${PROJECT}.qsf
sed -i '$d' ${PROJECT}.qsf

# =======================================================================
# Adjust .qsys entry in project file
# =======================================================================

QSYS=$( ls *.qsys )

sed -i '/ QSYS_FILE /d' ${PROJECT}.qsf
echo "set_global_assignment -name QSYS_FILE ${QSYS}" >> ${PROJECT}.qsf

# =======================================================================
# Add VHDL files
# =======================================================================

# remove existing files from project file
SGA_SPELL="set_global_assignment -name VHDL_FILE "
sed -i '/\<[_A-Za-z][_A-Za-z]*.vhdl/d' ${PROJECT}.qsf

for FILE in *.vhdl; do
   echo "${SGA_SPELL} ${FILE}" >> ${PROJECT}.qsf
done

# =======================================================================
# Synthesis
# =======================================================================

report "> Beginning synthesis ..."
nice -n 19 \
quartus_map --read_settings_files=on --write_settings_files=off \
            ${PROJECT} -c ${PROJECT}
report "  > Synthesis done"

# =======================================================================
# Filter (Place and route)
# =======================================================================

report "> Filter (Place and route) ..."
nice -n 19 \
quartus_fit --read_settings_files=off --write_settings_files=off \
            ${PROJECT} -c ${PROJECT}
report "  > Filter done"

# =======================================================================
# Assembler (Generating programming files)
# =======================================================================

report "> Assembler (Generating programming files) ..."
quartus_asm --read_settings_files=off --write_settings_files=off \
            ${PROJECT} -c ${PROJECT}
report "  > Assembler done"

# =======================================================================
# TimeQuest Timing Analysis
# =======================================================================

report "> TimeQuest Timing Analysis ..."
nice -n 19 \
quartus_sta ${PROJECT} -c ${PROJECT}
report "  > TimeQuest Timing Analysis done"

# =======================================================================
# Program FPGA
# =======================================================================

SOF=${PROJECT}.sof
if [ ! -e ${SOF} ]; then
  SOF=output_files/${SOF}
  [ -e ${SOF} ] \
    || abandon "Can't find .sof file"
fi

nice -n 19 \
quartus_pgm -c USB-Blaster -m JTAG -o "p;${SOF}"
# ----------------------------%<---------------------------------

The following are the contents of blinker.qsf, which should be in '${QUARTUS_DIR}'.

# ----------------------------%<---------------------------------
#============================================================
# Build by Terasic System Builder
#============================================================
set_global_assignment -name FAMILY "Cyclone IV E"
set_global_assignment -name DEVICE EP4CE22F17C6
set_global_assignment -name TOP_LEVEL_ENTITY "blinker"
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 12.0
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Standard Edition"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "9:50:00 MAY 01,2020"
set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 256
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 6
#============================================================
# CLOCK
#============================================================
set_location_assignment PIN_R8 -to CLOCK_50
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK_50
#============================================================
# LED
#============================================================
set_location_assignment PIN_A15 -to LED[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0]
set_location_assignment PIN_A13 -to LED[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1]
set_location_assignment PIN_B13 -to LED[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2]
set_location_assignment PIN_A11 -to LED[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3]
set_location_assignment PIN_D1 -to LED[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4]
set_location_assignment PIN_F3 -to LED[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5]
set_location_assignment PIN_B1 -to LED[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6]
set_location_assignment PIN_L3 -to LED[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7]
#============================================================
# KEY
#============================================================
set_location_assignment PIN_J15 -to KEY[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[0]
set_location_assignment PIN_E1 -to KEY[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[1]
#============================================================
# End of pin assignments by Terasic System Builder
#============================================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"

set_global_assignment -name SDC_FILE blinker.sdc
set_global_assignment -name QSYS_FILE altpllE588ED61A4853C9C.qsys
set_global_assignment -name VHDL_FILE  blinker.vhdl
set_global_assignment -name VHDL_FILE  blinker_types.vhdl
set_global_assignment -name VHDL_FILE  resetsynchronizer.vhdl
# ----------------------------%<---------------------------------

Finally, I know it would have been better if I had attached the source code. However, for some reason my browser wouldn't let me select them because it didn't like their file extensions.

Regards,

Paddy

christiaanb commented 4 years ago

Using:

I cannot replicate your issues:

And as we can see from Pin Planner, the ports are assigned to the correct pins: image

This is the generated blinker.vhdl file that I get:

-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.blinker_types.all;

entity blinker is
  port(-- clock
       CLOCK_50 : in blinker_types.clk_input;
       KEY0     : in boolean;
       KEY1     : in std_logic;
       LED      : out std_logic_vector(7 downto 0));

  attribute altera_attribute : string;
  attribute altera_attribute of LED : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of KEY1 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of KEY0 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of CLOCK_50 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";

  attribute chip_pin : string;
  attribute chip_pin of LED : signal is "L3, B1, F3, D1, A11, B13, A13, A15";
  attribute chip_pin of KEY1 : signal is "E1";
  attribute chip_pin of KEY0 : signal is "J15";
  attribute chip_pin of CLOCK_50 : signal is "R8";
end;

architecture structural of blinker is
  -- examples/Blinker.hs:52:1-9
  signal \c$ds1_app_arg\      : blinker_types.rst_input;
  -- examples/Blinker.hs:52:1-9
  signal \c$$d(%,,%)_app_arg\ : blinker_types.rst_dom50;
  -- examples/Blinker.hs:52:1-9
  signal \c$ds_app_arg\       : blinker_types.tup3 := ( tup3_sel0_std_logic_vector => std_logic_vector'(x"01"), tup3_sel1_ledmode => "0", tup3_sel2_index_16650001 => to_unsigned(0,24) );
  signal result               : boolean;
  -- examples/Blinker.hs:98:1-8
  signal leds                 : std_logic_vector(7 downto 0);
  -- examples/Blinker.hs:98:1-8
  signal mode                 : blinker_types.ledmode;
  -- examples/Blinker.hs:98:1-8
  signal cntr                 : blinker_types.index_16650001;
  signal \c$case_alt\         : blinker_types.tup2;
  signal \c$app_arg\          : blinker_types.index_16650001;
  signal \c$app_arg_0\        : blinker_types.ledmode;
  signal \c$case_alt_0\       : blinker_types.ledmode;
  signal \c$app_arg_1\        : std_logic_vector(7 downto 0);
  signal \c$case_alt_1\       : std_logic_vector(7 downto 0);
  -- examples/Blinker.hs:52:1-9
  signal old                  : std_logic := '1';
  -- examples/Blinker.hs:52:1-9
  signal \$d(%,,%)\           : blinker_types.rst_dom50;
  -- examples/Blinker.hs:52:1-9
  signal clk50                : blinker_types.clk_dom50;
  -- examples/Blinker.hs:52:1-9
  signal ds1                  : blinker_types.tup2_0;
  signal result_selection_res : boolean;

begin
  \c$ds1_app_arg\ <= '1' when (not KEY0) = true else '0';

  \c$$d(%,,%)_app_arg\ <= '1' when (not ds1.tup2_0_sel1_boolean) = true else '0';

  -- register begin 
  cds_app_arg_register : process(clk50,\$d(%,,%)\)
  begin
    if \$d(%,,%)\ =  '1'  then
      \c$ds_app_arg\ <= ( tup3_sel0_std_logic_vector => std_logic_vector'(x"01"), tup3_sel1_ledmode => "0", tup3_sel2_index_16650001 => to_unsigned(0,24) );
    elsif rising_edge(clk50) then
      \c$ds_app_arg\ <= \c$case_alt\.tup2_sel0_tup3;
    end if;
  end process;
  -- register end

  result_selection_res <= old = ('0');

  result <= KEY1 = ('1') when result_selection_res else
            false;

  leds <= \c$ds_app_arg\.tup3_sel0_std_logic_vector;

  mode <= \c$ds_app_arg\.tup3_sel1_ledmode;

  cntr <= \c$ds_app_arg\.tup3_sel2_index_16650001;

  \c$case_alt\ <= ( tup2_sel0_tup3 => ( tup3_sel0_std_logic_vector => \c$app_arg_1\
                  , tup3_sel1_ledmode => \c$app_arg_0\
                  , tup3_sel2_index_16650001 => \c$app_arg\ )
                  , tup2_sel1_std_logic_vector => leds );

  with (cntr) select
    \c$app_arg\ <= to_unsigned(0,24) when x"FE0F10",
                   cntr + to_unsigned(1,24) when others;

  \c$app_arg_0\ <= \c$case_alt_0\ when result else
                   mode;

  with (mode) select
    \c$case_alt_0\ <= "1" when "0",
                      "0" when others;

  with (cntr) select
    \c$app_arg_1\ <= \c$case_alt_1\ when x"000000",
                     leds when others;

  with (mode) select
    \c$case_alt_1\ <= std_logic_vector(rotate_left(unsigned(leds),to_integer(to_signed(1,64)))) when "0",
                      not leds when others;

  LED <= \c$case_alt\.tup2_sel1_std_logic_vector;

  -- register begin 
  old_register : process(clk50,\$d(%,,%)\)
  begin
    if \$d(%,,%)\ =  '1'  then
      old <= '1';
    elsif rising_edge(clk50) then
      old <= KEY1;
    end if;
  end process;
  -- register end

  resetsynchronizer_d : entity resetsynchronizer
    port map
      ( result => \$d(%,,%)\
      , eta    => clk50
      , eta1   => \c$$d(%,,%)_app_arg\ );

  clk50 <= ds1.tup2_0_sel0_clk_dom50;

  altpll_block : block
    signal locked  : std_logic;
    signal plllock : boolean;
    signal pllout  : blinker_types.clk_dom50;
    component altpllE588ED61A4853C9C
      port ( clk    : in blinker_types.clk_input
           ; areset : in blinker_types.rst_input
           ; c0     : out blinker_types.clk_dom50
           ; locked : out std_logic );
    end component;

  begin
    altpll50 : component altpllE588ED61A4853C9C
      port map
        ( clk    => CLOCK_50
        , areset => \c$ds1_app_arg\
        , c0     => pllout
        , locked => locked );

    with (locked) select
      plllock <= true when '1',
                 false when others;

    ds1 <= ( tup2_0_sel0_clk_dom50 => pllout
           , tup2_0_sel1_boolean => plllock );

  end block;

end;
paddytheplaster commented 4 years ago

Using:

I cannot replicate your issues:

  • Clash doesn't generate any signals named Pin_A15
  • Although Quartus shows a big red "IP upgrade required": image This warning can be safely ignored, and Quartus builds the bitstream when I click Processing -> Start Compilation (Ctrl+L) in the menu.

And as we can see from Pin Planner, the ports are assigned to the correct pins: image

This is the generated blinker.vhdl file that I get:

-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.blinker_types.all;

entity blinker is
  port(-- clock
       CLOCK_50 : in blinker_types.clk_input;
       KEY0     : in boolean;
       KEY1     : in std_logic;
       LED      : out std_logic_vector(7 downto 0));

  attribute altera_attribute : string;
  attribute altera_attribute of LED : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of KEY1 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of KEY0 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";
  attribute altera_attribute of CLOCK_50 : signal is "-name IO_STANDARD ""3.3-V LVTTL""";

  attribute chip_pin : string;
  attribute chip_pin of LED : signal is "L3, B1, F3, D1, A11, B13, A13, A15";
  attribute chip_pin of KEY1 : signal is "E1";
  attribute chip_pin of KEY0 : signal is "J15";
  attribute chip_pin of CLOCK_50 : signal is "R8";
end;

architecture structural of blinker is
  -- examples/Blinker.hs:52:1-9
  signal \c$ds1_app_arg\      : blinker_types.rst_input;
  -- examples/Blinker.hs:52:1-9
  signal \c$$d(%,,%)_app_arg\ : blinker_types.rst_dom50;
  -- examples/Blinker.hs:52:1-9
  signal \c$ds_app_arg\       : blinker_types.tup3 := ( tup3_sel0_std_logic_vector => std_logic_vector'(x"01"), tup3_sel1_ledmode => "0", tup3_sel2_index_16650001 => to_unsigned(0,24) );
  signal result               : boolean;
  -- examples/Blinker.hs:98:1-8
  signal leds                 : std_logic_vector(7 downto 0);
  -- examples/Blinker.hs:98:1-8
  signal mode                 : blinker_types.ledmode;
  -- examples/Blinker.hs:98:1-8
  signal cntr                 : blinker_types.index_16650001;
  signal \c$case_alt\         : blinker_types.tup2;
  signal \c$app_arg\          : blinker_types.index_16650001;
  signal \c$app_arg_0\        : blinker_types.ledmode;
  signal \c$case_alt_0\       : blinker_types.ledmode;
  signal \c$app_arg_1\        : std_logic_vector(7 downto 0);
  signal \c$case_alt_1\       : std_logic_vector(7 downto 0);
  -- examples/Blinker.hs:52:1-9
  signal old                  : std_logic := '1';
  -- examples/Blinker.hs:52:1-9
  signal \$d(%,,%)\           : blinker_types.rst_dom50;
  -- examples/Blinker.hs:52:1-9
  signal clk50                : blinker_types.clk_dom50;
  -- examples/Blinker.hs:52:1-9
  signal ds1                  : blinker_types.tup2_0;
  signal result_selection_res : boolean;

begin
  \c$ds1_app_arg\ <= '1' when (not KEY0) = true else '0';

  \c$$d(%,,%)_app_arg\ <= '1' when (not ds1.tup2_0_sel1_boolean) = true else '0';

  -- register begin 
  cds_app_arg_register : process(clk50,\$d(%,,%)\)
  begin
    if \$d(%,,%)\ =  '1'  then
      \c$ds_app_arg\ <= ( tup3_sel0_std_logic_vector => std_logic_vector'(x"01"), tup3_sel1_ledmode => "0", tup3_sel2_index_16650001 => to_unsigned(0,24) );
    elsif rising_edge(clk50) then
      \c$ds_app_arg\ <= \c$case_alt\.tup2_sel0_tup3;
    end if;
  end process;
  -- register end

  result_selection_res <= old = ('0');

  result <= KEY1 = ('1') when result_selection_res else
            false;

  leds <= \c$ds_app_arg\.tup3_sel0_std_logic_vector;

  mode <= \c$ds_app_arg\.tup3_sel1_ledmode;

  cntr <= \c$ds_app_arg\.tup3_sel2_index_16650001;

  \c$case_alt\ <= ( tup2_sel0_tup3 => ( tup3_sel0_std_logic_vector => \c$app_arg_1\
                  , tup3_sel1_ledmode => \c$app_arg_0\
                  , tup3_sel2_index_16650001 => \c$app_arg\ )
                  , tup2_sel1_std_logic_vector => leds );

  with (cntr) select
    \c$app_arg\ <= to_unsigned(0,24) when x"FE0F10",
                   cntr + to_unsigned(1,24) when others;

  \c$app_arg_0\ <= \c$case_alt_0\ when result else
                   mode;

  with (mode) select
    \c$case_alt_0\ <= "1" when "0",
                      "0" when others;

  with (cntr) select
    \c$app_arg_1\ <= \c$case_alt_1\ when x"000000",
                     leds when others;

  with (mode) select
    \c$case_alt_1\ <= std_logic_vector(rotate_left(unsigned(leds),to_integer(to_signed(1,64)))) when "0",
                      not leds when others;

  LED <= \c$case_alt\.tup2_sel1_std_logic_vector;

  -- register begin 
  old_register : process(clk50,\$d(%,,%)\)
  begin
    if \$d(%,,%)\ =  '1'  then
      old <= '1';
    elsif rising_edge(clk50) then
      old <= KEY1;
    end if;
  end process;
  -- register end

  resetsynchronizer_d : entity resetsynchronizer
    port map
      ( result => \$d(%,,%)\
      , eta    => clk50
      , eta1   => \c$$d(%,,%)_app_arg\ );

  clk50 <= ds1.tup2_0_sel0_clk_dom50;

  altpll_block : block
    signal locked  : std_logic;
    signal plllock : boolean;
    signal pllout  : blinker_types.clk_dom50;
    component altpllE588ED61A4853C9C
      port ( clk    : in blinker_types.clk_input
           ; areset : in blinker_types.rst_input
           ; c0     : out blinker_types.clk_dom50
           ; locked : out std_logic );
    end component;

  begin
    altpll50 : component altpllE588ED61A4853C9C
      port map
        ( clk    => CLOCK_50
        , areset => \c$ds1_app_arg\
        , c0     => pllout
        , locked => locked );

    with (locked) select
      plllock <= true when '1',
                 false when others;

    ds1 <= ( tup2_0_sel0_clk_dom50 => pllout
           , tup2_0_sel1_boolean => plllock );

  end block;

end;

Hi Chrisatiaan,

I just removed the pin assignments from the .qsf file and went through the workflow with the pin annotations enabled in 'Blinker.hs'. To my surprise it worked.

This is curious because I spent several hours figuring out what is going on. At some stage I definitely got the error with the pin names and at that stage I thought it was caused by the pin annotation because when I commented them out, the error disappeared.

I'll see if I can reproduce. I'm not making it up.

Regards,

Paddy

paddytheplaster commented 4 years ago

Hi again,

I tried a few things but I can't reproduce the error about pin names starting with 'Pin_'.

All I can say is that quartus does appear to use pin names of the form 'Pin*' in some of its text-based output (the error I got was through the command line interface). E.g. when I open 'blinker.map.rpt', I get the following information about the pin assignments. In the GUI the pin names are displayed as 'PIN*' etc.

+---------------------------------------------------+
; Source assignments for Top-level Entity: |blinker ;
+-------------+-------------+------+----------------+
; Assignment  ; Value       ; From ; To             ;
+-------------+-------------+------+----------------+
; LOCATION    ; Pin_L3      ; -    ; LED[7]         ;
; LOCATION    ; Pin_B1      ; -    ; LED[6]         ;
<MORE LINES OMITTED>

Regards,

Paddy

paddytheplaster commented 4 years ago
  • I notice the input and output ports of the topEntity are annotated with pin names. This suggests you don't have to do this in your .qsf file. Is this correct? If yes, that'd be wonderful. Is this described somewhere?

I believe that's correct. It goes by different names for different HDLs, but for VHDL this would be the chip_pin synthesis attributes. You can set attributes using Clash.Annotations.SynthesisAttributes. As you've noticed, Blinker.hs is an example of a design using it.

Thanks again Martijn,

I'm now trying the in-Haskell pin annotations but I get a problem when I use a port product for the output.

        , t_output  = PortProduct "" [ PortName "TX"
                                     , PortName "LED"
                                     ]

      -- output of top entity
      -> Signal ClockDomain (Bit,BitVector 8)
         `Annotate` 'StringAttr "chip_pin" "D3, L3, B1, F3, D1, A11, B13, A13, A15"
         `Annotate` 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL

When I compile this I get the following.

/home/paddy/Altera/Clash/tops/TopEntity.lhs:70:3: error:

    Clash.Netlist.Util(1427): Attempted to split Product into a number of HDL ports. This is not allowed in combination with attribute annotations. You can annotate Product's components by splitting it up manually.

    The source location of the error is not exact, only indicative, as it is acquired
    after optimizations. The actual location of the error can be in a function that is
    inlined. To prevent inlining of those functions, annotate them with a NOINLINE pragma.

When I turn the '(Bit,BitVector 8)' into a 'BitVector 9' (and concatenate the 'Bit' and 'BitVector 8' signals) I get the following:

Clash.Netlist.Util(743): Ports were annotated as product, but type wasn't one:

   Filtered was: FilteredHWType (Annotated [StringAttr' "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\"",StringAttr' "chip_pin" "D3, L3, B1, F3, D1, A11, B13, A13, A15"] (Annotated [StringAttr' "chip_pin" "D3, L3, B1, F3, D1, A11, B13, A13, A15"] (BitVector 9))) []

   Ports was: PortProduct "" [PortName "TX",PortName "LED"]
CallStack (from HasCallStack):
  error, called at src/Clash/Netlist/Util.hs:743:3 in clash-lib-1.3.0-LvWndWMDBc6AzweKogm6Ks:Clash.Netlist.Util

I checked the documentation on 'http://hackage.haskell.org/package/clash-prelude-1.2.4/docs/Clash-Annotations-SynthesisAttributes.html' but it doesn't refer to signals of product types. Is there a way around this, please?

Regards,

Paddy

DigitalBrains1 commented 4 years ago

This is my first brush with these annotations, but this works:

        , t_output = PortProduct "" [ PortName "TX"
                                    , PortName "LED"
                                    ]

[...]

    -> Signal System
          ( Bit `Annotate`
              [ 'StringAttr "chip_pin" "D3"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          , BitVector 8 `Annotate`
              [ 'StringAttr "chip_pin" "L3, B1, F3, D1, A11, B13, A13, A15"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          )

We should add such an example to the documentation.

paddytheplaster commented 4 years ago

This is my first brush with these annotations, but this works:

        , t_output = PortProduct "" [ PortName "TX"
                                    , PortName "LED"
                                    ]

[...]

    -> Signal System
          ( Bit `Annotate`
              [ 'StringAttr "chip_pin" "D3"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          , BitVector 8 `Annotate`
              [ 'StringAttr "chip_pin" "L3, B1, F3, D1, A11, B13, A13, A15"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          )

We should add such an example to the documentation.

This is my first brush with these annotations, but this works:

        , t_output = PortProduct "" [ PortName "TX"
                                    , PortName "LED"
                                    ]

[...]

    -> Signal System
          ( Bit `Annotate`
              [ 'StringAttr "chip_pin" "D3"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          , BitVector 8 `Annotate`
              [ 'StringAttr "chip_pin" "L3, B1, F3, D1, A11, B13, A13, A15"
              , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
              ]
          )

We should add such an example to the documentation.

Great. Thanks a mille.

Regards,

Paddy

martijnbastiaan commented 3 years ago

I believe this was mostly an issue with configuring the EDA tooling. I'll therefore be closing this issue. If this is incorrect, please reopen.