VHDL Dynamic slicing using mathematical expression - hardware

Is there an easy way to implement the following line:
DataTX(255-index*8 downto 248-index*8) <= encoded;
index is an integer that could be in the range 0 to 31.
DataTx is a STD_LOCIC_VECTOR(263 downto 0).
Now it currently throws an error saying there are multiple drivers for DataTx(263) and DataTx(260), which isn't actually occurring in this line.
Is there any way to write this line or implement it without have to do a massive if statement or case statement.
Thanks in the advance.
Edit:
The line above is placed in a process.
Meanwhile the other parts of DataTx are set outside the process as follows
DataTX(263 downto 261) <= "000" when spi_mode=reading else "001" when spi_mode=writing
else "011" when spi_mode=rxMode else "101" when spi_mode=txMode;
DataTX(260 downto 256) <= SPI_register;
Edit2:
DataTX(263 downto 261) <= "000" when spi_mode=reading else "001" when spi_mode=writing
else "011" when spi_mode=rxMode else "101" when spi_mode=txMode;
DataTX(260 downto 256) <= SPI_register;
-- Set the RF Chan based on input
rf_chan <= RfChans(0) when base_selection="00" else RfChans(1) when base_selection="01" else
RfChans(2) when base_selection="10" else RfChans(3) when base_selection="11";
-- Set the Base Address based on input
base_addr <= Bases(0) when base_selection="00" else Bases(1) when base_selection="01" else
Bases(2) when base_selection="10" else Bases(3) when base_selection="11";
process(clk)
variable s_index : integer range 0 to 31 := 0;
variable e_index : integer range 0 to 31 := 0;
variable r_index : integer range 0 to 31 := 0;
variable counter : integer range 0 to 7 := 0;
begin
if (rst = '1') then
...
elsif (clk'event and clk='1') then
case state is
when setup =>
case setup_state is
-- Some code like this is set here
spi_mode <= writing;
spi_register <= "10000";
DataTX(255 downto 224) <= base_addr;
DataTX(223 downto 0) <= (others => '1'); -- Fill with FF
when idle =>
... -- nothing here of relevance
-- Moves to E_setup
when E_setup =>
-- DataTx set here
spi_mode <= writing;
spi_register <= "00000";
SPI_trigger <= '1';
state <= E_setupd;
when E_setupd => -- one cycle delay
SPI_Trigger <= '0';
if ((counter = 7) and SS='1') then
-- Signals that SPI module has finished
state <= E_encode;
counter := 0;
elsif (counter < 7) then -- Give it some time to start
counter := counter +1;
end if;
when E_encode =>
encode_input <= SEQUENCE(e_index);
e_index := e_index +1;
state <= E_done;
when E_done =>
spi_register <= "00000";
-- Error here
DataTX(255-index*8 downto 248-index*8) <= encoded;
if (e_index = 31) then
e_index := 0;
state <= E_send;
else
e_index := e_index +1;
state <= E_encode;
end if;
end case;
end if;
end process;

The updated question gives enough information to attempt an answer.
It comes down to what is "locally static" i.e. computable without actually executing the process, so that hardware can be synthesised to meet the specification.
Now it might be obvious to you that
DataTX(<arbitrary range expression>) <= encoded;
only drives selected parts of DataTX leaving others undriven, without evaluating <arbitrary range expression>, but the synthesis tool isn't quite that smart. So the language places a restriction on the process, that the "locally static" expression is ALL of DataTX and so the process drives all of DataTX.
(NOTE: had the range expression been purely in terms of constants or numeric literals,this restriction would not apply)
The external assignments then form your additional drivers giving rise to "multiple drivers" errors.
Two fixes :
1) Drive the entirety of DataTX within the process, i.e. move the other slice assignments within the process ... this looks like unclean design to me
2) Assign a new signal e.g. EncodedTX within the process, and externally assign it to the correct slice of DataTX
DataTX(255 downto 0) <= EncodedTX;
or better (clearer design intent)
DataTX <= SPI_Mode_Bits & SPI_Register & Encoded_TX;
with a suitable declaration and assignment for the SPI_Mode_Bits signal.
Possibly there are other fixes too, but the second of these would probably be my first choice...
Given Edit2 I now believe option (1) is cleaner : e.g. assigning the extra bits in the main state machine process, which is where you set up SPI_Mode and SPI_Register anyway. You can even make SPI_Register an alias for the relevant slice of Data_TX. Then you don't need to cross reference between the SM and the external cruft needed to support it.
For example, consider the following declarations :
alias SPI_Register : std_logic_vector(4 downto 0) is DataTX(260 downto 256);
subtype SPI_Mode_Type is std_logic_vector(2 downto 0);
alias SPI_Mode : SPI_Mode_Type is DataTX(263 downto 261);
constant writing : SPI_Mode_Type := "001"; -- and a few more of these
The state machine, without change, will now perform all the assignments to Datatx and the external assignments can simply be deleted.

