Xilinx VHDL Multicycle constraints - vhdl

I have some code that's running on a Xilinx Spartan 6, and it currently meets timing. However, I'd like to change it so that I use fewer registers.
signal response_ipv4_checksum : std_logic_vector(15 downto 0);
signal response_ipv4_checksum_1 : std_logic_vector(15 downto 0);
signal response_ipv4_checksum_2 : std_logic_vector(15 downto 0);
signal response_ipv4_checksum_3 : std_logic_vector(15 downto 0);
…
process (clk)
begin
if rising_edge(clk) then
response_ipv4_checksum_3 <= utility.ones_complement_sum(x"4622", config.source_ip(31 downto 16));
response_ipv4_checksum_2 <= utility.ones_complement_sum(response_ipv4_checksum_3, config.source_ip(15 downto 8));
response_ipv4_checksum_1 <= utility.ones_complement_sum(response_ipv4_checksum_2, response_group(31 downto 16));
response_ipv4_checksum <= utility.ones_complement_sum(response_ipv4_checksum_1, response_group(15 downto 0));
end if;
end process;
Currently, to meet timing, I need to split up the additions over multiple cycles. However, I have 20 cycles to actually compute this value, during which time the config value can't change.
Is there some attribute I can use (preferred) or line in the constraints (ucf) file that I can use so that I could simply write the same thing, but use no registers?
Just for a bit of extra code, in my UCF, I already have a timespec that looks like this:
NET pin_phy_rxclk TNM_NET = "PIN_PHY_RXCLK";
TIMESPEC "TS_PIN_PHY_RXCLK" = PERIOD "PIN_PHY_RXCLK" 8ns HIGH 50%;

I think you need a FROM:TO constraint:
TIMESPEC TSname=FROM “group1” TO “group2” value;
where value can be based on another timespec, like TS_CLK*4
So you'd adjust your process to only have flipflops on the output signals, create a timegroup with the inputs in it, another with the outputs in it, and use those for group1 and group2 .
So, group 1 would contain all the input nets /path/to/your/instance/config.source_ip and /path/to/your/instance/response_group. It might be easier to create a vector input to the entity and wire up the config/response_group signals outside of it. Then you can just use /path/to/your/instance/name_of_input_signals.
Group 2 would contain /path/to/your/instance/response_ipv4_checksum.
And, as you comment, you can use TS_PIN_PHY_RXCLK*4 (assuming it is a time, not a frequency - otherwise you have to do a /4 I think)

Related

Loop for lines and for position of lines

