Seven Segment Display - verilog

I'm having some problems coding a seven seg display in verilog. I want to increment 1 digit by 1 and have it roll over to 0 after 9. I have done lots of debugging and looked at examples but I can't seem to find the problem. My code:
module counter(output sega, segb, segc, segd, sege, segf, segg);
OSCH #("2.08") osc_int ( //"2.03" specifies the operating frequency, 2.03 MHz. Other clock frequencies can be found in the MachX02's documentation
.STDBY(1'b0), //Specifies active state
.OSC(clk), //Outputs clock signal to 'clk' net
.SEDSTDBY());
reg [21:0] cnt;
wire clk_slow = cnt[21]; //clock at 1 Hz
reg [3:0] BCD; //represents the states of the counter
always #(posedge clk)
begin
begin
cnt <= cnt+1;
end
begin
if(clk_slow) BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
end
end
reg [6:0] seg;
always #(*)
begin
case(BCD)
//gfedcba
4'b0000: seg = 7'b1000000; //0
4'b0001: seg = 7'b1111001; //1
4'b0010: seg = 7'b0100100; //2
4'b0011: seg = 7'b0110000; //3
4'b0100: seg = 7'b0011001; //4
4'b0101: seg = 7'b0010010; //5
4'b0110: seg = 7'b0000010; //6
4'b0111: seg = 7'b1111000; //7
4'b1000: seg = 7'b0000000; //8
4'b1001: seg = 7'b0011000; //9
default seg = 7'b0111111;
endcase
end
assign {segg, segf, sege, segd, segc, segb, sega} = seg;
endmodule
So when its running, my LEDs light up the correct digit every other time. In this case, it lights up on 0, 2, 4, 6, 8 and repeats. In between each number, the LEDs are lit, but not as brightly ( a dim '8'). When I switched the order of the cases but kept the numbers in the same spot (i.e. case b0000 is now for number 9), the LEDs light up 9, 7, 5, 3, 1.... For some reason, my LEDs arnt responding for any of the "odd" cases (i.e. 0001, 0011...). Any help sorting this out is greatly appreciated, as I have spent lots of hours trying to debug already.
I am using a Diamond Lattice FPGA. It has an onboard clock (the first module in my code). I slow it down to 1 hz at clock_slow.

