myhdl constraints associating multiple pins to a variable - byte

I will be using an iCE40HX8K
given the evaluation boards constraint file
set_io LED3 A2
set_io LED7 B3
...
etc
whats the best way to bundle all 8 LED's into one variable
I had trouble associating things with my constraint file and ended up with something like this
#main module
def ledcount(LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8, clk):
when writing a register to the LED's I'm having to resort to this
op.next = op + 1
LED1 = op[0]
...
LED8 = op[7]
I'm generating verilog like this... (I did have single sliced bits from a single signal here but it seemed to cause problems - ie LED3 in constrains not assigning to anything)
clock = Signal(bool(0))
l1 = Signal(bool(0))
...
l8 = Signal(bool(0))
toVerilog(ledcount, l1, l2, l3, l4, l5, l6, l7, l8, clock)
bad enough but its going to become unwieldy with a parallel address and data bus ...
I notice in the generated verilog LED1-8 are specified like this
input LED1;
...
input LED8;
before the always clause
and inside the always
reg LED1;
...
reg LED8;
While all this compiles (Hardware should arrive tomorrow!) and it might(?) even work... I'm sure it can be done better!
I'd be quite happy handling the LED's together as a single byte using bit manipulation...

The most straight forward is to change your constraints to
set_io LED[2] A2
and then use a single LED port
def ledcount(leds, clk)
and it can be converted to
clk = Signal(bool(0))
leds = Signal(intbv(0)[8:])
myhdl.toVerilog(ledcount, leds, clk)

Related

block ram (BRAM) read and write using different clocks

I am relatively new to some advanced VHDL programming and have a problem i have been facing for a while.
I will try to be very thorough in my problem description.
I am using a Digilent Nexys-3 board with SPARTAN - 6 FPGA
Here is what i am trying to implement:
Read data from ADC SPI bus and store it into the BRAM.
For this i instantiate a block RAM using a memory IP core generator
ADC_BRAM: bram
port map( ..
..
addra => addra,
dina => ADC_DATA,
..
..
);
The addra, ADC_DATA (data on SPI bus stored into a std_logic_vector) is assigned during the "read_adc" state of the FSM in the ADC module.
After the ADC has sampled 100 points I stop writing into the BRAM
main: process(clk)
begin
if(rising_edge(clk)) then
case state is
when read_adc =>
.....
.....
.....
if(addra < "1100100") then
.....
<some code>
addra <= addra + 1;
.....
elsif (addra = "1100100") then
state <= endofconversion;
end if;
when endofconversion =>
addra <= "00000000";
wea <= "0"; -- write enable for BRAM
state <= read_bram;
Next, i want to access the data from the BRAM and send it using USB-UART.
From what i understand all the BRAM's are synchronous and thus have to be implemented with process(clk,reset).
Currently i have implemented the state " read_bram" under the same process as mentioned above
main: process(clk)
begin
if(rising_edge(clk)) then
case state is
<some code>
when endofconversion =>
addra <= "00000000";
wea <= "0"; -- write enable for BRAM
state <= read_bram;
when read_bram =>
....
<some code>
....
end case;
Now the UART clock needs to be much slower than the rate at which ADC has been read.
My question is " How do i implement the read operation of the BRAM using a much slower clock, which will ensure proper functioning of the UART" ?
I also tried another approach where the BRAM module is defined in the top level file and i send the " addra, ADC_DATA" generated from the ADC module into the port map of the BRAM module.
Now, on the top level if i create a slower clock to read the data ("douta") from the BRAM and send it to UART, i need to generate "addra" in this process and send it to BRAM port "addra"
This causes issues of " multiple drivers " connected to signal "addra", as its values changes in the "process()" of both the ADC module (faster clock) and the top level module (slower clock).
Please help me out. I can provide more info if the problem description is not clear.
TLDR; How can i use 2 separate clocks while implementing synchronous memory BRAM
- "faster clock => write into BRAM" -- based on ADC sampling rate
- " slower clock => read from BRAM" -- based on UART clk (slower BAUD rate than ADC sampling speed)

Array of 1-bit-wide memory