I want to have a loop that runs the all lines of my code and also that runs every position of all lines.
My problem is in selecting the line that the loop will run, and I want to have simple way to do it without making to write every single line one-by-one, cause the final code will have 66 lines to scan.
Hope you can help me.
Entity of this code will have 66 lines, but I'm just testing it this 10 lines right now:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lshift is
port( RED_Buffer1 : in std_logic_vector(6 downto 0);
RED_Buffer2 : in std_logic_vector(6 downto 0);
RED_Buffer3 : in std_logic_vector(6 downto 0);
RED_Buffer4 : in std_logic_vector(6 downto 0);
RED_Buffer5 : in std_logic_vector(6 downto 0);
IR_Buffer1 : in std_logic_vector(6 downto 0);
IR_Buffer2 : in std_logic_vector(6 downto 0);
IR_Buffer3 : in std_logic_vector(6 downto 0);
IR_Buffer4 : in std_logic_vector(6 downto 0);
IR_Buffer5 : in std_logic_vector(6 downto 0);
output : out bit_vector(1 downto 0));
end lshift;
What I have done so far but with no success:
ARCHITECTURE main OF lshift IS
SIGNAL condition1: boolean;
signal valor : std_ulogic;
BEGIN
PROCESS(IR_Buffer5)
BEGIN
FOR I IN 1 TO 5 LOOP
FOR J IN 1 TO 5 LOOP
CONSTANT linha_cond : string(1 to 12) := string(("RED_Buffer") && I);
IF (linha_cond(J) = '1') THEN
output <= "01";
END IF;
END LOOP;
END LOOP;
END PROCESS;
END main;
The purpose of this answer is to demonstrate indexing the subelement values of RED_Buffer1 through RED_Buffer5. Without the purpose of the code being revealed this could easily prove to be an XY Problem question.
While it is possible to organize RED_Buffer1 through RED_Buffer5 into a value that can be indexed as shown below, there are other issues as well.
library ieee;
use ieee.std_logic_1164.all;
entity lshift is
port (
red_buffer1: in std_logic_vector (6 downto 0);
red_buffer2: in std_logic_vector (6 downto 0);
red_buffer3: in std_logic_vector (6 downto 0);
red_buffer4: in std_logic_vector (6 downto 0);
red_buffer5: in std_logic_vector (6 downto 0);
ir_buffer1: in std_logic_vector (6 downto 0);
ir_buffer2: in std_logic_vector (6 downto 0);
ir_buffer3: in std_logic_vector (6 downto 0);
ir_buffer4: in std_logic_vector (6 downto 0);
ir_buffer5: in std_logic_vector (6 downto 0);
output: out bit_vector (1 downto 0)
);
end entity lshift;
architecture indexed_array of lshift is
signal condition1: boolean;
signal valor: std_ulogic;
type lbuffer is array (1 to 5) of std_logic_vector (6 downto 0);
signal red_buffer: lbuffer;
begin
red_buffer <= (red_buffer1, red_buffer2, red_buffer3, red_buffer4,
red_buffer5);
process (red_buffer)
begin
for i in 1 to 5 loop
for j in red_buffer'range loop
if red_buffer(i)(j) = '1' then
output <= "01";
end if;
end loop;
end loop;
end process;
end architecture indexed_array;
How the indexing is implemented here
A composite type (lbuffer) having the requisite number of elements with required element subtype is declared. This is possible because the declarations for ports RED_Buffer1 through RED_Buffer5 share a common subtype indication. Assignment to elements of an object of the type lbuffer would be compatible, having matching elements between the target and right hand expression.
A signal red_buffer with a type mark of lbuffer is declared.
A concurrent assignment was made to the signal in a concurrent signal assignment statement in the architecture statement part from an aggregate. The association in the aggregate is positional. It could as easily use named association:
-- red_buffer <= (red_buffer1, red_buffer2, red_buffer3, red_buffer4,
-- red_buffer5);
red_buffer <= (1 => red_buffer1, 2 => red_buffer2, 3 => red_buffer3,
4 => red_buffer4, 5 => red_buffer5);
The type of the aggregate is taken from context, here the assignment statement where red_buffer has the subtype lbuffer.
A selected element of the composite red_buffer is selected by an index name (red_buffer(i)). A subelement of red_buffer(i) is selected by use of an indexed name where the name red_buffer(i) where 'iis a constant using 'j from the inner loop - red_buffer(i)(j).
Note the range of the j parameter doesn't match the index range of subtype of the lbuffer element subtype here identical to the subtype of RED_Buffer1 through RED_Buffer5. This signifies a further potential semantic issue with the original code, whose purpose isn't made clear here. The only hint present in the original code comes from linha_cond where linha means line in Portuguese or Catalan indicating j is used to index within a 'line'.
The original code fails for two reasons
First an object can't be declared inline in VHDL. The for loop parameter is dynamically elaborated from an implicit declaration, the loop parameter is only visible within the loop statement's sequence of statements. The syntax doesn't allow for additional object declarations.
Second a name for a object declaration is conveyed in an identifier list consisting of one or more identifiers which are lexical elements (lexemes) that cannot be manipulated programmatically.
Other semantic issues with the question's code
The assignment to output without the passage of time doesn't appear useful.
A process statement is an independently executing concurrent statement wherein the loop statement containing an assignment to the same signal output will overwrite the projected output waveform for elements of output without any intervening passage of time.
There's only one entry in a projected output waveform queue for any particular simulation time. A simulation cycle consists of signal updates followed by the resumption and subsequent suspension of any processes sensitive to signal updates. The purpose is to emulate parallelism in hardware while describing behavior with sequential statements.
Here that would mean output would be updated to the value "01" if any of the if statement conditions in the unrolled loops evaluate to TRUE. That's likely not the intended behavior (without more information from the original poster).
Also note there is no output assignment to a different value and no default or otherwise assigned value. For synthesis this would represent a hold over delay on output until a '1' is first found.
In both cases this refers to an implicit latch for output.
This issue with the sample code can't be addressed without knowing how it is supposed to work and the only hint that has been shown here on Stackoverflow to date is by a question deleted by the user requiring 10K+ reputation to access (others will see aPage not found message, see revision 1).
Also concepts conveyed from programming or scripting languages don't generally port to Hardware Description Languages which are generally formal notations defined self-referentially (here in IEEE Std 1076, the VHDL Language Reference Manual) requiring inculcation or persistent effort to learn. HDLs generally describe hardware behaviorally and structurally not by programmatic equivalence.

