verilog average, add n-bit numbers together and then divide by nbit numbers - verilog

I am having trouble putting this code together my main code is a state machine it adds 2 numbers together = sum then loads A to add A to sum(sum=a+sum) after clock is reached it then divides by n bit. I'm lost putting it together. In having Lots of trouble assigning outputs. what is legal and what is not am I able to set the regs equal to each other sometimes I feel like I can do that and some other times I cannot.if I use the module can the input be an output and vice versa I posted my whole code cause I wanted to get it to work. I think my device is correct but I need to create a test bench to tested.
module Adder (A1, B1, Cin,Q);
parameter n = 5;
output[n:0]Q;
reg [n:0]Q;
input [n:0] A1;
wire[n:0] A1;
input [n:0] B1;
wire [n:0] B1;
input Cin;
always #(A1 or B1 or Cin)
begin
Q = A1 +B1 + Cin;
end
endmodule
module ave(Clk,X,LA,DataA,Sum,Q);
parameter n=5;
input A,B,EB,Temp,DataA,DataB,Sum,Q;
input X;
reg A,B,Temp,Sum;
reg y,Y
wire
reg S1=3'b000;S2=3'b001;S3=3'b010;S4=3'b011;S5=3'b100;
always (Clk)
begin
case(y)
S1:
y=S2;
S2:
y=S3;
S3:
if (counter>0) y=S2;
else y=S4;
S4:
y=S4;
S5:
Done;
endcase
end
always (Clk)
begin
case
S1:
Counter=n; Temp=n; Sum=0;
S2:
A=X;
S3:
if (counter>0) B<=A+B;
else B<=B;
S4:
DataA=Temp;
DataB=Sum;
S5:
Done=1;
end
Adder add(A,Sum,Cin,Sum);
divider divid(Clk,1,1,1,1,DataA,DataB,1,1,Q,0);
endmodule
this is my divider plus the other modules:
module shiftlne(R,C,L,w,Clk,Q);
parameter n=8;
input [n-1:0]R;
input L,w,Clk,C;
output [n-1:0]Q;
reg [n-1:0]Q;
integer k;
always #(posedge Clk)
begin
if(L)begin
if(C)begin
Q<=R;end
else
begin
for (k=0;k<(n-1);k=(k+1))
Q[k+1]=Q[k];
Q[0]<=w;
end
end
end
endmodule
module downcounter (R,E,L,Clk,Q);
parameter n=8;
input[n-1:0]R;
input Clk,L,E;
output [n-1:0]Q;
reg[n-1:0]Q;
always #(posedge Clk)
begin if(L)
Q<=R;
else if(E)
Q<=(Q-1);
end
endmodule
module muxdff( D0, D1, Sel, Clk,Q);
input Clk,D0,D1,Sel;
wire D;
output Q;
reg Q;
assign D=Sel?D1:D0;
always # (posedge Clk)
begin
Q=D;
end
endmodule
module regne (R,Clk,Resetn,E,Q);
parameter n=8;
input [n-1:0]R;
input Clk,Resetn,E;
output [n-1:0]Q;
reg [n-1:0] Q;
always #(posedge Clk or negedge Resetn)
begin
if (Resetn==0)
Q<=0;
else if (E)
Q<=R;
end
endmodule

Are you stuck using Verilog-95 if not you can clean up the code style, if nothing else it helps spot the bugs easier.
NB: Uses spaces to indent your code, not tabs as they mess up the formatting when posting Q's and can look different to people review your code depending on how there editor is setup.
module Adder #(
parameter n = 5
)(
input [n:0] A1, //Inputs do not have to be declared as wires
input [n:0] B1,
input Cin,
output reg [n:0] Q;
);
//Auto sensitivity list with #* lowers chance of bugs
always #* begin
Q = A1 + B1 + Cin;
end
endmodule
Most languages, and I apply this to my verilog keep constants like parameters and localparam in UPPERCASE, everything else is lowercase.
Your shiftlne code be made more readable: readable code to me implies easier to spot the bugs and understand the design intention.
always #(posedge Clk) begin
if( L ) begin
if( C ) begin
Q <= R;
end
else begin
for (k=0;k<(n-1);k=(k+1))
Q[k+1] = Q[k]; //For loop only applies to this line
// should it not be Q[k+1] <= Q[k];
Q[0] <= w;
end
end
end
endmodule

