Reset variable in a sequential case statement in verilog - variables

I want to give only one strobe pulse of 2 clock cycles wide everytime a data is placed on the output. I am not able to implement the logic in verilog.Here is the pseudocode i have written
reg [1:0] step = 2'b00;
always # (posedge clock)
begin
case (switch)
1'b0 : begin
load data 1;
flag <= 1;
end
1'b0 : begin
load data 2;
flag <= 1;
end
endcase
if (flag == 1)
case (step)
2'b00 : strobe high;
2'b01 : wait;
2'b10 : strobe low;
2'b11 : flag <=0;
endcase
end
If I do this the reg step is becoming 2'b11 after properly giving the strobe pulse after the first data, but I am not able to reset it to zero again for the second data, so when second time flag is set high the step variable only enters the last case. If I set step <= 2'b00 elsewhere the strobe output is constantly changing with each clock cycle. I want only one pulse.
Actual Code :
`timescale 1ns / 1ps
module test3(
input i_clock,
input i_switch,
output reg [7:0] o_data = 8'b00001111,
output reg o_strobe = 1'b0
);
reg flag = 1'b0;
reg [1:0] step = 2'b00;
always # (posedge i_clock)
begin
if (flag == 1'b0)
begin
case (i_switch)
1'b0 : begin
o_data [7:0] <= 32'b00000000;
flag <= 1'b1;
end
1'b1 : begin
o_data [7:0] <= 32'b11111111;
flag <= 1'b1;
end
endcase
end
else if (flag == 1)
begin
case (step)
2'b00 : begin
o_strobe <= 1'b1;
step <= 2'b01;
end
2'b00 : begin
step <= 2'b10;
end
2'b10 : begin
o_strobe <= 1'b0;
step <= 2'b11;
end
2'b11 : begin
flag <= 1'b0;
// step <= 2'b00;
end
endcase
end
end
endmodule
Waveforms:
No strobe on 2nd data, step <= 2'b00 commented
http://i30.photobucket.com/albums/c315/soumyabumba/strobe_zpsc342b740.gif
Continuous toggling strobe, step <= 2'b00 uncommented
http://i30.photobucket.com/albums/c315/soumyabumba/pulse_strobe_zps8a1a5fb4.gif

Thank a lot Tim. I solved it and its only because of your helpful suggestion to add the flag and step waveforms. The main problem was that the case(switch) is getting executed on each clock cycle with the switch value of previous cycle and it is triggering the flag which is there under each statement. So I removed the case(i_switch) from always # (i_clock) and put it separately in an always # (i_switch) so that the case(switch) runs only when the switch is changed.
I am facing a minor problem though. Since I have added the always#(i_switch) block I am having doubts on initializing the i_switch input in the test bench file. If I initialize it before the global reset of 100# the o_data is starting as 00000000 instead of 00001111 i.e. the case statement started running even before the global reset completes. If i give i_switch as a stimulus after 100# a red line and a X is coming for i_switch for 100# indicating uninitialized input. I have attached the waveform and the solved code. Will there be any problem in implementation of this? Also I read somewhere all if statement must follow by else statement otherwise unwanted latching may occur, what can be written under else (flag == 0) condition under always #(i_clock)?
Waveform :
http://i30.photobucket.com/albums/c315/soumyabumba/strobe_solved_zps72b65a42.png
Solved Code:
`timescale 1ns / 1ps
module test3(
input i_clock,
input i_switch,
output reg [7:0] o_data = 8'b00001111,
output reg o_strobe = 1'b0
);
reg flag = 1'b0;
reg [1:0] step = 2'b00;
always # (i_switch)
begin
case (i_switch)
1'b0 : begin
o_data [7:0] <= 32'b00000000;
flag <= 1'b1;
end
1'b1 : begin
o_data [7:0] <= 32'b11111111;
flag <= 1'b1;
end
endcase
end
always # (posedge i_clock)
begin
if (flag == 1)
begin
case (step)
2'b00 : begin
o_strobe <= 1'b1;
step <= 2'b01;
end
2'b01 : begin
step <= 2'b10;
end
2'b10 : begin
o_strobe <= 1'b0;
step <= 2'b11;
end
2'b11 : begin
flag <= 1'b0;
step <= 2'b00;
end
endcase
end
end
endmodule

Related

Strange RTL output

[Yosys 0.8]
A colleague of mine threw some random verilog code to Yosys to see how it reacts.
Here it is:
module top(input clk, input led, output led2, output to_port1,output [24:0] to_port2);
reg ctr = 0;
reg[24:0] counter = 2;
always#(posedge clk) begin
if (ctr == 1) begin
ctr <= 0;
counter <= counter + 1;
end
else
ctr <= 1;
end
assign led2 = ctr;
assign to_port1 = led;
assign to_port2 = counter;
endmodule
and Yosys, with command yosys -o synth.v x.v throws:
module top(clk, led, led2, to_port1, to_port2);
reg [24:0] _0_;
reg _1_;
reg [24:0] _2_;
reg _3_;
wire [31:0] _4_;
wire _5_;
input clk;
reg [24:0] counter;
reg ctr;
input led;
output led2;
output to_port1;
output [24:0] to_port2;
assign _4_ = counter + 32'd1;
assign _5_ = ctr == 32'd1;
always #* begin
_3_ = 1'h0;
end
always #* begin
end
always #({ }) begin
ctr <= _3_;
end
always #* begin
_2_ = 25'h0000002;
end
always #* begin
end
always #({ }) begin
counter <= _2_;
end
always #* begin
_1_ = ctr;
_0_ = counter;
casez (_5_)
1'h1:
begin
_1_ = 1'h0;
_0_ = _4_[24:0];
end
default:
_1_ = 1'h1;
endcase
end
always #(posedge clk) begin
ctr <= _1_;
counter <= _0_;
end
assign led2 = ctr;
assign to_port1 = led;
assign to_port2 = counter;
endmodule
Some constructs end up being complicated. This result code above cannot be compiled by recent verilog compilers when the original can.
Why the always #({ }) begin construct and empty always #* begin?
Is there an option we missed?
Thanks
In general you should always run proc (-p proc) between reading and writing Verilog, due to the nature of Yosys' internal representation of the read-in Verilog

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

VHDL Dynamic slicing using mathematical expression

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.

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;