I'm using ISE 14.7 and i'm trying to create design with some 1-bit-wide distributed RAM blocks.
My memory declaration:
type tyMemory is array (0 to MEMORY_NUM - 1) of std_logic_vector(MEMORY_SIZE - 1 downto 0) ;
signal Memory: tyMemory := ( others => (others => '0')) ;
attribute ram_style : string ;
attribute ram_style of Memory : signal is "distributed" ;
My code:
MemoryGen : for i in 0 to MEMORY_NUM - 1 generate
process( CLK )
begin
if rising_edge(CLK) then
if CE = '1' then
DataOut(i) <= Memory(i)(Addr(i)) ;
Memory(i)(Addr(i)) <= DataIn(i) ;
end if ;
end if ;
end process ;
end generate ;
After synthesis i get this warning:
WARNING:Xst:3012 - Available block RAM resources offer a maximum of two write ports.
You are apparently describing a RAM with 16 separate write ports for signal <Memory>.
The RAM will be expanded on registers.
How can i forse xst to use distributed memory blocks with size=ARRAY_LENGTH and width=1?
I can create and use separate memory component(and is works), but i need more elegant solution.
You need to create an entity that describes a variable length 1-bit wide memory, then use a generate statement to create an array of these. While what you have done would provide the functionality you are asking for in a simulator, most FPGA tools will only extract memory elements if your code is written in certain ways.
You can find documentation on what code Xilinx ISE tools will understand as a memory element by selecting the appropriate document for your device here http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_7/ise_n_xst_user_guide_v6s6.htm . Look under 'HDL Coding techniques'.
Note that if your memory length is large, you will not be able to get maximum performance from it without adding manual pipelining. I think you will get a synthesis message if your memory exceeds the intended useful maximum length for distributed memories. Assuming you are using a Spartan 6 device, you can find information on what the useful supported distributed memory sizes are here: http://www.xilinx.com/support/documentation/user_guides/ug384.pdf page 52.
This should inferre 16 one bit wide BlockRAMs:
architecture ...
attribute ram_style : string;
subtype tyMemory is std_logic_vector(MEMORY_SIZE - 1 downto 0) ;
begin
genMem : for i in 0 to MEMORY_NUM - 1 generate
signal Memory : tyMemory := (others => '0');
attribute ram_style of Memory : signal is "block";
begin
process(clk)
begin
if rising_edge(clk) then
if CE = '1' then
Memory(Addr(i)) <= DataIn(i) ;
DataOut(i) <= Memory(Addr(i)) ;
end if ;
end if ;
end process ;
end generate ;
end architecture;

Why can't make work my VHDL program using elsif not recognize one state

I'am a spanish user an newbie on VHDL programming the problems its that I was trying to make a machine state with the CASE but don't work. then i decide to do with ELSIF instruction all its working perfect but the state 0010 its not working a I don't know why its a very ease program but don't understand why y is not working EXCUSE MY POOR ENGLISH but I do my best thanks I show the program next:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
--definimos identidad de la interfaz
entity interfaz is
port(
sen:in std_logic_vector(3 downto 0);--entrada de sensor bus de 4 bits
clk:in std_logic;
mda, mdr, mia, mir:out std_logic);--mdr,mda=motor derecho retroceso,avance == mia,mir=motor izquiero avance,retroceso
end interfaz;
--comenzando arquitectura de interfaz
architecture behavior of interfaz is
----------------------------------------------------
--Instruccion con herramienta elseif
process
begin
wait until clk'event and clk='1';
if (sen=(0000)) then --alto
mda<='0';
mdr<='0';
mia<='0';
mir<='0';
elsif (sen=(0001)) then --retroceso
mda<='0';
mdr<='1';
mia<='0';
mir<='1';
elsif (sen=0010) then --avance
mda<='1';
mdr<='0';
mia<='1';
mir<='0';
elsif (sen=(0100)) then --izquierda
mda<='0';
mdr<='1';
mia<='1';
mir<='0';
elsif (sen=(1000)) then --derecha
mda<='1';
mdr<='0';
mia<='0';
mir<='1';
end if;
end process;
end behavior;
The sen=0010 appears like sen is compared to a 4-bit vector, but it is
actually compare with the decimal value 0010 = 10 = ten, due to the lack of
"" around the 0010 value. Fix this in all place with by adding "", like
"0010".
VHDL is basically strong typed, but the use ieee.std_logic_unsigned.all; adds
functions that allows compare between std_logic_vector and integer, and for
this reason the problem passes syntax check.
Also:
Fix a syntax error by adding begin before the process, since that is
required in architecture
Consider using if rising_edge(clk) instead of wait until clk'event and clk='1'
Consider rewrite with case

A line of verilog code

