I have this code:
Alu.v
module ALU(
src1_i,
src2_i,
src3_i,
src4_i,
ctrl_i,
result_o,
zero_o
);
//I/O ports
input [32-1:0] src1_i;
input [32-1:0] src2_i;
input [4-1:0] src3_i;//shmat is 5 bits instruction[10:6]
input [15-1:0] src4_i;//ori have to deal with 'zero-extended' number
input [4-1:0] ctrl_i;
output [32-1:0] result_o;
output zero_o;
//Internal signals
reg [32-1:0] result_o;
wire zero_o;
//Parameter
assign zero_o = (result_o == 0);
//Main function
always #(*) begin
case(ctrl_i)
0 :result_o <= src1_i & src2_i;//and
1 :result_o <= src1_i | src2_i;//or
2 :result_o <= src1_i + src2_i;//add
6 :result_o <= src1_i - src2_i;//substract
7 :result_o <= src1_i < src2_i ? 1 : 0;//set less than
10:result_o <= ~(src1_i - src2_i);//not the result for bne
11:result_o <= (src1_i | {16'b0000000000000000, src4_i});//ori
12:result_o <= ~(src1_i | src2_i);//nor
13:result_o <= src2_i << 16;//lui
14:result_o <= src2_i << src1_i;//sllv
15:result_o <= src2_i << src3_i;//sll
default:result_o <= 0;//default
endcase
end
endmodule
And in the other module:
Simple_Single_CPU.v
.....
ALU ALU(
.src1_i(RSdata_o),
.src2_i(reg_mux_data_o),
.src3_i(instr_o[10:6]),
.src4_i(instr_o[15:0]),
.ctrl_i(ALUCtrl_o),
.result_o(result_o),
.zero_o(zero_o)
);
I have checked that the port size and connection port size is right, but it gives me these warnings:
# ** Warning: (vsim-3015) C:/Users/lypan/Downloads/Lab2/Lab2/code/Simple_Single_CPU.v(116): [PCDPC] - Port size (4 or 4) does not match connection size (5) for port 'src3_i'. The port definition is at: C:/Users/lypan/Downloads/Lab2/Lab2/code/ALU.v(15).
#
# Region: /TestBench/cpu/ALU
# ** Warning: (vsim-3015) C:/Users/lypan/Downloads/Lab2/Lab2/code/Simple_Single_CPU.v(116): [PCDPC] - Port size (15 or 15) does not match connection size (16) for port 'src4_i'. The port definition is at: C:/Users/lypan/Downloads/Lab2/Lab2/code/ALU.v(16).
#
# Region: /TestBench/cpu/ALU
How can I fix the warnings?
The warning is correct.
In module ALU, you have this declaration:
input [4-1:0] src3_i;//shmat is 5 bits instruction[10:6]
This sets the width of src3_i to 4 because 4-1=3, and 3:0 is 4 bits.
But, in Simple_Single_CPU.v, you have:
.src3_i(instr_o[10:6]),
This connects a 5-bit signal (instr_o[10:6]) to a 4-bit port (src3_i).
You must decide whether the signal should really be 4 bits or 5 bits. For example, if you want 5 bits, use:
input [5-1:0] src3_i;//shmat is 5 bits instruction[10:6]
Related
I want to input data from r_D1_1 and r_D2_1 (these are outputs from a separate entity and continually change) into r_wave0 and r_wave1 respectively and I have tried doing the following:
r_wave0 <= r_D1_1 ;
r_wave1 <= r_D2_1 ;
This has resulted in the error (I have shown the error for the first line as the 2nd line is the same other than swapped input):
Error : type error near r_D1_1 ; current type integer ; expected type t_wave
As previously highlighted, the inputs are not fixed and so I wanted to assign them to r_wave0 and r_wave1 as they were generated. Should I overhaul the way I am creating the other arrays and 'calling' the input or maybe I shouldn't be labelling them as " in integer range 0 to 256 " and instead using SLVs?
All feedback is appreciated, thank you!
Below is a copy of the code for the entire entity.
entity Demodulator_A is
Port ( i_Clk : in STD_LOGIC;
i_Reset : in STD_LOGIC;
r_D2_1 : in integer range 0 to 256;
r_D1_1 : in integer range 0 to 256;
final_D2 : out integer range 0 to 256;
final_D1 : out integer range 0 to 256 );
end Demodulator_A;
architecture Behavioral of Demodulator_A is
type t_waveform1 is array (0 to 7) of integer; -- Array for reference waveform '1'
signal r_waveform1 : t_waveform1 := (16#80#, 16#60#, 16#40#, 16#60#, 16#80#, 16#A0#, 16#C0#, 16#A0#);
signal r_demodulated1 : t_waveform1;
type t_waveform0 is array (0 to 7) of integer; -- Array for reference waveform '0'
signal r_waveform0 : t_waveform0 := (16#80#, 16#A0#, 16#C0#, 16#A0#, 16#80#, 16#60#, 16#40#, 16#60#);
signal r_demodulated0 : t_waveform0;
type t_wave is array (0 to 7) of integer;
signal r_wave0 : t_wave ;
signal r_wave1 : t_wave ;
begin
DeModulationProc : process (i_Clk)
begin
if (r_wave0(2)>=16#81#) then
r_demodulated0 <= r_waveform0;
elsif (r_wave1(2)<=16#7F#) then
r_demodulated1 <= r_waveform1;
end if;
end process;
--0 = 80, A0, C0, A0, 80, 60, 40, 60. -- in hex the waveform values for 0
--1 = 80, 60, 40, 60, 80, A0, C0, A0. -- in hex the waveform values for 1
end Behavioral;
EDIT 1: I am trying to assign 1 changing integer to a whole array and it's causing problems so I want to assign the first integer to the first element of the array, the 2nd integer to the 2nd element and so on. From a comment I now know I could address the array with a counter and this counter could increment every time the input values changes. I will upload this code once I have written it to help others. Thank you Brian!
EDIT 2: I did have 2 libraries listed but forgot to include them in the above code snippet. Below are the two I used.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
what I want to do is the following:
In order to generate the appropriate OUTPUT I have to add a value(2^(stage-small_p+1) to my INPUT and then swapping the LSB (0) with a bit, which position depends on a the difference between the stage-signal and the constant small_p (stage-small_p).
Thanks for your help!
PROCESS(INPUT,stage)
BEGIN
IF stage > small_p THEN
OUTPUT_sig<=STD_LOGIC_VECTOR(TO_UNSIGNED(to_integer(UNSIGNED(INPUT)+2**
(stage-small_p+1)),m));
bit_0 <= OUTPUT_SIG(0);
bit_sp <=OUTPUT_SIG(stage-small_p);
FOR i in 0 to m-1 LOOP
IF (i=0) THEN
OUTPUT(i)<=bit_sp ;
ELSIF (i=(stage-small_p)) THEN
OUTPUT(i)<=bit_0;
ELSE
OUTPUT(i)<=OUTPUT_SIG(i);
END IF;
END LOOP;
ELSE
OUTPUT <= STD_LOGIC_VECTOR(TO_UNSIGNED(0,m));
END IF;
The error seems to be when assigning OUTPUT_SIG(i) to OUTPUT(i):
For example stage = 9 and p_small = 4:
My INPUT is 00110010,
OUTPUT_SIG has the value: 01110010,
whereas the OUTPUT has the value: 01010101.
stage-small_p = 5, so I would expect: 01010011 (Bit 5 and Bit 0 swapped).
In verilog for only this line of code its showing simulation output
1)
#( parameter width=1, length=16 )
(* ram_style = "block" *)
reg [(width)-1:0] mem[(1<<length)-1:0];
2)but for the below line it is not showing simulation output
#( parameter width=8, length=16 )
(* ram_style = "block" *)
reg [(2*width)-1:0] mem[(1<<length)-1:0];
Explain why 2nd set of code is not showing simulation results?
actually I want store 8 bits of min 65535 filter coefficients.. I want to read and write ..
please guide me in this...
A model of a RAM might look some thing like the code below, to write to it it is just a mater of sequencing the wr_addr, wr_data and wr_en.
module ram #(
parameter DATA_W = 8,
parameter DATA_D = 256
) (
input clk,
input rst_an,
input [0:$clog2(DATA_D)] rd_addr,
input [0:$clog2(DATA_D)] wr_addr,
input [0:DATA_W-1] wr_data,
input wr_en,
output [0:DATA_W-1] rd_data
);
reg [0:DATA_W-1] ram_data [0:DATA_D-1];
//READ
always #* begin
rd_data = ram_data[rd_addr];
end
//WRITE
always #(posedge clk, negedge rst_an) begin
if (~rst_an) begin
for(int i = 0; i<DATA_D ; i++) begin
ram_data[i] <= 'b0 ;
end
end
else begin
if (wr_en) begin
ram_data[wr_addr] <= wr_data ;
end
end
end
for(int i = 0; i<DATA_D ; i++) is system verilog syntax.
for plain verilog declare integer i then replace the for loop with :
for(i = 0; i<DATA_D ; i=1+1)
clog2 : is used to get the address width required for the given depth.
If you want a depth of 4, you need 2 bits to address it. Depth of 16, 4 bits to address, ie
log2( 4) => 2
log2(16) => 4
If you use non-powers of two you want to round up or ceiling
log2(5) => 2.32192809489
clog2(5) => 3
Therefore clog2 is very useful to get the required addressing width from the depth of the RAM.
I'm working on a project that is to make a simple music player on an FPGA. It takes a music file of a specified format from the PC and plays it out loud in loops.
We need to implement the standard note lengths, i.e. Quaver for half a beat, Minim for 2 beats, etc. Currently we have a table of the lengths of a beat in numbers of clock cycles at various BPM values. We need to multiply them by these note lengths to yield the correct clock cycles. The only problem is Tuplet, which is a third of a full beat.
Without implementing a full-blown divider circuit, are there any maths tricks one can do to divide, approximately, an integer by 3?
Dividing by 3 is the same as multiplying by 1/3 (=0.33333). 0.3333 can be expressed as an addition of two or more (depending on the needed accuracy) (left) shifted input values.
input*2^-a + input*2^-b + input*2^-c ...
Just find suitable values for a, b, c, ...
This works for (almost) all divisions.
The following is a VHDL translation of some code from Hank Warren’s Hacker’s Delight. It divides an unsigned integer by the constant value 3 using only shifts, additions, and multiplications by the constant values 3 and 5 (which can also be reduced to shifts and additions).
-- q is quotient, d is dividend
q := (d srl 2) + (d srl 4); -- q = d*0.0101 (approx)
q := q + (q srl 4); -- q = d*0.01010101
q := q + (q srl 8);
q := q + (q srl 16);
r := resize(d - q * 3, 32); -- 0 <= r <= 15.
q := resize(q + (5 * (r + 1) srl 4), 32);
If the exact result of integer division by 3 (x / 3) is required for an unsigned value of length LEN, then truncating integer operations can be used with a little trick. The constant for 1/3 should be of length LEN + 1 and 1 should be added. Truncation can then be used afterwards. Pseudo code as:
C = 2 ** (LEN + 1) / 3 + 1
y = (x * C) / 2 ** (LEN + 1)
A Python function that shows and tests the algorithm for all values is:
def div_by_3_test(LEN):
DIVISOR = 3
C = 2 ** (LEN + 1) // DIVISOR + 1
for x in range(2 ** LEN):
if (x * C) // 2 ** (LEN + 1) != x // DIVISOR: exit('Failed')
A VHDL module that implements this as:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity div_by_3 is
generic(
LEN : natural := 12);
port(
x_i : in std_logic_vector(LEN - 1 downto 0);
y_o : out std_logic_vector(LEN - 1 downto 0));
end entity;
architecture syn of div_by_3 is
-- Constant to multiply, basically 1/3, but adding 1 to avoid error
constant C : std_logic_vector(LEN - 1 + 1 downto 0) :=
std_logic_vector(to_unsigned(2 ** (LEN + 1) / 3 + 1, LEN + 1));
-- Intermediate, with length as 2 * LEN + 1
signal t : std_logic_vector(2 * LEN + 1 - 1 downto 0);
begin
-- Intermediate with full length result
t <= std_logic_vector(unsigned(C) * unsigned(x_i));
-- Result after truncation for division by LEN + 1
y_o <= t(2 * LEN + 1 - 1 downto LEN + 1);
end architecture;
The advantage is that a division by 3 of an LEN bit number can be made in one cycle using only a single 2 * LEN + 1 bit multiplication.
Registers may be added to allow pipeline for high speed design.
Note that a similar scheme is possible for any divisor, but length of C must then be LEN + ceil(log2(DIVISOR)), with C scaled accordingly. Please see https://math.stackexchange.com/q/2444306/275980 regarding the mathematical foundation.
As mentioned by dieli, multiply by 0.333333.
However, instead of using several negative powers of 2 (i.e. a, b, c,..) just multiply 1/3 by some large power of 2, e.g. 2^24 * (1/3) = 5592405. After multiplying the clock cycles and 5592405, just divide by 2^24.
B = (clock cycles)*5592405
result = B/2^24
The size of B would depend the maximum size of clock cycles and can be computed by
maximum register size for B = integer of ( (log10((max size of clock cycles)*5592405)/log10(2)) + 0.5)
Counter count the number of input samples. Then the counter output (n) and I want to check if the number of samples is even,then n_of_samples = (n*n) else if odd make that ((n*n)-1)
will be something like that
signal dis : integer range 0 to 255 := 0;
signal n : integer range 0 to 255 :=0;
if n mod 2=1 then
n_of samples<= ((n*n)-1);
else
n_of_samples <= n*n;
end if;
norm_dis <= dis / n_of_samples ;
the two signals will have values as (1,6,9,8,.....100) and (0,2,8,9.......,200)
and i want to fetch the two last outputs from the two signal (100,200)
and divide 100/200.how can i write it in vhdl and how can overcome the divide by zero error.
just make sure that you do not divide by zero!
if n_of_samples/=0 then
norm_dis <= dis / n_of_samples ;
end if;