Related

errors while using two process in one entity vhdl

I am trying to write a signal generator with VHDL and state machine approach. it needs to have two processes in an entity and I am doing everything just as same as the course I've passed but I am getting some errors around my process and I think something must be wrong with it. this is the code
entity pulse_generator is
port(clk : in std_logic;
output: out std_logic);
end pulse_generator;
architecture Behavioral of pulse_generator is
type state is (one, two, three, four);
signal nxt, pre: state;
begin
--upper
p1: process(clk)
begin
if (falling_edge(clk))then
pre <= nxt;
end if
end process p1;
--lower
p2: process(pre)
variable count: integer range 0 to 500;
begin
case pre is
when one =>
output <= '0';
count := count+1;
if (count = 300)then
nxt <= two;
count := 0;
else nxt <= one;
end if;
when two =>
output <= '1';
count := count+1;
if (count = 400)then
nxt <= three;
count := 0;
else nxt <= two;
end if;
when three =>
output <= '0';
count := count+1;
if (count = 500)then
nxt <= four;
count := 0;
else nxt <= three;
end if;
when four =>
output <= '1';
count := count+1;
if (count = 200)then
nxt <= one;
count := 0;
else nxt <= four;
end if;
end case;
end process p2;
end Behavioral;
and these are the errors
ERROR:HDLCompiler:806 - Line 19: Syntax error near "end".
ERROR:HDLCompiler:806 - Line 22: Syntax error near "process".
ERROR:HDLCompiler:806 - Line 23: Syntax error near "variable".
ERROR:HDLCompiler:806 - Line 59: Syntax error near "process".
ERROR:HDLCompiler:806 - Line 61: Syntax error near "Behavioral"
what am I doing wrong?

How to derive a Fixed Length Output signal from a variable length Input signal in verilog

I have an HDL Block in which the output follows the input in such a way that when input signal is binary 0, output remains 0 but when input turns 1, output turns 1 for a preset number of clock cycles (signal_length). i.e. input may remain high for suppose 65 or 66 clock cycles but output should remain high for preset number of clock cycles. I tried to accomplish the task with Verilog. But I am having an error and I don’t know how to rectify. Hope someone can help.
module last_ind
#(
parameter MAX_LENGTH = 262144,
parameter signal_length
)
(
input clk,
input [17:0] pkt_length,
input tdata,
output tlast
);
reg [17:0] cnt = 0;
always # (posedge clk)
begin
if ((tdata==1) && (cnt<signal_length))
tlast <= 1;
else
cnt <= 0;
end
assign cnt <= cnt + 1'b1;
endmodule
maybe something like this will do. It should keep the signal up for the signal_length cycles and will reset when tdata gets '0'. You decide on the correct protocol though.
reg [17:0] cnt = signal_length;
always # (posedge clk) begin
if (cnt < signal_lenth)
cnt <= cnt + 1;
else if (cnt == signal_length + 1 && tdata == 1 && tlast == 0) begin
cnt <= 0;
tlast <= 1;
end
else if (tdata == 0) begin
cnt <= sighal_length + 1;
tlast <= 0;
end
else
tlast <= 0;
end

Pushing std_logic_vector to variable