How to attach a parity bit to a given 4 bit std_logic_vector?

Image of the DUT
I'm trying to write an internal nibble transmission guarded by a parity bit.
For this I want to write a transmitter/receiver logic which is shown in the image attached.
So I have a 4 bit input vector and generate a parity bit for it and here comes my problem.
I want to attach the parity bit to the input vector. But the input vector is only 4 bit. Is there a way to resize it by simply attaching the parity bit to the input vector or do i have to transmit the parity bit seperately?
And as a little side question in relation to the whole implementation:
Do I have to create seperated processes for the receiver and transmitter like I have in my code or do I simply have to write one process containing both?
My first idea was to simply use an internal vector with 5 bit to attach the parity bit but the problem is that I only want the given input as output in the end and there is the same problem. In the process of the parity checker I have to fill the output vector which is 4 bit with the intern 5 bit vector and have no idea if this simply works like I tried in my code.
I hope you can understand the problem.
Thanks.
architecture rtl of odd parity is
signal rxdat_s : out std_logic_vector(3 downto 0);
signal ok_s : out std_logic;
signal txdat_s : in std_logic_vector(3 downto 0);
signal secured_s : std_logic_vector (4 downto 0);
begin
odd_parity_gen: process ( txdat_s, clk ) is
variable txdat_v : std_logic_vector(3 downto 0);
variable secured_v : std_logic_vector(4 downto 0);
variable odd_parity_v : integer;
begin
txdat_v := txdat_s;
odd_parity_v := xnor txdat_v;
secured_v := txdat_v + odd_parity_v;
secured_s <= secured_v;
end process odd_parity_gen;
odd_parity_check: process () is
variable ok_v : integer;
variable rxdat_v : std_logic_vector(3 downto 0);
variable secured_v : std_logic_vector(4 downto 0);
begin
rxdat_v := rxdat_s;
secured_v := secured_s;
ok_v := ok_s;
ok_v := xnor secured_v;
rxdat_v := secured_v;
ok_s <= ok_v;
rxdat_s <= rxdat_v;
reg: process ( clk ) is
begin
if rising_edge (clk) then
if nres = '0' then
--reset all signals
else
--main logic
end if;
end if;
end process;
I assume this code has been cobbled together as example. You have input/output ports in an architecture and your ports are rather confusing: rxdat_s is an output and txdat_s is an input. Also you have no 5 bit output port which you need to send 4 bits plus parity.
Also this: secured_v := txdat_v + odd_parity_v; adds a an integer and a std_logic_vector which requires conversion or a library.
Assuming your parity generator is correct you can add a parity bit to the front using concatenation: the & operator.
secured_s <= odd_parity_v & rxdat_s;
Or at the back using:
secured_s <= rxdat_s & odd_parity_v;

how to make std_logic_vector consist of std_logic_vectorin vhdl