Your problem is related to those lines:
always #(posedge clk)
begin
cnt <= cnt+1;
if(clk_slow) BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
end
Because clk is faster than clk_slow, the if condition will be true for more than one clock cycle ('cause clk_slow is high for couple clk cycles). That's why BCD will be incremented more than once. I'd recommend you to divide this two instructions into two separate always blocks:
always #(posedge clk) begin
cnt <= cnt + 1;
end
always #(posedge clk_slow) begin
BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
end

Related

Seven Segment Display outputs are unknown

I'm trying to make a counter that counts from 0-9 and displays on my Nexys A7's seven segment display. The code compiles, but in the testbench it shows that all the outputs are unknown. I tested my clock divider module, and it looks fine. I'm not sure why it isn't working.
module BCD_sevenseg(
input clk,
output segA, segB, segC, segD, segE, segF, segG, segDP, div_clk
);
counter module1(
.clk(clk),
.div_clk(div_clk)
);
reg[3:0] BCD; //BCD signal is 4 bits wide
always#(posedge clk) //check every positive edge
if(div_clk) //executes if counter value from module1 is true
BCD <= (BCD == 4'h9 ? //check if BCD is at binary 9
4'h0 : BCD + 4'h1 );
//true: reset to 0
//false: count up
reg [7:0] sevenseg; //8 segments on 7 segment display (w/ decimal point)
always#(*)
case(BCD) //one case for each digit
4'h0: sevenseg = 8'b11111100;
4'h1: sevenseg = 8'b01100000;
4'h2: sevenseg = 8'b11011010;
4'h3: sevenseg = 8'b11110010;
4'h4: sevenseg = 8'b01100110;
4'h5: sevenseg = 8'b10110110;
4'h6: sevenseg = 8'b10111110;
4'h7: sevenseg = 8'b11100000;
4'h8: sevenseg = 8'b11111110;
4'h9: sevenseg = 8'b11110110;
default: sevenseg = 8'b00000000;
endcase
assign {segA, segB, segC, segD, segE, segF, segG, segDP} = sevenseg;
endmodule
Clock divider:
module counter(
input clk,
output reg div_clk=0
);
integer count_value=0;
always#(posedge clk)
begin
if(count_value == 10)//change this number to adjust output signal frequency
begin
div_clk = ~div_clk;
count_value <= 0;
end
else
count_value <= count_value+1;
end
endmodule
Testbench code:
module BCD_sevenseg_tb();
reg clk=0;
wire segA, segB, segC, segD, segE, segF, segG, segDP, div_clk;
BCD_sevenseg UUT(
.clk(clk),
.segA(segA),
.segB(segB),
.segC(segC),
.segD(segD),
.segE(segE),
.segF(segF),
.segG(segG),
.segDP(segDP),
.div_clk(div_clk)
);
always
#1 clk=~clk;
endmodule
Your outputs are always X because BCD is always X. You declared BCD as a reg, which defaults to X. You need to initialize BCD to a known value, such as 0.
For simulation purposes, you can do this simply with:
reg[3:0] BCD = 0; //BCD signal is 4 bits wide
A standard way to initialize signals is to use a reset input signal. For example:
always #(posedge clk) begin
if (reset) begin
BCD <= 4'h0;
end else begin
if (div_clk) BCD <= (BCD == 4'h9 ? 4'h0 : BCD + 4'h1 );
end
end

How to change clock in Verilog?

module task_A(input [15:0]sw, input clk,output reg [3:0] an= 4'b1111,output reg[7:0] seg);
reg [2:0] num = 3'd0;
wire Z,Z1,Z2;
clk_1_47hz(clk,Z1);
clk_762hz(clk,Z2);
reg count=0;
assign Z= (count<5)?(Z1):(Z2);
always # (posedge Z)
begin
num <= (sw[15:0]==16'b1111111111111111)?((num==5 | num==0)?(3'd1):(num+1)):(0);
count <=count+1;
case(num)
3'd0 : begin seg <= 8'b11111111 ; an <= 4'b1111; end
3'd1 : begin seg <= 8'b10000111 ; an <= 4'b0111; end //t
3'd2 : begin seg <= 8'b10001000 ; an <= 4'b1011; end //a
3'd3 : begin seg <= 8'b11001111 ; an <= 4'b1101; end //l
3'd4 : begin seg <= 8'b11111001 ; an <= 4'b1101; end //l
3'd5 : begin seg <= 8'b10010001 ; an <= 4'b1110; end //y
endcase
end
endmodule
I wish to change the clock after the 7 segment display has displayed 'tally' once. So I use count to check. But the clock does not change at all. May I know how to correct it?
count is declared as a 1-bit signal, which is always smaller than 5.
reg count=0;
To accomplish your goal, declare it as a 3-bit signal or more.
And you may also need to set a limit for count, and stop it, if you want to switch to Z2 clock forever after 'tally' is displayed once.

Counter through Verilog

I'm developing a counter in Verilog that cycles through the following series:
0, 1, 3, 7, 6, 4, 0, 1, ...
and resets to 0 on reset_b.
Here is my code so far, it doesn't seem to make it past 3 in the cycle:
module Counter_1(output reg [2: 0] Count, input clock, reset);
reg [2: 0] last;
always #(posedge clock, negedge reset) begin
if (!reset) begin
Count <= 3'b000;
end
else begin
case (last)
3'b000: Count <= 3'b001;
3'b001: Count <= 3'b011;
3'b011: Count <= 3'b111;
3'b111: Count <= 3'b110;
3'b110: Count <= 3'b100;
3'b100: Count <= 3'b000;
endcase
end
last <= Count;
end
endmodule
It is always useful to look at the sequence:
000
001
011
111
110
100
Analyse the pattern and you find the sequence can be made by:
if (!reset)
Count <= 3'b000;
else
Count <= {Count[1:0],~Count[3]};
To follow your method: you can just use the Count as input for the next value. The usage of 'last' is not needed:
case (Count)
3'b000 : Count <= 3'b001;
3'b001 : Count <= 3'b011;
You should certainly be assigning last in the reset block:
if (!reset) begin
last <= 3'b000;
Count <= 3'b000;
end
I'd imagine that will fix your issue, as I don't see any other problems with your code (assuming your clock and reset inputs work correctly and you're using an active high reset).
Also, why are you including reset in your always condition? I believe that your always condition could simply be:
always #(posedge clock) begin

Verilog (register delay or mistake in code?)

I am trying to study Verilog
and I got problem with my code:
the problem is when I trying to add my numbers like
first value clk> second value clk> 3rd value clk> 4th value clk>and here supposed to be my average value BUT for some unknown reason I need to press clock 2 times AGAIN to get averege value
and I don't know why. (I think there is a problem in my code with avereger)
why I have such delay
my avereger must get 4 - 10 bits numbers and show me the averege of it (on my leds)
Here is my code
and I am including my vector form [
]
module avereger (data_in,Led1,Led2,Led3,clk,rst);
input clk,rst;
input [9:0]data_in;
output[6:0] Led1,Led2,Led3;
reg [9:0] data[3:0];
reg [11:0] sum,avg_reg;
always # (posedge clk)
begin
if(rst==1'b1)
begin //all values will be 0
data[0]<=0;
data[1]<=0;
data[2]<=0;
data[3]<=0;
sum<=0;
avg_reg<=0;
end
else
begin
data[3]<=data[2];
data[2]<=data[1];
data[1]<=data[0];
data[0]<=data_in;
sum<= data[0] + data[1] + data[2] + data[3];
avg_reg<=sum[11:2];
end
end
decoder_driver BCD(avg_reg,Led1,Led2,Led3);
endmodule
module decoder_driver(A,Led1,Led2,Led3);
input [9:0] A;
output [6:0] Led1,Led2,Led3;
reg [3:0] B,C,D;
wire [3:0] wireB,wireC,wireD;
assign wireB=B;
assign wireC=C;
assign wireD=D;
display1 HUN(wireB,Led1);
display1 TEN(wireC,Led2);
display1 ONE(wireD,Led3);
always # (A)
begin
B=A/7'd100;
C=A%7'd100/7'd10;
D=A%7'd100%7'd10;
end
endmodule
module display1 (a,Led);
input [3:0] a;
output [6:0] Led;
reg [6:0] Led;
always # (a)
begin
case(a)
4'b0000: Led <= 7'b1000000; //0
4'b0001: Led <= 7'b1111001; //1
4'b0010: Led <= 7'b0100100; //2
4'b0011: Led <= 7'b0110000; //3
4'b0100: Led <= 7'b0011001; //4
4'b0101: Led <= 7'b0010010; //5
4'b0110: Led <= 7'b0000010; //6
4'b0111: Led <= 7'b1111000; //7
4'b1000: Led <= 7'b0000000; //8
4'b1001: Led <= 7'b0010000; //9
4'b1010: Led <= 7'b0001110; //F
default: Led <= 7'b1111111; //-
endcase
end
endmodule
The reason the code is taking 6 total cycles instead of 4 is because calculating sum and avg_reg takes a cycle each, thus combined with the 4 cycles needed to shift in the 4 data items, and you get 6 cycles.
If you watch what happens during simulation, you'll notice shifting in the 4 items takes 4 cycles as expected. However, sum is, at the edge the 4th value is take into data[0], the sum of the first third items and whatever was in data[4] which is probably all zeroes if you've just done a reset. And avg_reg is the value of sum from right before the edge shifted over twice. On the next cycle sum becomes correct and then the cycle after that avg_reg becomes correct.
If you want to remove these cycles, you can simply have sum determined combinationally and don't really need avg_reg at all:
module avereger (data_in,Led1,Led2,Led3,clk,rst);
input clk, rst;
input [9:0] data_in;
output[6:0] Led1,Led2,Led3;
reg [9:0] data[3:0];
wire [11:0] sum;
always # (posedge clk) begin
if(rst==1'b1) begin //all values will be 0
data[0]<='0;
data[1]<='0;
data[2]<='0;
data[3]<='0;
end
else begin
data[3]<=data[2];
data[2]<=data[1];
data[1]<=data[0];
data[0]<=data_in;
end
end
// Find sum combinationally
assign sum = data[0] + data[1] + data[2] + data[3];
// Do >>2 here
decoder_driver BCD(.A(sum[11:2]),
.Led1(Led1),
.Led2(Led2),
.Led3(Led3));
endmodule
Side note, you should avoid writing your own sensitivity lists as its very easy to make mistakes, use always #(*) instead of always #(A) in your other modules.

Up Down counter code

I need help in my project which is a counter that counts up or down from 0 to 20. I already did my counter code and it's working in active HDL. But now I need to show the numbers in 7-segment in nexys 3 FPGA board.
I have the code of the segment, but I have a problem when I call the module of segment - it is giving me an error in active HDL. Can you please tell me what is the error?
This is my current code :
module main
#(parameter N=7)
(
input switch,
input button,
input fastclk,
output [3:0] enable,
output reg[6:0] out
);
wire[N:0]count;
wire slowclk;
clock c1(fastclk,slowclk);
Updown u1(switch,button,slowclk,count);
segment s1([3:0]count,[7:4]count,fastclk,enable,out);
endmodule
module clock(fastclk,slowclk); //clock code
input fastclk;
output wire slowclk;
reg[25:0]period_count = 0;
always #(posedge fastclk)
begin
period_count <= period_count + 1;
end
assign slowclk = period_count[25];
endmodule
module Updown // UpDown Counter
#(parameter N=7)
(
input switch,
input button,
input clk,
output reg [N:0]count=8'd0,
);
always #(posedge clk)
begin
if(switch == 1 && button == 1) // Countup from 0 to 20
begin
if(count == 8'd20)
count <= 0 ;
else
count <= count +1;
end
else if(switch == 0 && button == 1) // Countdown from 20 to 0
begin
if(count == 8'd0)
count <= 8'd20 ;
else
count <= count -1;
end
else count <=8'd0;
end
endmodule
module mux(A,B,sel,Y); // 2x1 Multiplexer
input [3:0]A;
input [3:0]B;
input sel;
output [3:0]Y;
reg [3:0]Y;
always #(*)
begin
if(sel==0)
Y=A;
else
Y=B;
end
endmodule
module hex7seg(input wire [3:0]x , output reg[6:0]a_to_g); // Hex to 7seg Code
always #(*)
case(x)
0: a_to_g = 7'b0000001;
1: a_to_g = 7'b1001111;
2: a_to_g = 7'b0010010;
3: a_to_g = 7'b0000110;
4: a_to_g = 7'b1001100;
5: a_to_g = 7'b0100100;
6: a_to_g = 7'b0100000;
7: a_to_g = 7'b0001111;
8: a_to_g = 7'b0000000;
9: a_to_g = 7'b0000100;
'hA: a_to_g = 7'b0001000;
'hB: a_to_g = 7'b1100000;
'hC: a_to_g = 7'b0110001;
'hD: a_to_g = 7'b1000010;
'hE: a_to_g = 7'b0110000;
'hF: a_to_g = 7'b0111000;
default: a_to_g = 7'b0000001;
endcase
endmodule
module segment (a,b,fast,enable,seg7);
input [3:0]a;
input [3:0]b;
input fast;
output [3:0] enable;
output [6:0] seg7;
wire [3:0]e1 = 4'b1110;
wire [3:0]e2 = 4'b1101;
wire slow;
wire [3:0]number;
clock c1(fast,slow);
mux m1(a,b,slow,number);
mux m2(e1,e2,slow,enable);
hex7seg h1(number,seg7);
endmodule
You have a small error in segment module initialization part of code:
segment s1([3:0]count,[7:4]count,fastclk,enable,out);
This part of code should look a little bit different:
segment s1(count[3:0],count[7:4],fastclk,enable,out);
The big issue is:
segment s1([3:0]count,[7:4]count,fastclk,enable,out);
It should be:
segment s1(count[3:0],count[7:4],fastclk,enable,out);
Other option (IEEE Std 1364-2001 auto connect by name (.*)):
segment s1(.a(count[3:0]), .b(count[7:4]), .fast(fastclk), .seg7(out), .*);
Some simulators may complain about initial values on outputs with ANSI style port lists or trailing comma in the port list. So this:
output reg [N:0]count=8'd0,
);
Should be:
output reg [N:0] count
);
initial count=8'd0;
I prefer being able to control the reset in my designs, so I'd prefer:
input reset_n,
output reg [N:0] count
);
always #(posedge clk
// or negedge reset_n // <-- uncomment for asynchronous reset
) begin
if (!reset_n) begin
count=8'd0;
end
else begin
// synchronous code here
end
end
In main you have output reg[6:0] out. Since out is not assigned by an always-block in main (sub-modules don't count), it should be a wire not a reg. This one is a guideline as it is best practice for Verilog, most simulates tolerate it.

Resources