[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
Related
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
Im trying to build an moving average module. It should use the number of values to use as parameter.
How do I get the sum of all n tmp-registers using a for- or gernerate-block within one clock-cylce?
reg [WORDLEN - 1:0] tmp [SIZE - 1:0];
reg [WORDLEN + SIZE / 2 - 1:0] sum;
always #(posedge clk)
sum <= sum(tmp) // Like <= tmp[0] + tmp[1] + ... + tmp[SIZE-1]
Loops like this tend to be easier to understand if you first break apart the synchronous and combinatorial parts. First we have a combinatorial loop which unrolls to a configurable number of adds. Then imply a flip-flop on the result.
integer i;
reg [WORDLEN + SIZE / 2 - 1:0] sum_comb;
always #* begin
sum_comb = 'd0;
for( i=0; i< SIZE; i=i+1) begin
sum_comb = sum_comb + tmp[i];
end
end
always #(posedge clk) begin
sum <= sum_comb;
end
If you use SystemVerilog, you can just write:
always #(posedge clk)
sum <= tmp.sum;
Below is a complete sample code:
module test;
parameter WORDLEN = 8;
parameter SIZE = 4;
reg [WORDLEN - 1:0] tmp [SIZE - 1:0];
reg [WORDLEN + SIZE / 2 - 1:0] sum;
logic clk = 0;
initial begin
tmp = '{ '{1}, '{4}, '{6}, '{7}};
forever begin
clk = ~clk;
#10;
tmp [0] = tmp[0] + 1; //Increment tmp[0] twice during each clock for testing
end
end
always #(posedge clk) begin
sum <= tmp.sum ;
$display ("sum(tmp) = sum(%p) = %d", tmp, sum) ;
end
endmodule
output:
# sum(tmp) = sum('{1, 4, 6, 7}) = 18
# sum(tmp) = sum('{1, 4, 6, 9}) = 20
# sum(tmp) = sum('{1, 4, 6, 11}) = 22
# sum(tmp) = sum('{1, 4, 6, 13}) = 24
# sum(tmp) = sum('{1, 4, 6, 15}) = 26
# sum(tmp) = sum('{1, 4, 6, 17}) = 28
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
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.
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;