module mac #(
parameter integer A_BITWIDTH = 8,
parameter integer B_BITWIDTH = A_BITWIDTH,
parameter integer OUT_BITWIDTH = 20,
parameter integer C_BITWIDTH = OUT_BITWIDTH - 1
)
(
input clk,
input rstn,
input en,
input add,
input [A_BITWIDTH-1:0] data_a,
input [B_BITWIDTH-1:0] data_b,
input [C_BITWIDTH-1:0] data_c,
output reg done,
output [OUT_BITWIDTH-1:0] out
);
localparam
STATE_IDLE = 2'b00,
STATE_MULT = 2'b01,
STATE_ACCM = 2'b10;
reg [1:0] state;
reg signed [OUT_BITWIDTH-1:0] out_temp;
reg signed [A_BITWIDTH-1:0] data_a_bf;
reg signed [B_BITWIDTH-1:0] data_b_bf;
reg signed [C_BITWIDTH-1:0] data_c_bf;
assign out = out_temp;
always # (posedge clk or negedge rstn) begin
if(!rstn) begin
state <= STATE_IDLE;
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
done <= 1'b0;
out_temp <={OUT_BITWIDTH{1'b0}};
end
else begin
case(state)
STATE_IDLE: begin
// TO DO
// Done flag reset!
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
out_temp <={OUT_BITWIDTH{1'b0}};
done <= 1'b0;
if(en && !done) begin
// If en == 1 and done != 1, then running state.
// And capture data_a, data_b, data_c to buffer
data_a_bf <= data_a;
data_b_bf <= data_b;
data_c_bf <= data_c;
state <= STATE_MULT;
end
else begin
// If not, just waiting for condition.
end
end
STATE_MULT: begin
// TO DO;
if (!add) begin
// If add signal is low, do muliply with data_a_bf and data_b_bf.
//out_temp <= data_a_bf * data_b_bf;
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
end
else begin
// If add signal is high, shift data_a_bf to match bit representation.
//out_temp <= {data_a_bf, 8'b0};
out_temp <= {data_a_bf, 8'b0};
end
state <= STATE_ACCM;
end
STATE_ACCM: begin
// TO DO
// Do add and make output 'done' flag high.( done = 1)
out_temp <= out_temp + data_c_bf;
done <= 1'b1;
state <= STATE_IDLE;
end
default:;
endcase
end
end
endmodule
I want to do 'bit select' concatenation of data_a_bf signed extension * data_b_bf signed extension and assign it to out_temp, but it occurs a syntax error. How can I do this?
I don't know how to do bit select of it.
I think you just need to see error line.
I just upload all code.
Selecting a bit of a concatenation is a feature of SystemVerilog, not Verilog. Make sure your file has a .sv file extension. The tool that you are using might also have a switch to turn on support for SystemVerilog.
A Verilog friendly solution would be to create a bit mask.
For example, change:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
To:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}} & 'h0FFFF;
Related
I have a question about VHDL. The following code is for a player turn selector in a game. It simulates well, but when I generate a bit stream it has a warning that says:
"[Synthesizer 8-327] infer latch for variable 'teToca_reg' [" C: /...../ Eleccion.vhd ": 137]"
The main problem is generated by an assignment made in a process, which I need in order for the "cambio" signal to receive the first value of the turn in that game, and to be able to change after each time B1 is pressed. The problem appears because the assignment is done later combinationally in the opposite direction so that the output "teToca" takes the changed value.
The signal "FinPartida" is set to 1 when a game ends and "win" gives a value, so "teToca" receives a new value.
proceso_switch: process(clk,reset)
begin
if reset = '1' then
cambia <= '0';
elsif clk'event and clk='1' then
if FinPartida='1' then
cambia <= tetoca; --LATCH
elsif state = S_JUEGO and flanco='1' and B1='1' and posicion/=9 and pos1(posicion)='0' and pos2(posicion)='0' then
cambia <= NOT cambia; --OK
end if;
end if;
end process;
teToca <= empieza when state = S_ESPERA and reset = '0' else
'0' when state = S_ESPERA and reset = '1' else
--PLATCH--
cambia when state = S_JUEGO AND (flanco='1' and B1='1' and posicion/=9 and pos1(posicion)='0' and pos2(posicion)='0') else
--LATCH--
'0' when state = S_JUEGO AND win="001" else
'1' when state = S_JUEGO AND win="100";
turno <= teToca;
In VHDL '93 the compiler told me it found 0 possible definitions for operator "=".
It causes an error with the following error message:
Error (10327): VHDL error at mst_fifo_fsm.vhd(171): can't determine definition of operator ""="" -- found 0 possible definitions
Line 171 is at the first assignment of ifsm_cond(0):
process(clk, rst_n)
begin
if (rst_n = '0') then
ifsm_cond <= "0000";
elsif (rising_edge(clk)) then
if (mltcn = '0') then
ifsm_cond(0) <= (cur_stap1 = IDLE) AND (not imst_rd_n(0)) AND (not rxf_n) AND (not ibuf_ful(0));
ifsm_cond(1) <= (cur_state = MTRD) AND ( imst_rd_n(0) OR (rxf_n AND (not rxf_n_p1)) OR ibuf_ful(0)) ;
ifsm_cond(2) <= (cur_state = MDLE) AND (not imst_wr_n(0)) AND (not txe_n)& (ibuf_nep(0) OR stren OR w_1byte) AND (not w_1flag);
ifsm_cond(3) <= (cur_stap3 = MTWR) AND ( imst_wr_n(0) OR (txe_n AND (not txe_n_p1)) OR r_oobe OR ((not ififonempt(0)) AND (not stren) AND (not prefnempt(0))));
else
ifsm_cond(0) <= (not imst_rd_n(conv_integer(ichannel))) AND (not irxf_n(conv_integer(ichannel))) AND (not ibuf_ful(conv_integer(ichannel))) AND (cur_stap3 = IDLE);
ifsm_cond(1) <= ( imst_rd_n(conv_integer(ichannel)) OR (rxf_n & (not rxf_n_p1)) OR ibuf_ful(conv_integer(ichannel))) AND (cur_state = MTRD);
ifsm_cond(2) <= (not imst_wr_n(conv_integer(ichannel))) AND (not itxe_n(conv_integer(ichannel))) AND (ibuf_nep(conv_integer(ichannel)) OR stren) AND (cur_stap3 = MDLE);
ifsm_cond(2) <= (not imst_wr_n(conv_integer(ichannel))) AND (not itxe_n(conv_integer(ichannel))) AND (ibuf_nep(conv_integer(ichannel)) OR stren) AND (cur_stap3 = MDLE);
ifsm_cond(3) <= ( imst_wr_n(conv_integer(ichannel)) OR (rxf_n AND
(not rxf_n_p1)) OR ((not ififonempt(conv_integer(ichannel)) AND (not stren)
AND (not prefnempt(conv_integer(ichannel)))))) AND (cur_stap3 = MTWR);
end if;
end if;
end process;
I guess it is at the statement (cur_stap1 = IDLE).
cur_stap1 is a user defined signal with the following declaration:
type states is (IDLE, MTRD, MDLE, MTWR);
signal cur_state, next_statem, cur_stap1, cur_stap2, cur_stap3, cur_stap4 :
states;
I thougt of one possible solution to clarify first in a conditional concurrent signal assignment if cur_stap1 is IDLE and assign this to a signal which replaces (cur_stap1 = IDLE). But I have some more lines with other statements like this.
Is there a better solution to solve this issue? This concurrent signal assignment is done in a process. Should I rather try an IF ELSIF END IF statement for the whole line?
Thank you in advance.
The problem is that not imst_rd_n(0) returns a std_logic type, while cur_stap1 = IDLE returns a boolean type. There is no and operator that accepts both types, thus the compiler tries to solve it another way: by looking for an = operator defined for your custom type (state) that returns a std_logic, which there isn't. Hence the error.
Instead of not imst_rd_n(0), you should write imst_rd_n(0)='0' and so on. This returns a boolean and a boolean and operator is defined. Imho it's also better for readability.
You should then write your assignment in an if statement.
If [boolean expression] then
[Signal] <= '1';
Else
[Signal] <= '0';
End if;
Also try to design a state machine with a simple output:
Case [current_state] is
When [state 1] =>
If ....
When ....
End case;
You can work with default assignment.
Example:
if rising_edge(clk) then
ifsm_cond <= (others => '0'); -- default assignment
case cur_state is
when IDLE =>
if imst_rd_n(0)='0' AND rxf_n='0' AND ibuf_ful='0' then
ifsm_cond(0) <= '1';
end if;
when MTRD =>
if imst_rd_n(0)='1' OR (rxf_n='1' AND rxf_n_p1='0') OR ibuf_ful(0)='1' then
ifsm_cond(1) <= '1';
end if;
etc.
I would not write a function for operator = for two input's type states that returns a std_logic, as that could lead to other unwanted conflicts. I would instead propose to make a casting function from boolean to std_logic. E.g.:
function to_std_logic(input : boolean) return std_ulogic is
begin
if input then
return '1';
end if;
return '0';
end function;
Usage example: ifsm_cond(0) <= to_std_logic(cur_stap1 = IDLE) AND (not imst_rd_n(0)) AND (not rxf_n) AND (not ibuf_ful(0));
I'm getting an error during CheckSyntax for the following code I've tried. The error says:
"Line 48. parse error, unexpected VARIABLE Line 53. Undefined symbol 'InOutDetector'.
Line 57. InOutDetector: Undefined symbol (last report in this block)".
Can you let me know how should I fix this?
Here is an image of my code, as I could not paste it.
https://www.dropbox.com/s/ay8pjq4ojoep6ry/RoomLightController.png?dl=0
entity Room_Light_Controller is
port (
clk, sA, sB: IN STD_LOGIC;
sL: OUT STD_LOGIC
);
end Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
SIGNAL People : INTEGER:=0;
SIGNAL AllowNextCount : BIT:='0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
variable InOutDetectorDetector: integer;
process (clk)
begin
if ((sA = '0') and (sB = '1')) then
-- entering
InOutDetector := 1;
end if;
if ((sA = '1') and (sb = '0')) then
-- exiting
InOutDetector := -1;
end if;
if ((sA ='1') and (sB = '1') and (AllowNextCount = '1')) then
-- only when both sensors are touched validate the people counter
People := People+InOutDetector;
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if ((sA = '0') and (sB = '0')) then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if (People > 0) then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end Behavioral;
In addition to the error Amir notes that there is a name mismatch and the variable is declared in the wrong place, there is an additional error with the assignment to People:
library ieee;
use ieee.std_logic_1164.all;
entity Room_Light_Controller is
port (
clk, sA, sB: in std_logic;
sL: out std_logic
);
end entity Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
signal people: integer := 0;
signal allownextcount: bit := '0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
-- variable InOutDetectorDetector: integer;
process (clk)
variable InOutDetector: integer; -- as per Amir
begin
if sA = '0' and sB = '1' then
-- entering
InOutDetector := 1;
end if;
if sA = '1' and sb = '0' then
-- exiting
InOutDetector := -1;
end if;
if sA ='1' and sB = '1' and AllowNextCount = '1' then
-- only when both sensors are touched validate the people counter
People <= People + InOutDetector; -- was :=, signal assignment
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if sA = '0' and sB = '0' then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if People > 0 then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end architecture Behavioral;
People is a signal and requires the signal assignment symbol (<=) not the variable assignment symbol (:=).
After the two changes the VHDL design specification analyzes and elaborates.
Notice a context clause has been added to make your code a Minimal, Verifiable and Complete example.
Also note in the Help Center web page on Minimal, Complete, and Verifiable example the section Minimal and readable,
..Use consistent naming and indentation, and include comments if needed to explain portions of the code.
If this code were intended to be synthesize you might likely need to constrain the integers.
For execution efficiency all the independent if statements could be consolidated using elsif. That's hardly an issue in a small design, but the binary patterns described for sA and sB are mutually exclusive (while not exhaustive for type std_logic).
You neglected to provide the complete error messages, which appear to be output from XST. Historically the recommended design flow includes simulation, which if for no other purpose provides better syntax error messages from VHDL analysis.
XST historically assumes you are handing it a design description that is syntax error free, and is other wise quite sparse in providing adequate error messages.
The error message prefix (e.g. ERROR:HDLParsers:1209) can tell you how to find the problem via Xilinx's support site and/or documentation.
Declare the variable inside the process and rename it to (InOutDetector). You used (InOutDetector) inside the process.
Then if you want to run the process on clk rising edge, complete your process such as the following code :
process(clk)
variable InOutDetector : integer;
begin
if clk = '1' and clk'event then
-- your code
end if;
end process;
However if you don't want to use the clk rising edge, just complete the sensitivity list with parameters that you read or check it inside the process (sA,sB,AllowNextCount,People) and remove clk from the process sensitivity list.
Also be careful about incomplete if statements. Latches may be generated from incomplete case or if statements.
I am writing something in verilog in quartus, and appeared to me something strange, but pretty simple actually
This code increments the address correctly
module counter(
input wire clock,
input wire reset,
output reg [4:0]address
);
initial
begin
address = 5'b0
end
always#(posedge clock)
begin
if(reset)
begin
address <= 5'b0;
end
else
begin
address <= address + 5'b00001;
end
end
endmodule
this, the bits that change become not matter, it happens when I start the output to something other than 0
module counter(
input wire clock,
input wire reset,
output reg [4:0]address
);
initial
begin
address = 5'b11101;
end
always#(posedge clock)
begin
if(reset)
begin
address <= 5'b0;
end
else
begin
address <= address + 5'b00001;
end
end
endmodule
Does anyone know any way to solve this problem?
While it is difficult to tell exactly what you are saying, it seems you are curious as to why changing the starting value in the initial block seems to have no affect on where the counter starts.
It seems you are likely performing a reset as part of your testbench, so when you look at address, the value always starts at 0 (because the initial block setting is changed by the reset in the always block).
This part is suspicious to me:
if(reset)
begin
address <= 5'b0;
end
Should be:
if(reset)
begin
address <= 5'b00000;
end
You can try use this implementation with load and start signal:
module Counter(load,clk,start,data_in,data_out);
input load;
input clk;
input start;
input [5-1:0] data_in;
output [5-1:0] data_out;
reg [5-1:0] tmp;
initial
begin
tmp = 5'b0000;
end
always # ( posedge clk)
begin
if(~start)
begin
tmp <= 5'b0000;
end
else if(load)
tmp <= data_in;
else
tmp <= tmp + 1'b1;
end
assign data_out = tmp;
endmodule
I have a variable number of modules linked to another module via a signal bus : std_logic_vector(NUM-1 downto 0), with each component using 8 bits, so that:
bus(7 downto 0) = first module
bus(15 downto 8) = second module
As for creating the instances and doing the port mapping, that is easily done with a
INST: for i in 0 to NUM-1 generate
Inst_module port map ( bus => bus(i*8+7 downto i*8) );
end generate INST;
My question:
I would like to be able to interface with each module via a FSM (since it needs to do some other things too), so would like to be able to 'generate' the following code, rather than having to write out each state manually (Where signal empty : std_logic_vector(NUM-1 downto 0) is a status flag for each module)
type state_type is (st0_idle, st1_work0, st1_work1 --,etc.)
signal state : state_type;
begin
process(empty)
begin
if RESET = '1' then
--reset FSM
state <= st0_idle;
else
if CLK'event and CLK='1' then
case state is
when st0_idle =>
if empty(0) = '0' then
state <= st1_work0;
elsif empty(1) = '1' then
state <= st1_work1;
--etc.
end if;
when st1_work0 =>
bus(7 downto 0) <= SOMETHING;
state <= st0_idle;
when st1_work1 =>
bus(15 downto 8) <= SOMETHINGELSE;
state <= st0_idle;
--etc..
end if;
end if;
end process;
As you can see, there is a lot of repetition. But I can't simply put a for-generate inside the case, so what should I do?
One good way to make processes with state machines more readable is to merge common code into procedures defined within the process. For example:
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st0_idle => ...
when st1_work0 => assign_something(0, something, st0_idle);
when st1_work1 => assign_something(1, something_else, st0_idle);
-- ... etc ...
end case;
if reset = '1' then
state <= st0_idle;
end if;
end procedure;
Hopefully you get the idea. Depending on how regular the state machine structure is, you may also want to replace the enumerated state variables that correspond to each index with a simple count or index variable that you keep track of along with the named state.
That's all up to you, but however you do it, using procedures to factor out common code whenever you can will probably make your VHDL much easier to work with.
Applying this change would make the code look something like this:
architecture ...
type state_type is (st_idle, st_work);
signal state : state_type;
signal index : integer range 0 to NUM-1;
...
begin
...
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st_idle =>
for i in 0 to NUM-1 loop
if empty(i) = '1' then
index := i;
exit;
end if;
end loop;
when st_work => assign_something(index, something, st_idle);
end case;
if reset = '1' then
state <= st_idle;
end if;
end procedure;
Obviously this has to be changed to match exactly what you want to do ... =)