I have such signal:
sw : std_logic_vector(7 downto 0);
and now I want to make another one, which will have it as upper bits, 1 the rest:
std_logic_vector(31 downto 0) := (7 downto 0 => sw, others => '1');
but it won't compile. any help please? I don't want to do it bit by bit.
I'm not entirely sure where should go this smaller signal, but you probably want to do this:
signal sw: std_logic_vector(7 downto 0);
signal big: std_logic_vector(31 downto 0);
big <= sw & x"FFFFFF";
This will assign sw vector to 8 most significant bits of big vector, and '1' to rest of bits. Write in comments, if you want to do something else.
What you are trying to do is assign a signal -which is variable- to another signal during initialization. What do you expect to happen?
I.e. at the moment you define a signal, you can only initialize it. If you want to assign something to the signal, you have to write a declaration.
definition -> initialization
declaration -> assignment
So in this case you can define big a larger range, and fix the constant bits in initialization
signal big : std_logic_vector(31 downto 0) => (others => '1');
And when you want to assign sw to any part of big, do that after the begin.
big(31 downto 24) <= sw;
or
big(7 downto 0) <= sw;
etc. The bits you initialized as '1' will be overwritten by the assignment.

Dynamic Arrray Size in VHDL

I want to use dynamic range of array , so using "N" for converting an incoming vector signal to integer. Using the specifc incoming port "Size" gives me an error, while fixed vector produces perfect output.
architecture EXAMPLE of Computation is
signal size :std_logic_vector (7 downto 0);
process (ACLK, SLAVE_ARESETN) is
variable N: integer:=conv_integer ("00000111") ; ---WORKING
--variable N: integer:=conv_integer (size) ; -- Not working
type memory is array (N downto 0 ) of std_logic_vector (31 downto 0 );
variable RAM :memory;
Only reason to do this type of coding is send as much data as possible to FPGA .As I need to send Data from DDR to Custom IP via DMA in vivado may be more than 100 MB. so kindly guide me if I am trying to implement in wrong way as stated above.
You can't do that in VHDL. What kind of hardware would be generated by your code? If you don't know, the synthesizer won't either.
The way to do this kind of thing is to set N to the largest value you want to support, and use size in your logic to control your logic appropriately. It's difficult to give more pointers without more information, but as an example, you could use a counter to address your ram, and have it reset when it's greater than size.
Update
Here's a counter example. You have to make sure that size doesn't change while operating or it will fall into an unknown state. A real design should have reset states to ensure correct behaviour.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity example is
port (
clk : std_logic;
rst : in std_logic;
size : in unsigned(7 downto 0);
wr : in std_logic;
din : in std_logic_vector(31 downto 0)
);
end entity;
architecture rtl of example is
signal counter : unsigned(7 downto 0);
type ram_t is array(0 to 255) of std_logic_vector(31 downto 0);
signal ram : ram_t;
begin
RAM_WR: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
else
if wr = '1' then
ram(to_integer(counter)) <= din;
if counter = size then
counter <= (others => '0');
else
counter <= counter + 1;
end if;
end if;
end if;
end if;
end process RAM_WR;
end architecture rtl;
I believe you can only have a generic an array constraint in a process. Otherwise, the compiler cannot elaborate.
In a function or procedure, you can have truly variable array bounds.

How to declare an output with multiple zeros in VHDL

Hello i am trying to find a way to replace this command: Bus_S <= "0000000000000000000000000000000" & Ne; with something more convenient. Counting zeros one by one is not very sophisticated. The program is about an SLT unit for an ALU in mips. The SLT gets only 1 bit(MSB of an ADDSU32) and has an output of 32 bits all zeros but the first bit that depends on the Ne=MSB of ADDSU32. (plz ignore ALUop for the time being)
entity SLT_32x is
Port ( Ne : in STD_LOGIC;
ALUop : in STD_LOGIC_VECTOR (1 downto 0);
Bus_S : out STD_LOGIC_VECTOR (31 downto 0));
end SLT_32x;
architecture Behavioral of SLT_32x is
begin
Bus_S <= "0000000000000000000000000000000" & Ne;
end Behavioral;
Is there a way to use (30 downto 0)='0' or something like that? Thanks.
Try this: bus_S <= (0 => Ne, others => '0')
It means: set bit 0 to Ne, and set the other bits to '0'.
alternative to the given answers:
architecture Behavioral of SLT_32x is
begin
Bus_S <= (others => '0');
Bus_S(0) <= ne;
end Behavioral;
Always the last assignment in a combinatoric process is taken into account. This makes very readable code when having a default assignment for most of the cases and afterwards adding the special cases, i.e. feeding a wide bus (defined as record) through a hierarchical block and just modifying some of the signals.

Resources