I'm trying to push two std_logic_vectors to to the variables a and b in the function divide.
Now, the problem is that the variable b won't be written.
But variable a will be written, which is coded the same way as b.
I received the following error message:
used initial value expression for variable "b1" because variable was never assigned a value
This is the function call:
s_ratio <= divide((to_unsigned(0,N_CUM-4) & unsigned(hold_ratio(7 downto 4))) , (to_unsigned(0,N_CUM-4) & unsigned(hold_ratio(3 downto 0))));
And this is the function with the variable b in line 3.
function divide (a : UNSIGNED; b : UNSIGNED) return UNSIGNED is
variable a1 : unsigned(a'length-1 downto 0):=a;
variable b1 : unsigned(b'length-1 downto 0):=b;
variable p1 : unsigned(b'length downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to b'length-1 loop
p1(b'length-1 downto 1) := p1(b'length-2 downto 0);
p1(0) := a1(a'length-1);
a1(a'length-1 downto 1) := a1(a'length-2 downto 0);
p1 := p1-b1;
if(p1(b'length-1) ='1') then
a1(0) :='0';
p1 := p1+b1;
else
a1(0) :='1';
end if;
end loop;
return a1;
end divide;

Verilog implementation of serial receiver not behaving like simulation (in fact, it's doing nothing)

I have designed a simple implementation of a UART reciever using Verilog. I did it using the state machine approach.
Here is my code:
module my_serial_receiver(
input clk,
input reset_n,
input Rx,
output reg [7:0] received_byte,
output reg byte_ready
);
parameter IDLE = 4'd0, BIT_0 = 4'd1, BIT_1 = 4'd2,
BIT_2 = 4'd3, BIT_3 = 4'd4, BIT_4 = 4'd5, BIT_5 = 4'd6,
BIT_6 = 4'd7, BIT_7 = 4'd8, BYTE_READY = 4'd9;
reg [3:0] state = 0;
reg [8:0] baud_clock = 0;
reg baud_sync = 0;
reg baud_tick = 0;
reg baud_reset = 0;
always #(posedge clk) begin
if (baud_reset) baud_clock <= 9'd1;
else if (baud_sync) begin
if (baud_clock == 9'd322) baud_clock <= 0;
else baud_clock <= baud_clock + 9'd1;
end
else begin
if (baud_clock == 9'd215) baud_clock <= 0;
else baud_clock <= baud_clock + 9'd1;
end
end
always #(*) begin
baud_tick <= ~|baud_clock;
end
always #(posedge clk or negedge reset_n) begin
if (~reset_n) begin
state <= IDLE;
received_byte <= 8'h0;
end
else begin
case(state)
IDLE: begin
byte_ready <= 0;
if (Rx == 0) begin
state <= BIT_0;
baud_reset <= 1;
baud_sync <= 1;
end
end
BIT_0: begin
baud_reset <= 0;
if (baud_tick) begin
baud_sync <= 0;
received_byte[0] <= Rx;
state <= BIT_1;
end
end
BIT_1: begin
if (baud_tick) begin
received_byte[1] <= Rx;
state <= BIT_2;
end
end
BIT_2: begin
if (baud_tick) begin
received_byte[2] <= Rx;
state <= BIT_3;
end
end
BIT_3: begin
if (baud_tick) begin
received_byte[3] <= Rx;
state <= BIT_4;
end
end
BIT_4: begin
if (baud_tick) begin
received_byte[4] <= Rx;
state <= BIT_5;
end
end
BIT_5: begin
if (baud_tick) begin
received_byte[5] <= Rx;
state <= BIT_6;
end
end
BIT_6: begin
if (baud_tick) begin
received_byte[6] <= Rx;
state <= BIT_7;
end
end
BIT_7: begin
if (baud_tick) begin
received_byte[7] <= Rx;
state <= BYTE_READY;
end
end
BYTE_READY: begin
if (baud_tick) begin
byte_ready <= 1;
state <= IDLE;
end
end
default: state <= IDLE;
endcase
end
end
endmodule
And here is a picture of my simulation results:
For the simulation I sent the bytes 0x55, 0x11, 0x32, 0x63, and 0xFF. The byte_ready signal is asserted at the correct time for each of those bytes (for exactly one clock cycle). My simulation appears to be working perfectly.
I have even simulated for varying errors in baud rate. (Note: I am designing this to work with a baud rate of 115200. The simulation still worked properly.
I have even used the Signaltap logic analyzer to confirm the incoming Rx signal. I even used Signaltap to observe the state progression of the system, but the state literally never changes. It stays right at the start even though I see Rx being received by the FPGA.
I have even changed it up to show different LEDs flashing for the states or bytes received. Nothing lights up.
It appears that the design is not reacting at all.
I am completely lost with regards of what to do next. Any help would be greatly appreciated.
EDIT:
I have managed to get the LEDs reacting. Now however it seems that the bytes I receive is completely random. Probing into the signals I realize the LSB of my state (state[0]) is progressing in a wrong manner, with comparison to the simulation.
It should be toggling for every single Rx bit received, but Signaltap reveals that it's doing something else.
Signaltap and Modelsim waves (The ModelSim one is what's supposed to be happening):
How can I fix this discrepancy?
It would be advisable to register the RX input before using in. The logic that uses it, can see it at different times (in relation to the clock) and some flops might toggle as if RX changed state, while other might not.
Also, it is not advisable to assign signals that are asynchronously reset in the same always block with the ones that aren't.

difference of two number from set of numbers input from file in VHDL

i am trying to find difference of two numbers from set of number available in file. "read.txt" contain numbers as
5
15
25
36
98
654
256
20
354
and i want output as 10 10 11 62 556 398 236 334
but i am getting in my output file "realout.txt" as 0
0
10
11
556
236
236
236
236
236
236
i don't know why every time at starting position 0 is printed and at the end number is repeated 5 times more..please help me to solve this problem my code is here.
library IEEE;
library std;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.all;
use IEEE.MATH_REAL.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use std.textio.all; --include package textio.vhd
entity testvhdl is
end testvhdl;
architecture Behavioral of testvhdl is
constant MAX : integer := 256*256-1;
SIGNAL rstb : std_logic := '0';
SIGNAL clk : std_logic := '0';
SIGNAL a : std_logic_vector(7 downto 0) := (others=>'0');
--Outputs
SIGNAL sum : std_logic_vector(7 downto 0);
--period of clock,bit for indicating end of file.
signal endoffile : bit := '0';
signal d1,d2,intt,n: integer:=0;
signal aa,ab,ac: integer:=0;
signal linenumber : integer:=1;
--signal dbus: std_logic_vector(7 downto 0) := x"00";
--------------------------------------------------------------------------------------------
function CONV_STDLV8bit_2INT(ARG: std_logic_vector (7 downto 0))
return integer is
variable int: integer:=0;
variable tmp: std_logic_vector(7 downto 0);
begin
int :=0;
tmp := ARG;
for i in 0 to 7 loop
if (tmp(i) ='1') then
int := int+(2**i);
else
int := int+0;
end if;
end loop;
return int;
end CONV_STDLV8bit_2INT;
--------------------------------------------------------------------------------------------
function CONV_INT2STDLV(ARG: INTEGER; SIZE: INTEGER)
return STD_LOGIC_VECTOR is
variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0):=x"00";
variable temp: integer:= 0;
begin
temp := ARG;
for i in 0 to SIZE-1 loop
if ((temp mod 2) = 1) then
result(i) := '1';
else
result(i) := '0';
end if;
if temp > 0 then
temp := temp / 2;
elsif (temp > integer'low) then
temp := (temp - 1) / 2; -- simulate ASR
else
temp := temp / 2; -- simulate ASR
end if;
end loop;
return result;
end CONV_INT2STDLV;
--------------------------------------------------------------------------------------------
constant PERIOD : time := 20 ns;
constant DUTY_CYCLE : real := 0.5;
constant OFFSET : time := 30 ns;
begin
-- Instantiate the Unit Under Test (UUT)
--uut: imadder PORT MAP(
-- rstb => rstb,
-- clk => clk,
-- a => a,
-- b => b,
-- sum => sum
-- );
CLOCK: PROCESS -- clock process for clk
BEGIN
WAIT for OFFSET;
CLOCK_LOOP : LOOP
clk <= '0';
WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
clk <= '1';
WAIT FOR (PERIOD * DUTY_CYCLE);
END LOOP CLOCK_LOOP;
END PROCESS;
tb: PROCESS
BEGIN
rstb <='0';
wait for 60ns;
rstb <='1';
wait for 1312us; -- will wait forever
END PROCESS;
reading : process
file infile : text is in "real.txt"; --declare input file 1987
file outfile : text is out "realout.txt"; --declare output file 1987
--file infile2 : text is in "img2.txt"; --declare input file 1987
variable inline,inline2 : line; --line number declaration
variable dataread1 : integer;
variable dataread2 : integer;
variable buff_out : line; --line number declaration
-- variable aa,ab,ac: integer:=0;
begin
wait until clk = '0' and clk'event;
if(n < 10) then
if (not (endfile(infile))) then --checking the "END OF FILE" is not reached.
readline(infile, inline);
readline(infile, inline2);
read(inline, dataread1);
read(inline2, dataread2);
d1 <= dataread1;
d2 <= dataread2;
-- if n mod 5 = 0 then
aa <= abs(d1 - d2);
-- a <= CONV_INT2STDLV(aa,8);
--
-- n <= n+1;
-- elsif (d1 > aa) then
-- ab <= d1 - aa;
-- ac <= ac+ab;
-- aa <= d1;
--
-- else
-- ab <= aa - d1;
-- ac <= ac+ab;
-- aa <= d1;
--
-- end if;
-- d1 <= ac;
--readline(infile2, inline2);
--read(inline2, dataread1);
--d2 <=integer(dataread1);
--b <= CONV_INT2STDLV(d2,8);
else
a<=x"00";
--b<=x"00";
end if;
else
endoffile <='1'; --set signal to tell end of file read file is reached.
end if;
-- end process reading;
--write process #negative edge
--writing : process
-- begin
-- wait until clk = '0' and clk'event;
if(endoffile='0') then --if the file end is not reached.
--intt <= CONV_STDLV8bit_2INT(aa);
if(linenumber > 0) then
n <= n+1;
--if(linenumber>11) then
write(buff_out, aa);
writeline(outfile, buff_out);-- write line to output_image text file.
--end if;
end if;
linenumber <= linenumber + 1;
else
null;
end if;
end process reading;
end Behavioral;
--WRITE (buf, string'("hello"));
--WRITELINE(fileptr,buf);
--WRITE (buf, bit_vector'(" 010111 "));
--WRITELINE(fileptr,buf);
--http://myfpgablog.blogspot.in/2011/12/memory-initialization-methods.html
-- constant MEM_DEPTH : integer := 2**ADDR_WIDTH;
-- type mem_type is array (0 to MEM_DEPTH-1) of signed(DATA_WIDTH-1 downto 0);
-- impure function init_mem(mif_file_name : in string) return mem_type is
-- file mif_file : text open read_mode is mif_file_name;
-- variable mif_line : line;
-- variable temp_bv : bit_vector(DATA_WIDTH-1 downto 0);
-- variable temp_mem : mem_type;
-- begin
-- for i in mem_type'range loop
-- readline(mif_file, mif_line);
-- read(mif_line, temp_bv);
-- temp_mem(i) := signed(to_stdlogicvector(temp_bv));
-- end loop;
-- return temp_mem;
-- end function;
-- constant mem : mem_type := init_mem("mem_init_vhd.mif");
...i don't know why every time at starting position 0 is printed and at the end number is repeated 5 times more..please help me to solve this problem my code is here.
Besides the wild context clauses and all the extraneous noise there are two things observably wrong here. First you proposed input data set for real.txt has an odd number of lines (elements - integers). Second you are misapplying the BIT signal endofile:
reading :
process
file infile : text is in "real.txt";
file outfile : text is out "realout.txt";
variable inline,inline2 : line;
variable dataread1 : integer;
variable dataread2 : integer;
variable buff_out : line;
begin
wait until clk = '0' and clk'event;
if(n < 10) then
if (not (endfile(infile))) then
readline(infile, inline);
readline(infile, inline2);
read(inline, dataread1);
read(inline2, dataread2);
d1 <= dataread1;
d2 <= dataread2;
aa <= abs(d1 - d2);
else
a<=x"00";
end if;
else
endoffile <='1';
end if;
if(endoffile='0') then
if(linenumber > 0) then
n <= n+1;
write(buff_out, aa);
writeline(outfile, buff_out);
end if;
linenumber <= linenumber + 1;
else
null;
end if;
end process reading;
This is what your design with less than 20 integers on separate lines looks like:
As you can see from the waveform that results in the last value being repeated (the falling edge of the following clocks).
I added the 720 so it wouldn't get an integer read fail assertion.
The first two zeros are from not holding off output when rstb is true and a pipeline delay loading d0, d1 on a falling clock edge and then assigning aa on the next clock edge. There isn't a pipeline signal to qualify aa as valid for output.
endofile will never get written to a '1' where that assignment is unless your data set is big enough. n is counting input pairs of integers (pairs of lines):
So endofile should be fixed (on two counts, it's not set when an end of file condition is actually encountered, and the second readline is assumed to have been successful).
There's a third thing wrong, with enough data from real.txt you're missing the last absolute difference value in realout.txt, which says that pipeline signal specifying aa is valid should have a hold over as well as a hold off.
It might be easier to fix this by troubleshooting waveforms.
For the portion of your code not commented out the context clause should look like this:
library IEEE;
use ieee.std_logic_1164.all;
use std.textio.all;