I have a line of verilog code which I got online, I do not understand what it means.
rom_data <= #`DEL {rom[rom_addr+3],rom[rom_addr+2],rom[rom_addr+1],rom[rom_addr]};
Can someone help me debunk this ?
Breaking it down:
1 rom_data <=
2 #`DEL
3 {rom[rom_addr+3], rom[rom_addr+2], rom[rom_addr+1], rom[rom_addr]};
non-blocking assignment to rom_data, likely used inside always#(posedge clk) to imply a flip-flop
Delay set by some thing like :
`define DEL "1ms"
the 1ms or other value is pasted in where you have `DEL.
the {} means concatenation, it is taking the rom[rom_addr] and the next 3 values.
ie {2'b00, 2'b01, 2'b10, 2'b11} => 8'b00_01_10_11
All together you have rom_addr pointing at a particular location. When rom_data changes you take the next 4 values, from rom_addr to rom_addr + 3 and assign them to rom_data after a delay of `DEL.

Warning "has no load", but I can't see why

I got these warnings from Lattice Diamond for each instance of any uart (currently 11)
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_14' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_0_COUT1_9_14' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_12' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_10' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_8' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_6' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_4' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_2' has no load
WARNING - ngdbuild: logical net 'UartGenerator_0_Uart_i/Uart/rxCounter_cry_0' has no load
The VHDL-code is
entity UART is
generic (
dividerCounterBits: integer := 16
);
port (
Clk : in std_logic; -- Clock signal
Reset : in std_logic; -- Reset input
ClockDivider: in std_logic_vector(15 downto 0);
ParityMode : in std_logic_vector(1 downto 0); -- b00=No, b01=Even, b10=Odd, b11=UserBit
[...]
architecture Behaviour of UART is
constant oversampleExponent : integer := 4;
subtype TxCounterType is integer range 0 to (2**(dividerCounterBits+oversampleExponent))-1;
subtype RxCounterType is integer range 0 to (2**dividerCounterBits)-1;
signal rxCounter: RxCounterType;
signal txCounter: TxCounterType;
signal rxClockEn: std_logic; -- clock enable signal for receiver
signal txClockEn: std_logic; -- clock enable signal for transmitter
begin
rxClockdivider:process (Clk, Reset)
begin
if Reset='1' then
rxCounter <= 0;
rxClockEn <= '0';
elsif Rising_Edge(Clk) then
-- RX counter (oversampled)
if rxCounter = 0 then
rxClockEn <= '1';
rxCounter <= to_integer(unsigned(ClockDivider));
else
rxClockEn <= '0';
rxCounter <= rxCounter - 1;
end if;
end if;
end process;
txClockDivider: process (Clk, Reset)
[...]
rx: entity work.RxUnit
generic map (oversampleFactor=>2**oversampleExponent)
port map (Clk=>Clk, Reset=>Reset, ClockEnable=>rxClockEn, ParityMode=>ParityMode,
ReadA=>ReadA, DataO=>DataO, RxD=>RxD, RxAv=>RxAv, ParityBit=>ParityBit,
debugout=>debugout
);
end Behaviour;
This is a single Uart, to create them all (currently 11 uarts) I use this
-- UARTs
UartGenerator: For i IN 0 to uarts-1 generate
begin
Uart_i : entity work.UartBusInterface
port map (Clk=>r_qclk, Reset=>r_reset,
cs=>uartChipSelect(i), nWriteStrobe=>wr_strobe, nReadStrobe=>rd_strobe,
address=>AdrBus(1 downto 0), Databus=>DataBus,
TxD=>TxD_PAD_O(i), RxD=>RxD_PAD_I(i),
txInterrupt=>TxIRQ(i), rxInterrupt=>RxIRQ(i), debugout=>rxdebug(i));
uartChipSelect(i) <= '1' when to_integer(unsigned(adrbus(5 downto 2)))=i+4 and r_cs0='0' else '0';
end generate;
I can syntesis it and the uarts work, but why I got the warning?
IMHO the rxCounter should use each single possible value, but why each second bit creates the warning "has no load"?
I read somewhere that this mean that these net's aren't used and will be removed.
But to count from 0 to 2^n-1, I need no less than n-bits.
This warning means that nobody is "listening" to those nets.
It is OK to have signals that will be removed in synthesis. Warnings are not Errors! You just need to be aware of them.
We cannot assess what is happening from your partial code.
Is there a signal named rxCounter_cry?
What is the datatype of ClockDivider?
What is the value of dividerCounterBits?
What happens in the other process? If it is irrelevant, please try to run your synthesis without that process. If it is relevant, we need to see it.
Lattice ngdbuild is particularly spammy for the job it is doing, I pipe ngdbuild output through grep in my makefile to remove exactly these messages:
ngdbuild ... | grep -v "ngdbuild: logical net '.*' has no load"
There's more than 2500 of these otherwise, eliminating them helps concentrate on real issues.
Second worst toolchain spammer is edif2ngd complaining about Verilog parameters it does not have explicit handling for. This one is a two line message (over 300 of these) so I remove it with:
edif2ngd ... | sed '/Unsupported property/{N;d;}'
Just be aware that sometimes it implements things with adders. The highest order bit will not use the carry output of that adder, and the lowest order bit will not use the sign input. So you get a warning like:
WARNING - synthesis: logical net 'clock_chain/dcmachine/count_171_add_4_1/S0' has no load
WARNING - synthesis: logical net 'clock_chain/dcmachine/count_171_add_4_19/CO' has no load
No problem, bit 19 is the highest, so it will not carry anywhere, and bit 1 is the lowest, so it does not get a sign bit from anywhere. If, however, you get this warning on any of the bits in between highest and lowest, it normally means something is wrong, but not an error, so it will build something that "works" when you test it, but not in an error case. If you simulate it with error cases it will normally show undesirable results.

Resources