24 Hour Clock code, getting fan out error - verilog

module top_module(
input clk,
input reset,
input ena,
output pm,
output reg [7:0] hh,
output reg [7:0] mm,
output reg [7:0] ss);
wire [4:0] enable;
assign enable[0] = ss[3:0] == 4'd9;
assign enable[1] = ss[7:0] == 8'h59;
assign enable[2] = {mm[3:0],ss[7:0]} == 12'h959;
assign enable[3] = {mm[7:0],ss[7:0]} == 16'h5959;
assign enable[4] = {hh[3:0],mm[7:0],ss[7:0]} == 20'h95959;
bcd in1(clk, reset, ena, ss[3:0]);
bcd in2(clk, reset, enable[0], ss[7:4]);
bcd in3(clk, reset, enable[1], mm[3:0]);
bcd in4(clk, reset, enable[2], mm[7:4]);
bcd in5(clk, reset, enable[3], hh[3:0]);
bcd in6(clk, reset, enable[4], hh[7:4]);
always # (*) begin
if(reset) begin
pm <= 0;
hh <= 8'h12;
ss <= 8'h00;
mm <= 8'h00;
end
else if(ena) begin
// ss <= ss == 8'h59;
// mm <= (mm == 8'h59 & ss == 8'h59) ?? 8'h00 : mm;
// hh <= (hh == 8'h12 & mm == 8'h59 & ss == 8'h59) ?? 8'h01 : hh;
end
end
endmodule
module bcd(input clk, reset, ena,
output [3:0] q);
always # (posedge clk) begin
q <= reset ? 0 : (ena ? (q == 4'd9 ? 0 : q + 1) : q);
end
endmodule
I'm trying to understand why when I try to run this code, I'm getting this error:
Error (12014): Net "hh[7]", which fans out to "hh[7]", cannot be assigned more than one value File: /home/h/work/hdlbits.2188345/top_module.v Line: 28
Error (12015): Net is fed by "GND"
Error (12015): Net is fed by "bcd:in6|q[3]" File: /home/h/work/hdlbits.2188345/top_module.v Line: 49
I'm getting that for all of the other elements in ss, mm and hh, one by one. I'm not seeing how I'm trying to give it a value in more than one place. Very confusing.

The error message tells you that you are assigning to hh[7] in 2 places. The 1st line is:
bcd in6(clk, reset, enable[4], hh[7:4]);
and the 2nd line is:
hh <= 8'h12;
In the 1st line, hh is driven by the q output signal of the bcd module.
One way to fix the problem is to delete the always block from top_module. The only thing that code does is set the signals during reset, which is already done in the bcd module.
Here is modified code that compiles without errors for me:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire [4:0] enable;
assign enable[0] = ss[3:0] == 4'd9;
assign enable[1] = ss[7:0] == 8'h59;
assign enable[2] = {mm[3:0],ss[7:0]} == 12'h959;
assign enable[3] = {mm[7:0],ss[7:0]} == 16'h5959;
assign enable[4] = {hh[3:0],mm[7:0],ss[7:0]} == 20'h95959;
bcd in1(clk, reset, ena, ss[3:0]);
bcd in2(clk, reset, enable[0], ss[7:4]);
bcd in3(clk, reset, enable[1], mm[3:0]);
bcd in4(clk, reset, enable[2], mm[7:4]);
bcd in5(clk, reset, enable[3], hh[3:0]);
bcd in6(clk, reset, enable[4], hh[7:4]);
endmodule
module bcd(input clk, reset, ena,
output reg [3:0] q);
always # (posedge clk) begin
q <= reset ? 0 : (ena ? (q == 4'd9 ? 0 : q + 1) : q);
end
endmodule
Note also that I removed reg from the hh, mm and ss ports, and I added reg to the q port.

Related

binary to bcd verilog output is always x

I have a binary to bcd convertor module that uses the shift add 3 algorithm as follows :
module BCD(
input wire [7:0] binary,
output wire [3:0] Hundreds,
output wire [3:0] Tens,
output wire [3:0] Ones
);
integer i;
reg [11:0] bcd;
initial begin
bcd = 12'b000000000000;
for(i=7;i>=0;i=i-1) begin
bcd[11:0] = { bcd[10:0], binary[i] };
if(bcd[3:0] >= 5) bcd[3:0] = bcd[3:0] + 2'b11;
if(bcd[7:4] >= 5) bcd[7:4] = bcd[7:4] + 2'b11;
end
end
assign Hundreds = bcd[11:8];
assign Tens = bcd[7:4];
assign Ones = bcd[3:0];
endmodule;
and a Test bench for it as follows :
module BCD_Testbunch();
reg [7:0] binary;
wire [3:0] bcd_u;
wire [3:0] bcd_t;
wire [3:0] bcd_h;
integer i;
initial begin
binary = 8'b00000000;
$monitor("t = %g\t || Binary =%b (%d) BCD = %d %d %d",$time,binary,binary,bcd_h,bcd_t,bcd_u);
for(i=1;i<=8'b11111111;i=i+1)
#5 binary = binary + 1;
end
BCD B (binary,bcd_h,bcd_t,bcd_u);
endmodule;
yet my bcd output is always 0 x x whatever the value of the binary input
As #mkrieger1 pointed out in comments I changed the initial to always #(*) in bcd module And everything is working now

Verilog Temporary Variable

I tried to make a CMP instruction in Verilog. To keep the result of the substraction, I declared a wire. This is what the code looks like (It is executed in an always statement).
wire [data_width:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
Now Icarus Verilog complains about a syntax error and that reg_accumulator - reg_x is not an l-value:
cpu.v:149: syntax error
cpu.v:149: Syntax in assignment statement l-value.
And why does it complain? What would be the right approach to declare a temporary variable in a function / task?
module comparator(
input clk,
input [7:0] op_a,
input [7:0] op_b
);
reg f_zero;
reg f_carry;
function compare;
input [data_width-1:0] a;
input [data_width-1:0] b;
begin
wire [7:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end
endfunction
always #(posedge clk) begin
compare(op_a, op_b);
end
endmodule // comparator
Either you should use systemverilog and include this in a class or you can create a parameterized module:
module compare_zero_n_carry
# (
parameter DATA_WIDTH = 8
)
(zero, carry, a, b);
/* ports */
input [DATA_WIDTH-1:0] a; //.."reg_accumulator"
input [DATA_WIDTH-1:0] b; //.."reg_x"
output zero;
output carry;
wire [DATA_WIDTH-1:0] tmp_wire = a - b;
assign zero = (tmp_wire & {DATA_WIDTH{1'b1}}) == {DATA_WIDTH{1'b0}};
//..HERE IM NOT REALLY SURE WHAT IS THE LOGIC FOR THE CARRY,
//..IT SHOULD BE ONE BIT
assign carry = (tmp_wire & {1'b1,{(DATA_WIDTH-1){1'b0}}});
endmodule // compare_zero_n_carry
And instantiate it in the main comparator module as:
input clk;
input [DATA_WIDTH-1:0] op_a;
input [DATA_WIDTH-1:0] op_b;
wire f_zero;
wire f_carry;
reg f_zero_reg;
reg f_carry_reg;
compare_zero_n_carry
# (
.DATA_WIDTH (DATA_WIDTH)
)
compare_zero_n_carry_inst (
.a (op_a),
.b (op_b),
.zero (f_zero),
.carry (f_carry)
);
always # (posedge clk) begin
f_zero_reg <= f_zero;
f_carry_reg <= f_carry;
end
You cannot declare a wire inside the always block.
wire [7:0] tmp_wire = reg_accumulator - reg_x;
always #(posedge clk) begin
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end

dispalying S on 7 segments

This code should dispaly S for 1 sec then turn off for 1 sec and then dispaly G for 1 sec and then turn of for 1 sec and then display S for 1 sec and so on.
The problem is I am getting S then off then G then off then G then off and so on. I believe the error in the hex7segm module but I could not find a solution. Any help would be appreciated
Here is the code:
module asqw (output wire [6:0]a2g,output wire [3:0]AN,input wire fastclk);
wire slowclk;
slow_clock xx(fastclk,slowclk);
hex7segm zz(slowclk,a2g,AN);
endmodule
moduleslow_clock (input wire fastclk,output wire slowclk);
reg[27:0]period_count=0;
always#(posedge fastclk)
begin
period_count<=period_count+1;
end
assign slowclk=period_count[27];
endmodule
module hex7segm (input wire slowclk,
output reg [6:0]a2g,
output reg [3:0]AN
);
reg[1:0]x;
reg[1:0]y=0;
always#(*)
begin
if(slowclk)
begin
x=y;
AN= 4'b1110;
y=y+1;
if(y==2) y=0;
else
x=2;
AN= 4'b1110;
end
case(x)
0: a2g=7'b0100100;
1: a2g=7'b0100000;
2: a2g=7'b1111111;
default: a2g=7'b0100100;
endcase
end
endmodule
Hi probably a little bit late to answer but here it is: The main problem is that you are mixing combinational and sequential logic. You need to separate these two. Moreover, I couldn't see why your new clock has a duty cycle of 50%.
Top module:
module asqw (
output [6:0]a2g,
input wire fastclk);
wire slowclk;
slow_clock xx(fastclk,slowclk);
hex7segm zz(slowclk,a2g);
endmodule
Seven Segment Driver:
module hex7segm (
input wire slowclk,
output reg [6:0]a2g
);
localparam S = 7'b0100100;
localparam G = 7'b0100000;
localparam OFF = 7'b1111111;
reg [2:0] state = 0;
always # (posedge slowclk)
begin
state <= (state == 5) ? 0 : state + 3'b1;
end
always # (*)
begin
case(state)
0: a2g <= S;
2: a2g <= G;
4: a2g <= S;
default: a2g <= OFF;
endcase
end
endmodule
Slow clock:
module slow_clock (
input wire fastclk,
output reg slowclk = 0
);
reg[27:0]period_count = 0;
always#(posedge fastclk)
begin
period_count <= (period_count == 25000000) ? 0 : period_count+ 28'b1;
slowclk <= (period_count == 25000000) ? ~slowclk : slowclk;
end
endmodule

feedback on mux in verilog

I am preforming a feedback mux calculation using verilog. But however the system does not response (giving X) to one of input which is B (the input controlled by the mux). Can helping me pointing out where is the error and how to fix it.
Here are the codes:
module test(input sel,input [3:0]a,b,output [3:0]o);
localparam in_0 = 4'd0;
wire [3:0]w1;
assign w1 = a + b;
assign o = w1 | 4'd0;
assign b = (sel)?w1:in_0;
endmodule
Here are the testbench:
module test_tb();
reg sel;
reg [3:0] a,b;
wire [3:0]o;
test U1(.sel(sel),.a(a),.b(b),.o(o));
initial begin
sel <= 1'b0;
a <= 4'd2;
#2;
sel <= 1'b1;
#2;
a <= 4'd1;
#2;
sel <= 1'b0;
a <= 4'd4;
#2;
end
endmodule
According to the testbench (the initialization) it seems that b is not an input (it's just the output of multiplexer)
I think you want to implement the following circuit :
But to avoid creating loops (when sel=1), you should add a clk port to your design in order to control the operation :
module test(
input clk,
input sel,
input [3:0] a,
output [3:0] o
);
wire [3:0] b;
reg [3:0] w1;
assign o = w1;
assign b = (sel)?w1:4'd0;
always #(posedge clk)
w1 <= a + b;
endmodule
Looking at your example :
module test(
input sel,
input [3:0] a,
input [3:0] b,
output [3:0]o
);
localparam in_0 = 4'd0;
wire [3:0]w1;
assign w1 = a + b;
assign o = w1 | 4'd0;
assign b = (sel)? w1 : in_0;
Note that with sel==1 you have w1 = a+b, and b =w1which is w1= a+w1; as a combinatorial loop. this will not work. If there was a flip-flop inside to break the loop then it would behave like an accumulator.
Aa noted by Emman that b is an input and therefore the value can not be overriden.
This line assign b = (sel)? w1 : in_0; is not valid. Note that it never actually uses the input value as this completely overrides it in all situations.

Part-Select Causing Illegal lvalue

I have a Verilog project below that implements an LSFR. Currently, the code does not compile correctly in Xilinx ISE 14.6. It errors out with:
ERROR:HDLCompilers:108 - "top.v" line 70 Part-select of scalar wire array 'q' is illegal
ERROR:HDLCompilers:107 - "top.v" line 70 Illegal right hand side of nonblocking assignment
ERROR:HDLCompilers:108 - "top.v" line 74 Part-select of scalar wire array 'q' is illegal
ERROR:HDLCompilers:107 - "top.v" line 74 Illegal right hand side of nonblocking assignment
Which is pointing at this point in my code:
always # (display) begin
if(display == 1'b0) begin
LSB <= q[3:0];
switch <= LSB;
end
else begin
MSB <= q[7:4];
switch <= MSB;
end
end
I looked up the error in the Xilinx user guide, and it says to resolve the issue, give the value a bit width greater than 2. Since it's already at 8, I'm not sure what's wrong.
Here's my entire top module:
`timescale 1ns / 1ps
module top (c, start, clk_in, display, segments);
input [7:0] c;
input start, clk_in;
output [3:0] display;
output [6:0] segments;
reg [6:0] segments;
reg [3:0] display;
reg [3:0] LSB;
reg [3:0] MSB;
wire q[7:0];
wire q_[7:0];
wire clk, dff0_w, dff1_w, dff2_w, dff3_w, dff4_w, dff5_w, dff6_w;
reg [3:0] switch;
initial begin
display <= 4'b0111;
end
clock_divider #(15) divider(.cin(clk_in), .cout(clk));
//switch changes back and forth between the MSB and LSB of the 8 bit number when muxing
decoder bits(clk, switch, segments);
//D adders
dff dff0(.D(dff0_w),.Q(q[0]),.clk(clk),.start(start));
dff dff1(q[0],q[1],clk,start);
dff dff2(q[1],q[2],clk,start);
dff dff3(q[2],q[3],clk,start);
dff dff4(q[3],q[4],clk,start);
dff dff5(q[4],q[5],clk,start);
dff dff6(q[5],q[6],clk,start);
dff dff7(q[6],q[7],clk,start);
//xor gates
xor (dff6_w, q[7], q_[6]);
xor (dff5_w, dff6_w, q_[5]);
xor (dff4_w, dff5_w, q_[4]);
xor (dff3_w, dff4_w, q_[3]);
xor (dff2_w, dff3_w, q_[2]);
xor (dff1_w, dff2_w, q_[1]);
xor (dff0_w, dff1_w, q_[0]);
//buffer the C values
assign q_[0] = c[0] ? 1'b0 : q[0];
assign q_[1] = c[1] ? 1'b0 : q[1];
assign q_[2] = c[2] ? 1'b0 : q[2];
assign q_[3] = c[3] ? 1'b0 : q[3];
assign q_[4] = c[4] ? 1'b0 : q[4];
assign q_[5] = c[5] ? 1'b0 : q[5];
assign q_[6] = c[6] ? 1'b0 : q[6];
assign q_[7] = 1 ? 1'b0 : q[7]; //Cn is always 1
//mux the display
always # (posedge clk) begin
if(display == 4'b0111)
display <= 4'b1011;
else
display <= 4'b0111;
end
//display the appropriate value when the anode is asserted
always # (display) begin
if(display == 1'b0) begin
LSB <= q[3:0];
switch <= LSB;
end
else begin
MSB <= q[7:4];
switch <= MSB;
end
end
endmodule
Try changing:
wire q[7:0];
wire q_[7:0];
to:
wire [7:0] q;
wire [7:0] q_;
That clears up compile errors for me.

Resources