Related

Delay a 32-bit signal with N clock cycle in verilog

I am trying to delay a 32-bit signal using shift register. My logic is a single flip flop delay a signal by 1 clk so I use shift register as it is combination of flip flop can someone guide me what is wrong with this code.
module delay_n_cycles (
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out,
parameter N = 5
);
reg [31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= {shift_reg[30:0], data_in};
if (N == 0) begin
data_out <= shift_reg[31];
end else begin
data_out <= shift_reg[N-1];
end
end
endmodule
First of all, your code is syntactically wrong. parameter cannot be declared in a way you provided.
Your shift register is only 32 bit wide. Usually, to delay multi-bit data this way, you need to keep N copies of data in the register, shift them at one end and read at the other. I guess the following should help:
module delay_n_cycles #(parameter N = 5)(
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out
);
reg [N-1:0][31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= (shift_reg << 32) | data_in;
data_out <= shift_reg[N-1];
end
endmodule
This code will work with system verilog because it used packed multi-dimensional arrays.
You need to shift the reg by 32 (width of the data) in packed version.
Here is an example of a testbench:
module tb();
bit clk;
int clkCount;
initial
forever begin
#5 clk = ~clk;
clkCount++;
end
logic [31:0] data_in, data_out;
initial begin
$monitor("%0t (%0d) [%h]: %0d --> %0d", $time, clkCount, ds.shift_reg[4], data_in, ds.data_out);
for(int i = 0; i < 20; i++) begin
#10 data_in = i;
end
$finish;
end
delay_n_cycles ds(data_in, clk, data_out);
endmodule

Verilog booth algorithm adding and subtracting

module calculator(state,U,V,X,X_1,multiplicant,multiplier,count);
input [1:0] state;
input [3:0] multiplicant,multiplier;
output reg [3:0] U,V,X;
output reg X_1;
output reg[2:0] count;
wire [7:0] ASR;
wire [4:0] CSR;
wire [3:0] sum, sub;
always # (state or count)
begin
U<=4'b0;
V<=4'b0;
X<=multiplier;
X_1<=1'b0;
count<=3'b0;
if(state==2'b01)
begin
case({X[0],X_1})
2'b00:
begin
{U,V}<=ASR;
{X,X_1}<=CSR;
end
2'b11:
begin
{U,V}<=ASR;
{X,X_1}<=CSR;
end
2'b01:
begin
U<=sum;
{U,V}<=ASR;
{X,X_1}<=CSR;
end
2'b10:
begin
U<=sub;
{U,V}<=ASR;
{X,X_1}<=CSR;
end
endcase
count <= count +1;
end
end
rca U0_rca4(.a(multiplicant),.b(U),.ci(1'b0),.s(sum));
rca U1_rca4(.a(U),.b(~multiplicant),.ci(1'b1),.s(sub));
ASR8 U2_ASR8({U,V},1'b1,ASR);
CSR5 U3_CSR5({X,X_1},1'b1,CSR);
endmodule
This is my code, the case 2'b01 and case 2'b10 doesn't work. Actually, shifting works well but adding rca's sum or sub to 'U' doesn't work. Why does it happen? I need explain. Or can I modify my code better? I have to make 4bit*4bit -> 8bit result multiplier
you have multiple issues with your code.
First of all there are no clocks. The case statement looks full and is a combinational logic, however 'counter <= counter + 1` is not a combinational logic and requires a flop.
you are using non-blocking assignments '<=' all over the places, making your model simulating not as expected in any case, and also probably causing glitches and races in simulation. Please review the chapter about use of blockling/non-blocking assignments.
Now for the cases 01 and 10 you have multiple assignments to the U variable:
2'b01:
begin
U<=sum; // << here is assighment #1
{U,V}<=ASR; // << here is assignment #2
{X,X_1}<=CSR;
end
So, you just overwrite it in the next assignment, therefore, sum (and sub in 10) do not take any effect.

Two module verilog is not working

module rff_try_1(q,inp,clk);
input clk,inp;
output q;
reg q;
DFF dff0(q,inp,clk);
endmodule
module DFF(q,inp,clk);
input inp,clk;
output q;
reg q;
always # (posedge clk)begin
if(clk)begin
q=inp;
end
end
endmodule
here I'm using two modules but output is not coming
I'm trying to make two bit right shift register but 1st i have to make one single bit register but even this is not working
There are several mistakes in the code.
1) The line if(clk)begin and relevant end should be removed, posedge clk already describes trigger condition of the flip-flop.
2) A non-blocking assignment (<=) is required for the sequential logic.
The always block should be as follows:
always # (posedge clk) begin
q <= inp;
end
3) Some simulators don't complain, but signal q should be wire in module rff_try_1.
wire q;
Simulation
I simulated the code (after the modifications) on EDA Playground with the testbench below. Used Icarus Verilog 0.9.7 as simulator.
module tb();
reg clk = 1;
always clk = #5 ~clk;
reg inp;
wire q;
rff_try_1 dut(q, inp, clk);
initial begin
inp = 0;
#12;
inp = 1;
#27;
inp = 0;
#24;
inp = 1;
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
#200;
$finish;
end
endmodule
The signal q is as expected as seen on the waveform.

Verilog code 2 errors i can't find: Would be grateful for an extra pair of eyes to spot a mistake i might've overlooked

I'm writing a verilog code where i'm reading two files and saving those numbers into registers. I'm then multiplying them and adding them. Pretty much a Multiplication Accumulator. However i'm having a hard frustrating time with the code that i have. It read the numbers from the files correctly and it multiples but here is the problem? When i first run it using ModelSim, I reset everything so i can clear out the accumulator. I then begin the program, but there is always this huge delay in my "macc_out" and i cannot seem to figure out why. This delay should not be there and instead it should be getting the result out A*B+MAC. Even after the delay, it's not getting the correct output. My second problem is that if i go from reset high, to low (start the program) and then back to reset high ( to reset all my values), they do not reset! This is frustrating since i've been working on this for a week and don't know/can't see a bug. Im asking for an extra set of eyes to see if you can spot my mistake. Attached is my code with the instantiations and also my ModelSim functional Wave Form. Any help is appreciated!
module FSM(clk,start,reset,done,clock_count);
input clk, start, reset;
output reg done;
output reg[10:0] clock_count;
reg [0:0] macc_clear;
reg[5:0] Aread, Bread, Cin;
wire signed [7:0] a, b;
wire signed [18:0] macc_out;
reg [3:0] i,j,m;
reg add;
reg [0:0] go;
reg[17:0] c;
parameter n = 8;
reg[1:0] state;
reg [1:0] S0 = 2'b00;
reg [1:0] S1 = 2'b01;
reg [1:0] S2 = 2'b10;
reg [1:0] S3 = 2'b11;
ram_A Aout(.clk(clk), .addr(Aread), .q(a));
ram_B Bout(.clk(clk), .addr(Bread), .q(b));
mac macout(.clk(clk), .macc_clear(macc_clear), .A(a), .B(b), .macc_out(macc_out), .add(add));
ram_C C_in(.clk(clk), .addr(Cin), .q(c));
always #(posedge clk) begin
if (reset == 1) begin
i <= 0;
add<=0;
j <= 0;
m <= 0;
clock_count <= 0;
go <= 0;
macc_clear<=1;
end
else
state<=S0;
case(state)
S0: begin
// if (reset) begin
// i <= 0;
// add<=0;
// j <= 0;
// m <= 0;
// clock_count <= 0;
// go <= 0;
// macc_clear<=1;
// state <= S0;
// end
macc_clear<=1;
done<=0;
state <= S1;
end
S1: begin
add<=1;
macc_clear<=0;
clock_count<=clock_count+1;
m<=m+1;
Aread <= 8*m + i;
Bread <= 8*j + m;
if (m==7) begin
state <= S2;
macc_clear<=1;
add<=0;
end
else
state <=S1;
end
S2: begin
add<=1;
macc_clear<=0;
m<=0;
i<=i+1;
if (i<7)
state<=S1;
else if (i==8) begin
state<=S3;
add<=0;
end
end
S3: begin
add<=1;
i<=0;
j<=j+1;
if(j<7)
state<=S1;
else begin
state<=S0;
done<=1;
add<=0;
end
end
endcase
end
always # (posedge macc_clear) begin
Cin <= 8*j + i;
c <= macc_out;
end
endmodule
module mac(clk, macc_clear, A, B, macc_out, add);
input clk, macc_clear;
input signed [7:0] A, B;
input add;
output reg signed [18:0] macc_out;
reg signed [18:0] MAC;
always #( posedge clk) begin
if (macc_clear) begin
macc_out <= MAC;
MAC<=0;
end
else if (add) begin
MAC<=(A*B)+ MAC;
macc_out<=MAC;
end
end
endmodule
module ram_A( clk, addr,q);
output reg[7:0] q;
input [5:0] addr;
input clk;
reg [7:0] mem [0:63];
initial begin
$readmemb("ram_a_init.txt", mem);
end
always #(posedge clk) begin
q <= mem[addr];
end
endmodule
module ram_C(clk,addr, q);
input [18:0] q;
input [5:0] addr;
input clk;
reg [18:0] mem [0:63];
always #(posedge clk) begin
mem[addr] <= q;
end
endmodule
ModelSim Functional Simulation Wave Form
1) Take a look at the schematic view for your MACC module - I think some of your "problems" will be obvious from that;
2) Consider using an always#(*) (Combinational) block for your FSM control signals (stuff like add or macc_clear) rather than a always#(posedge clk) (sequential) - it makes the logic to assert them easier. Right now they're registered, so you have a cycle delay. ;
3) In your MAC, you clear the MAC register on a reset, but you don't clear the macc_out register.
In short, I think you need to step back, and consider which signals are combinational logic, and which ones are sequential and need to be in registers.

how to map reg values to the ports of other module

i am an amateur in verilog. i am trying to call module divider. but i get errors like "Reference to vector reg 'qtnt' is not a legal net lvalue" in synthesis. i have tried using wires as inputs but when i tried to assign values to them an error message was recieved. please help
module euclid_mul(
input[9:0] p0,p1,q0,
input[19:0] tot,
input clk,
output reg [20:0] p2,
output reg out_en,o1,o2
);
reg[20:0] dvr,dvd,qtnt,rem;
reg[9:0] ph;
reg[20:0] mul,res;
reg enable,f1;
initial f1=0;
initial enable=0;
divider div2(dvd,dvr,enable,qtnt,rem,f1);
always # (negedge clk)
begin
if(f1==0) begin
mul=q0*p1;
ph=p0;
res={11'b00000000000,ph[9:0]}-mul;
if(res[20])
begin
o1=1;
dvd=-res;
end
else
dvd=res;
o2=1;
dvr=tot;
enable=1;
end
end
always #(posedge f1)
begin
if(res[20])
begin
p2=tot-rem;
out_en=1;
end
else
begin
p2=rem;
out_en=1;
end
end
endmodule
You may get more response if you formatted the code so that it was easier to read. Something like the following:
I have also pointed out a section where I think you are missing a begin and end statement.
Also inside clocked sections you often want to use nonblocking assignments <=.
Since you have not provided the divider module, I would prefer to see ports named rather than specified in order, it might help us to know what it is likely to do, even better label it with its direction and width.
module euclid_mul(
input [9:0] p0,p1,q0,
input [19:0] tot,
input clk,
output reg [20:0] p2,
output reg out_en,o1,o2
);
reg [20:0] dvr,dvd,qtnt,rem;
reg [9:0] ph;
reg [20:0] mul,res;
reg enable,f1;
initial begin
f1 = 0;
enable = 0;
end
divider div2(dvd,dvr,enable,qtnt,rem,f1);
// My prefered style to help us understand conectivity.
//divider
// divider_i0(
// .divisor( dvd ), //input [20:0]
// .result ( res ) //output [20:0]
//);
always # (negedge clk) begin
if(f1==0) begin
mul = q0*p1;
ph = p0;
res = {11'b00000000000,ph[9:0]}-mul;
if ( res[20] ) begin
o1 = 1;
dvd = -res;
end
else begin //There was a missing begin
dvd = res;
o2 = 1;
dvr = tot;
enable = 1;
end //Missing End
end
end
always #(posedge f1) begin
if(res[20]) begin
p2 = tot-rem;
out_en = 1;
end
else begin
p2 = rem;
out_en = 1;
end
end
endmodule
Inputs can be regs and driven from inside always or initial blocks, or wires driven from a single assign or another modules output.
Outputs should always be connected to wires, the module drives them.

Resources