In this other question I asked I got some general advice regarding my module.
Now I seek advice here since I noted that the Verilog community has more users.
I am trying to implement into an existing framework a Most Significant Bit (MSB) operation.
The idea is as follows: I am getting 32 bit complex samples in from ddc_out_strobe, which are 16 bit I and 16 bit Q.
My idea is to combine 4 "cutted" samples into a new sample to feed to the output bb_sample. This is done by getting the 4 MSB out of I0,Q0,I1,Q1,I2,Q2,I3,Q3 (4*8 = 32 bit total) and wiring them every 4th bb_strobe to bb_sample.
Here you can see my implementation:
module my_rx_dsp0_custom
#(
//frontend bus width
parameter WIDTH = 24
)
(
//control signals
input clock, //dsp clock
input reset, //active high synchronous reset
input clear, //active high on packet control init
input enable, //active high when streaming enabled
//user settings bus, controlled through user setting regs API
input set_stb, input [7:0] set_addr, input [31:0] set_data,
//full rate inputs directly from the RX frontend
input [WIDTH-1:0] frontend_i,
input [WIDTH-1:0] frontend_q,
//full rate outputs directly to the DDC chain
output [WIDTH-1:0] ddc_in_i,
output [WIDTH-1:0] ddc_in_q,
//strobed samples {I16,Q16} from the RX DDC chain
input [31:0] ddc_out_sample,
input ddc_out_strobe, //high on valid sample
output ddc_out_enable, //enables DDC module
//strobbed baseband samples {I16,Q16} from this module
output [31:0] bb_sample,
output bb_strobe //high on valid sample
);
reg [3:0] i_msb;
reg [3:0] q_msb;
reg [31:0]temp_buff = 0;
reg [31:0]my_zeros = 0;
reg [1:0] count = 0;
always #(posedge clock)
if(ddc_out_strobe) begin
i_msb <= ddc_out_sample[31:28];
q_msb <= ddc_out_sample[15:12];
temp_buff <= {i_msb,q_msb,temp_buff[31:24]};
// to avoid if-else conditions
count <= (count==2'd3) ? 2'd0 : (count+1);
end
// to avoid if-else conditions
assign bb_strobe = (count==2'd3) ? 1'b1 : 1'b0;
assign bb_sample = (count==2'd3) ? temp_buff : my_zeros;
assign ddc_out_enable = enable;
assign ddc_in_i = frontend_i;
assign ddc_in_q = frontend_q;
endmodule //my_rx_dsp0_custom
(1) When trying to build the FPGA images I get the following warning (I just show you the one for 23, but it is the same for other ones):
WARNING:Xst:1896 - Due to other FF/Latch trimming, FF/Latch <temp_buff_23> has a constant value of 0 in block <my_rx_dsp0_custom>. This FF/Latch will be trimmed during the optimization process
I have searched this problem in SE and found some good explanations on what might be going wrong, here or here for example.
What I understand is the following: temp_buff <= {i_msb,q_msb,temp_buff[31:24]}; is a conflictive line since the <= operator is getting the old values from i_msb and q_msb, and not the ones from the MSB operation.
(2) I tried avoiding if-else conditions to allow me to declare some things out of the always #* block (this way I avoid having a wire on the LHS of an always block, which is not allowed).
Are my conditionals correct?
As I explained before, I want only every 4th bb_sample to be assigned.
Is assign bb_strobe = (count==2'd3) ? 1'b1 : 1'b0; getting the effect I want despite not being in the always #(posedge clock) block?
If other infos are needed, please let me know. This is part of a much bigger project that I am trying to modify for my purposes.
(1) The trimmed FF/Latch warning is not due to non-blocking assignments. It is from 24 bits of the temp_buff register always being assigned to zeros. The RHS is 16bits; i_msb (4 bits), q_msb (4 bits), and temp_buff[31:24] (8 bits). And you are assigning it to a 32bit value. The assignment:
temp_buff <= {i_msb,q_msb,temp_buff[31:24]};
Is equivalent to:
temp_buff <= {16'h0000, i_msb,q_msb,temp_buff[31:24]};
This means temp_buff[31:16] will always be zero can can be optimized out. temp_buff[7:0] can also be optimized out to constant zeros because it is assigned to temp_buff[31:24] which is a constant 0. Perhaps you meant you shift right 8 bits like so:
temp_buff <= {i_msb,q_msb,temp_buff[31: 8 ]};
(2) You are correct that wires should not be assigned with any always block (or initial block). However you could have turned the wire to a reg. It is a miss conception that reg is for registers only (FF/Latches). reg in a properly coded combinational block will create combinational logic (no FF or Latches). Property meaning the reg is assigned within every branching condition withing the always block, else it infers a latch. Example
module my_rx_dsp0_custom
/* ... your original code ... */
output reg [31:0] bb_sample,
output reg bb_strobe //high on valid sample
);
/* ... your original code ... */
always #(posedge clock)
if(ddc_out_strobe) begin
temp_buff <= {i_msb,q_msb,temp_buff[31:8]};
count <= (count==2'd3) ? 2'd0 : (count+1);
end
always #*
begin
i_msb = ddc_out_sample[31:28];
q_msb = ddc_out_sample[15:12];
bb_strobe = (count==2'd3);
bb_sample = bb_strobe ? temp_buff : 32'd0;
end
assign ddc_out_enable = enable;
/* ... your original code ... */
Related
I am working on a project where I am required to code the WM8731 audio codec chip on the Altera DE1 board. The project is very basic. It does not need to process the input audio signals. The signal from the input should be directly relayed to the output.
The main task is to set up the codec chip via the I2C protocol. I am new to VHDL and I am having some issues understanding the concept.
Prior to use the codec chip needs to be initialised. This consists of passing sets of data via the I2C. The data to be passed is given below along with the description.
constant sdin_load : std_logic_vector (11*24-1 downto 0)
--this contains codec configuration data
Problem - The main clock frequency is 50MHz, and the I2C bus frequency is 100KHz. So the projects ask to have:
1) declare the bit counter; -- bit counter, runs at 100kHz,
2) declare the word counter; -- word counter, runs at about 5kHz
3) declare the counter for the bit length; -- frequency divider counter which runs at 50MHz
What I understand is that since the main clock and the I2C clock are of different frequency we need to have a counter to keep track of event. My understanding:
1) The bit counter can count from 1 to 500 which is 50MHz/100KHz. So whenever the counter goes to 500 next bit of information is transferred.
2) This is the part which I do not understand. If the word counter runs at 5KHz then it will only count 20 pulses of the I2C clock (100KHz/5KHz) not the 29 bit of information that it is sending.
3) Finally, why do we need to declare a counter to bit length that runs at 50MHz? We already have the clock running at that frequency.
We have been given a sample code. for the implementation of the counter. I am attaching the complete architecture for reference.
library ieee;
use ieee.std_logic_1164.all;
entity codec_init is
port
(
CLOCK_50 : in std_logic; -- master clock
RES_N : in std_logic; -- reset, active 0
SCLK : out std_logic; -- serial clock
SDIN : out std_logic -- serial data
);
end entity;
architecture rtl of codec_init is
constant sdin_load : std_logic_vector (11*24-1 downto 0)
--this contains codec configuration data
begin
process (CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
-- reset actions
if (RES_N = '0') then
-- reset the counters to an appropriate state
...; -- load the frequency divider,
-- 50MHz/500=100kHz bus speed
...; -- load the shift register
...; -- load the bit counter,
-- 29 bits in the word protocol
...; -- load the word counter, 11 words
-- reset the outputs to an appropriate state
...;
...;
elsif (...) then -- deadlock in the end
-- do nothing, wait for the next reset
-- modify reference counters
-- for frequency divider, bits and words
elsif (...) then -- at the end of each bit
...; -- reload the frequency divider counter
if (bcnt = 0) then -- at the end of each word
...; -- reset the bit counter
...; --modify the word counter
else -- the bit is not the end of a word
...; --modify the bit counter
end if;
else -- if not the end of the bit
...; -- modify the frequency divider
end if;
-- generating SCLK, it is going up and then down inside each bit
if (...) then -- condition when SCLK goes up
...;
elsif (...) then -- condition when SCLK goes down
...;
end if;
-- generating serial data output
if (...) then -- start transition condition
...;
elsif (...) then -- ack bit condition
...;
elsif (...) then -- stop transition condition
...;
elsif(...) then -- condition for the non-special bits
...; -- shifting
...;
end if;
-----------------------------
end if;
end process;
-- forming the output with high impedance states for ack-s
SDIN <= 'Z' when (...condition for ack bits...)
else (sdout);
end rtl;
Thanks.
This may not be the answer that you are looking for, but I will post it as it may be useful.
If your main goal is to just program your audio chip, and not necessarily fight with I2C protocol, you may use I2C block from for example OpenCores. You can find there quite good projects. I can't recommend particular one for I2C, but there are many I2C projects, that you can try.
Another place there you can try looking for IPs is Altera's IP library. I don't know if there is one for I2C there, because I work with Xilinx devices, but you can try.
EDIT:
Ok, I will also refer more to actual question, as probably your task to really implement i2c.
As far as I can see, you are asked to have counters, not clocks. This is not the same. And for this 5KHz - it is said that it will be about 5KHz, probably because of the reason you already pointed out.
And if you ask about what do you need this counters for, I guess for:
Clock for sending data
You have to count words to know when to stop transmission.
This is for bit length, so maybe this 50MHz should be 50KHz? It would be more reasonable.
Read carefully what it is given to you in comments of this code.
I am new to vhdl and I have a question that I could not find an answer to.
I am trying to implement some algorithm that operates on a vector 1024 bits long. So I have to read data from a file and insert them in this temp_vector(1023 downto 0).
The file contains many inputs and for each one the algorithm operates on the output of the previous one. The problem is that the length of this input data is not constant, but each input length varies from 0 to 16000.
In each cycle I can only read 64 bits from my testbench and insert them. At specific moments I also have to append sequences of bits of variable length to the already inserted data. I use the integer bit_position to keep track of the last position of temp_vector I inserted data in, and the integer data_in_length to tell me the actual length of the data that I read in each cycle.
After temp_vector is full or I finished inserting all the input, I stop reading and the algorithm operates on temp_vector and then the reading from the file resumes.
I get correct results in simulations. The problem I have is with FPGA and ASIC synthesis. It has to do with the varying length of the input data.
I came up with two approaches in order to read the file and insert the data to temp_vector.
First
temp_vector_proc : process(clk, rst_n)
begin
if rst_n = '0' then
state <= RESET;
elsif clk'event and clk = '1' then
case state is
when RESET =>
state <= TAKING_DATA;
enable_calculations <= '0';
bit_position <= 0;
temp_vector <= (others => '0');
when TAKING_DATA =>
if take_data = '1' then
for i in 0 to 63 loop
temp_vector(i+bit_position) <= data_in_keyak(i);
end loop;
bit_position <= bit_position +data_in_length;
end if;
when ...
.....
end case;
end if; -- end rst_n = '0'
end process temp_vector_proc;
And second
when TAKING_DATA =>
if take_data = '1' then
temp_vector(63+ bit_position downto bit_position) <= data_in(63 downto 0);
bit_position <= bit_position +data_in_length;
end if;
when ...
.....
end case;
The second approach is working in FPGA but it is taking a lot of time and consuming too many Logic Elements and for design compiler it is returning an error that the range has to be constant.
The first one is also working in FPGA and returning no error in ASIC ( Design compiler), but for the ASIC it runs forever (I let it run overnight). It was stuck at beginning Pass 1 Mapping of the entity that contains the first code.
I hope I explained my problem enough and I would really appreciate some thoughts on how to implement it in a more efficient way.
I do not think I can go with generics because the file is read and operated on in one go, so the lengths are changing during the simulation. I also though about shifting but since the shifting value would be changing each time, i guess that it would still consume a lot of time/area.
Finally could my whole approach be wrong? I mean is it possible that for FPGA and especially for ASIC I need to be working on specific input sizes? That would mean that I should try to write and synthesize code that does not work for all of my file, but for some of its inputs with some specified size only.
Thanks a lot in advance for your time.
I'm trying to create a 4*4 matrix in this form:
2 3 1 1
1 2 3 1
1 1 2 3
3 1 1 2
Then I need to assign the values element in each location to multiply by 4 inputs each one 8 bits.
a0, a1, a2, a3
I have tried to write this code :
module Mix_Nibbles_Matriex(
out_0,out_1,out_2,out_3,nibble_0,nibble_1,nibble_2,nibble_3,
clk,rst,load
);
input clk,rst,load ;
output reg [7:0] out_0,out_1,out_2,out_3;
input [7:0] nibble_0,nibble_1,nibble_2,nibble_3;
//wire matrix[3:0][0:3];
reg [1:0][7:0] a_unpacked_array[4];
always #( posedge clk or negedge rst)
if (!rst)
a_unpacked_array[0][0]=0;
else if (load)
assign a_unpacked_array[0][0]=2;
assign a_unpacked_array[0][1]=3;
assign a_unpacked_array[0][2]=1;
assign a_unpacked_array[0][3]=1;
assign a_unpacked_array[1][0]=2;
assign a_unpacked_array[1][1]=3;
assign a_unpacked_array[1][2]=1;
assign a_unpacked_array[1][3]=1;
assign a_unpacked_array[2][0]=2;
assign a_unpacked_array[2][1]=3;
assign a_unpacked_array[2][2]=1;
assign a_unpacked_array[2][3]=1;
assign a_unpacked_array[3][0]=2;
assign a_unpacked_array[3][1]=3;
assign a_unpacked_array[3][2]=1;
assign a_unpacked_array[3][3]=1;
//display ("a_unpacked_array = %b", a_unpacked_array);
endmodule
I'm still have these errors:
ERROR:HDLCompiler:939 - "D:/Embedded_Project/Mix_Nibbles_Matriex.v" Line 38: Single value range is not allowed in this mode of verilog
ERROR:HDLCompiler:1439 - "D:/Embedded_Project/Mix_Nibbles_Matriex.v" Line 38: Multiple packed dimensions are not allowed in this mode of verilog
ERROR:HDLCompiler:1417 - "D:/Embedded_Project/Mix_Nibbles_Matriex.v" Line 44: Bit-select or part-select is not allowed in a assign statement for non-net a_unpacked_array
ERROR:HDLCompiler:598 - "D:/Embedded_Project/Mix_Nibbles_Matriex.v" Line 27: Module ignored due to previous errors.
There are couple problems with your code.
Verilog doesn't support multiple packed dimensions. You'd need to use SystemVerilog to make this construct work. You can also follow #Greg suggestion to use unpacked dimension.
reg [1:0][7:0] a_unpacked_array[4]; - compiler tries to treat 4 as range, but single value range are not allowed. Maybe what you meant is [3:0]? Also [1:0] should be probably [3:0].
Your always block has some issues: missing begin-end, unnecessary assign keywords, etc.:
always #(posedge clk or negedge rst)
if (!rst) begin
a_unpacked_array[0][0] <= 0;
//...
end else if (load) begin
a_unpacked_array[0][0] <= 2;
//...
end
timescale 1ns/10ps
/* resource counter for nor gates
*/
module global_vars;
integer count;
endmodule
module my_nor(y, a, b);
output y;
input a, b;
global_vars gv;
/* at instantiation increment the resources used */
gv =gv +1;
/* add 2ns inherent delay */
nor #2 nor1(y,a,b);
endmodule
When I compile, there is one syntax error at global_vars gv;
I have no idea. Should I initial the gv?
In verilog you can not just do this:
gv = gv +1;
wire types need to use assign:
wire gv;
assign gv = a + b;
reg types can use initial, always #* or always #(posedge clk).
always #* begin
gv = a + b;
end
Your trying to use an instance like a variable, I am not sure what your trying to do with your global_vars, may be make a global variable but creating an instance would make it local not global. Here you would do just as well to make gv an integer rather than an instance.
Note
Wire assignment and always #* are combinatorial, is there is no time delay in the assignment, therefor the value can not be directly referenced to itself. For example
gv = gv + 1;
Is a combinatorial loop, when do you expect the +1 to happen. This is normally solved by making gv a flip-flop and updating its value on a clock edge:
always #(posedge clk) begin
gv <= gv + 1;
end
In this case you still need to set an initial value for gv. for FPGAs this can be done using an initial or an async reset for ASIC.
FPGA using initial:
initial begin
gv = 'b0;
end
always #(posedge clk) begin
gv <= gv + 1;
end
Or for ASIC using reset:
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
gv <= 'b0;
end
else begin
gv <= gv + 1;
end
end
It looks like you are trying to embed a reference to a global variable within a synthesizable module so that you can count how many times that module has been instantiated. As #Morgan has already pointed out, you can't reference a module instantiate as a variable. But there is an even more fundamental problem -- you are trying to mix behavioral code (i.e. global variables) into synthesizable code and that just doesn't work.
Creating a synthesized module is really a two step process -- design and then coding. In the design phase, you figure out what kind of logic you are trying to create. You don't need to go down to the gate level, but you should be able to sketch out the function with clouds of combinatorial logic, registers, FIFOs, memories etc. Once you've gained some familiarity with the language, this may strictly be a mental process rather than something committed to paper, but you still need to think about the logic you are creating. Then once you have designed your circuit, you actually go write the code to implement your design.
Global variables do not exist in hardware. You can make a counter that is accessible by multiple modules, but but it would need some sort of arbitration process. But what you're trying to do is create a run-time counter that counts up the number of modules instantiated, for which there is no hardware analog. You could use 'define statements to instantiate a variable number of modules and have a signal from each module which is defined as '1' if the module is instantiated and '0' if it isn't and then count the number of '1's, but that is self defeating since you already had to define a macro telling you the number of modules before you instantiated them! In which case, you might as well just use the macro value directly and dispense with all the extra signals.
I'm very new to VHDL and XILINX ISE. I use the version 13.2 for Xilinx ISE.
I want to design a very simple counter with the following inputs:
Direction
Count
The count input will be assigned to a button and I want the counter to count up or down according to direction input when the button is pressed. I have written a sample VHDL before this one. It had a clock input and It was counting according to the clock input. Now I want it to count when I press the button instead of counting synchronously.
Here's my VHDL code (please tell me if my code have a logical or any other flaw):
entity counter is
Port ( COUNT_EN : in STD_LOGIC;
DIRECTION : in STD_LOGIC;
COUNT_OUT : out STD_LOGIC_VECTOR (3 downto 0));
end counter;
architecture Behavioral of counter is
signal count_int : std_logic_vector(3 downto 0) := "0000";
begin
process
begin
if COUNT_EN='1' then
if DIRECTION='1' then
count_int <= count_int + 1;
else
count_int <= count_int - 1;
end if;
end if;
end process;
COUNT_OUT <= count_int;
end Behavioral;
I use Spartan xc3s500e and I placed the inputs accordingly. Below is my .ucf file:
#Created by Constraints Editor (xc3s500e-fg320-5) - 2013/03/18
NET "COUNT_EN" LOC = K17;
NET "COUNT_OUT[0]" LOC = F12;
NET "COUNT_OUT[1]" LOC = E12;
NET "COUNT_OUT[2]" LOC = E11;
NET "COUNT_OUT[3]" LOC = F11;
NET "DIRECTION" LOC = L13;
#Created by Constraints Editor (xc3s500e-fg320-5) - 2013/03/18
NET "COUNT_EN" CLOCK_DEDICATED_ROUTE = FALSE;
I needed to change the last line because I was getting the error:
This will not allow the use of the fast path between the IO and the Clock...
After having this error gone, I programmed the device. But the output (leds) acted crazy. They sometimes stood still for a few seconds, sometimes just flashed very fast. I could not figure out where my mistake is. I would appreciate any help, some beginner tutorials are greatly appreciated (the links i found directed me to xilinx's documentations and they seemed quite complicated for a beginner).
From your description I understand that you are not looking for an Asynchronous Counter.
What you need is counter that counts on trigger from PushButton Switch. The below RTL should work:
If any difficulty in HDL coding let me know.
You don't have a clock. Once the COUNT_EN and DIRECTION conditions are satisfied, the count_int variable is going to increase as fast as it possibly can... in fact the timing of when individual bits change will probably make the entire thing completely unstable and incorrect.
You should always use a clock... just to allow the FPGA to get the timing right.
In this case, put the clock back... then add a new signal COUNT_EN_LAST. Save the old COUNT_EN each pass through the clocked process. Only increment when COUNT_EN = '1' and COUNT_EN_LAST = '0'.
In fact, you'll next find that you need to "debounce" the input. Physical buttons/switches "bounce" and give you multiple off-on events per single button press. For that, you'd simply make COUNT_EN_LAST a vector (say 5 long), shift new values into it each time ("COUNT_EN_LAST <= COUNT_EN_LAST(3 downto 0) & COUNT_EN;"), and only increment when COUNT_EN_LAST = "01111", or right before they're all 1's. The length of the vector you need will change depending on how fast your clock is and how long the switch can bounce before settling down to the new state.