How can I use this verilog code to generate a 1Hz clock signal while maintaining the counting functionality? Maxval enables the counter to count up to a certain value and then go back to 0 by reset and start over again. Or, it'll just reset and count again if it hits the maximum value. The thing is, my FPGA has a 50Mhz clock, but I need to use this counter with a 1Hz and a 2Hz clock. Any tips on adapting this code for that purporse?
module clocktime(input clk, freerun, Reset, output, input[7:0] Maxval, output reg[7:0] Count, output reg Carry);
always # (posedge clk or posedge Reset) begin
if ( Reset ) begin
Count <= 0;
Carry <= 0;
end
else
if ( freerun )
if ( Count < Maxval ) begin
Count <= Count + 8'd1;
Carry <= 0;
end
else begin
Count <= 0;
Carry <= 1;
end
end
endmodule
Start with increasing the width of Maxval and Count variables. You'll need 26 bits to fit a number of 50 millions there. Right now with 8 bits you can divide the clock by 255 at most.
To get additional outputs (1hz, 2hz) you can do something like this:
module top(clk50, reset, out_1hz, out_2hz);
input clk50;
input reset;
output out_1hz;
output out_2hz;
reg[25:0] clk50_divisor = 12500000;
reg [1:0] div2_4;
assign out_1hz = div2_4[1];
assign out_2hz = div2_4[0];
wire tmp_4hz;
clocktime div_clk50(
.clk(clk50),
.freerun(1),
.Reset(reset),
.Maxval(clk50_divisor),
.Carry(tmp_4hz));
always #(posedge tmp_4hz)
div2_4 <= div2_4 + 1'd1;
/* another option, might be better in your particular case,
or not different at all
always #(posedge clk50)
if (tmp_4hz)
div2_4 <= div2_4 + 1'd1;
*/
endmodule
module clocktime(clk, freerun, Reset, Maxval, Count, Carry);
input clk;
input freerun;
input Reset;
input [25:0] Maxval;
output reg[25:0] Count;
output reg Carry;
always # (posedge clk or posedge Reset) begin
if ( Reset ) begin
Count <= 0;
Carry <= 0;
end
else
if ( freerun )
if ( Count < Maxval ) begin
Count <= Count + 8'd1;
Carry <= 0;
end
else begin
Count <= 0;
Carry <= 1;
end
end
endmodule
Related
I am trying to create a second clk counter using a 100 MHz clk input, but when I simulate the clk divider, it just shows the output as an X even though the clk input is correct. What could I be doing wrong?
1 second clk divider:
module clkdiv(
input clk,
input [25:0] terminalcount,
output reg clk_div
);
reg [25:0] count;
wire tc;
assign tc = (count == terminalcount);
always # (posedge(clk)) begin
if (tc) count <= 0;
else count <= count + 1;
end
always # (posedge(clk)) begin
if (tc) clk_div = !clk_div;
end
endmodule
Test Bench:
module clockdivTB;
// inputs
reg clk; // make 100 MHz -- T = 10 ns
// outputs
wire newclk;
// second clock -- connect test signals to clkdiv
clkdiv slowclkCUT (
.clk(clk),
.terminalcount(50000000-1), // 1 Hz
.clk_div(newclk)
);
// initialize inputs
initial begin
clk = 0;
// create input clock 100MHz
forever #5 clk = ~clk;
end
endmodule
Result:
The output is X because reg types are initialized to X (unknown). You need to initialize the output to a known value. For simulation purposes, you can set clk_div and count to 0 as follows:
module clkdiv(
input clk,
input [25:0] terminalcount,
output reg clk_div = 0
);
reg [25:0] count = 0;
However, if you want to synthesize your logic, you likely need to add a reset input. You can drive the input from your testbench.
module clkdiv(
input reset,
input clk,
input [25:0] terminalcount,
output reg clk_div
);
reg [25:0] count;
wire tc;
assign tc = (count == terminalcount);
always # (posedge(clk)) begin
if (reset) count <= 0;
else if (tc) count <= 0;
else count <= count + 1;
end
always # (posedge(clk)) begin
if (reset) clk_div <= 0;
else if (tc) clk_div <= !clk_div;
end
endmodule
I'm trying to make a second counter and millisecond counter using Verilog. The Problem is that whenever I run a simulation, the value of the second counter (clk_1sec) and millisecond counter (clk_1msec) is fixed to 0.
My Simulation shows proper result until 19th line of the code, but the simulation doesn't show the proper result of clk_1sec and clk_1msec (value of those two counters are fixed to 0)
module clk_gen(clk_5k, reset, loopcount, clk_1sec, clk_1msec);
input clk_5k, reset;
output [14:0] loopcount;
output clk_1sec, clk_1msec;
reg [14:0] loopcount;
reg clk_1sec, clk_1msec;
always #(posedge clk_5k or negedge reset)
begin
if (~reset)
begin
clk_1sec <= 0; clk_1msec <= 0; loopcount <= 0;
end
else
loopcount <= loopcount + 2'b10;
begin
if (loopcount += 13'b1001110001000)
clk_1sec = ~clk_1sec;
else if (loopcount += 3'b101)
clk_1msec = ~clk_1msec;
end
end
end
end
endmodule
Expected result is that clk_1sec should change its value when the value of loopcount is loopcount + 5000 (decimal) and clk_1msec should change its value when the value of loopcount is loopcount + 5 (decimal).
There are some misunderstandings in your code:
You are using blocking assignments inside clocked always. You should use only non blocking assignments.
You are using 13 bit constants to operate with a 15 bit register (loopcount). You should use 15 bit constants.
And above all, you are using an improper way to tell if the value of loopcount is multiple of 5 (to count miliseconds). Multiples of something that is not a power of two is difficult to implement in hardware. Either you should use a power of two clock signal (32.768 kHz is a common clock for these applications) or you should use a counter to count cycles to get miliseconds and another one to count miliseconds to get one second.
Assuming a 32.768 kHz clock, your module would go like this:
module clk_gen (
input wire clk32768,
input wire reset,
output reg [15:0] loopcount,
output wire clk_1sec,
output wire clk_1msec
);
assign clk_1sec = loopcount[15]; // 1 exact second (32768 counts)
assign clk_1msec = loopcount[5]; // not quite 1ms, but 0.97ms
always #(posedge clk32768 or negedge reset) begin
if (~reset)
loopcount <= 16'd0;
else
loopcount <= loopcount + 16'd1;
end
endmodule
If you need to stick with a 5KHz clock and/or need precise milisecond measurement (within the limits of your clock oscillator), then you can do as this:
module clk_gen (
input wire clk_5k,
input wire reset,
output reg clk_1sec,
output reg clk_1msec
);
reg [2:0] counter_cycles; // counts from 0 to 4 cycles => 1ms
reg [9:0] counter_msecs; // counts from 0 to 999 msecons => 1s
always #(posedge clk_5k or negedge reset) begin
if (~reset) begin
clk_1sec <= 1'b0;
clk_1msec <= 1'b0;
counter_cycles <= 3'd0;
counter_msecs <= 10'd0;
end
else begin
if (counter_cycles == 3'd4) begin
counter_cycles <= 3'd0;
clk_1msec <= ~clk_1msec;
if (counter_msecs == 10'd999) begin
counter_msecs <= 10'd0;
clk_1sec <= ~clk_1sec;
end
else begin
counter_msecs <= counter_msecs + 10'd1;
end
end
else begin
counter_cycles <= counter_cycles + 3'd1;
end
end
end
endmodule
You can edit/simulate this version at
https://www.edaplayground.com/x/3CjH
The problem is improper nesting of begin/end blocks with the first else. Your indentation does not match what the compiler sees. And I'm sure you meant == instead of +=
This is code for ALU that does addition and multiplication only. An addition is handled in same clock cycle but the multiplication result has to be delayed by 3 clock cycles.
module my_addmul(
//control signals
input i_clk,
input i_rst,
input i_en,
//add=01, mul=10
input [1:0] i_op,
//input and output registers
input [31:0] i_A,
input [31:0] i_B,
output [31:0] o_D,
//to signal if output is valid
output o_done
);
//registers to save output
reg [31:0] r_D;
reg [63:0] r_mul;//(*keep="true"*)
reg r_mul_done;
reg r_mul_done2;
reg r_done;
//updating outputs
assign o_D = r_D;
assign o_done = r_done;
always # (posedge i_clk)
begin
r_done <= 0;
r_mul_done <= 0;
if (i_rst) begin
r_D <= 0;
r_mul <= 0;
r_mul_done <= 0;
r_mul_done2 <= 0;
end else if (i_clk == 1) begin
if (i_en == 1) begin
//addition - assignment directly to OP registers
if (i_op == 01) begin
r_done <= 1;
r_D <= i_A + i_B;
//multiplication - indirect assignment to OP registers
end else if (i_op == 2'b10) begin
r_mul <= i_A * i_B;
r_mul_done <= 1;
end
end
//1-clock cycle delay
r_mul_done2 <= (r_mul_done == 1) ? 1 : 0;
//updating outputs in the 3rd cycle
if (r_mul_done2 == 1) begin
r_D <= r_mul[31:0];
r_done <= 1;
end
end
end
endmodule
The problem is that if the keep attribute is not used, the r_mul register that stores the multiplication output until 3rd clock cycle is optimised out. I read on the problem and realised that Vivado is thinking like this: "If the multiplication happens every clock cycle, the r_mul is over-written before it is sent to output. Therefore, it is a register being written but not read, Lets remove it!" Since I insert the 3 clock cycle wait in test bench, the simulation result is always accurate. I want to know what is the "Proper" way of doing this so I don't have to use the keep attribute. It is an ok solution but I think useful techniques should be learned so hacks don't have to be used. Any ideas or discussion welcome.
If I want to delay a signal, I'd probably insert flops for that. You can probably flop your mul_output like the way you do for the mul_done signal. Also, it is better to have different always blocks for doing the same. You can check the code below but it might be buggy since I haven't simulated/synthesized it -
module my_addmul(
//control signals
input i_clk,
input i_rst,
input i_en,
//add=01, mul=10
input [1:0] i_op,
//input and output registers
input [31:0] i_A,
input [31:0] i_B,
output [31:0] o_D,
//to signal if output is valid
output o_done
);
//registers to save output
reg [31:0] r_D;
reg [63:0] r_mul;//(*keep="true"*)
reg r_mul_1;
reg r_mul_2;
reg r_mul_done;
reg r_mul_done2;
reg r_done;
//updating outputs
assign o_D = r_D;
assign o_done = r_done;
always # (posedge i_clk)
begin
r_done <= 0;
r_mul_done <= 0;
if (i_rst) begin
r_D <= 0;
r_mul <= 0;
r_mul_done <= 0;
r_mul_done2 <= 0;
end else if (i_clk == 1) begin
if (i_en == 1) begin
//addition - assignment directly to OP registers
if (i_op == 01) begin
r_done <= 1;
r_D <= i_A + i_B;
//multiplication - indirect assignment to OP registers
end else if (i_op == 2'b10) begin
r_mul <= i_A * i_B;
r_mul_done <= 1;
end
end
end
end
always # (posedge i_clk)
begin
if (i_rst)
begin
r_mul_1 <= 0;
r_mul_done2 <= 0;
end
else
begin
r_mul_1 <= r_mul;
r_mul_done2 <= r_mul_done;
end
end
always # (posedge i_clk)
begin
if (i_rst)
begin
r_D <= 0;
r_done <= 0;
end
else
begin
r_D <= r_mul_1;
r_done <= r_mul_done2;
end
end
endmodule
How do I initialize the array Save_state? This statement is giving X value at the output:
reg [9:0] count
reg [9:0] Save_state [0: 1024];
always # (posedge Clock )
Count <=count+1 ;
Save_state[count] <=count ;
You can use an initial block as well. This is allowed in simulation and is synthesizable on some architectures (Xilinx FPGA and CPLD support register initialization)
reg [9:0] count
reg [9:0] Save_state [0: 1024];
integer i;
initial begin
count = 0;
for (i=0;i<=1024;i=i+1)
Save_state[i] = 0;
end
always # (posedge Clock ) begin
count <= count + 1;
Save_state[count] <= count;
end
Although for this particular example, in which the elements of the Save_state array will always have the same value, you can do like this (synthesizable on Xilinx and Altera, AFAIK):
reg [9:0] Save_state [0: 1024];
integer i;
initial begin
for (i=0;i<=1024;i=i+1)
Save_state[i] = i[9:0];
end
And at the beginning of you simulation, Save_state already have the values 0,1,2,...,1023 stored in it.
You can use a reset port to initialize count and save_state such as the following code :
integer i;
reg [9:0] count;
reg [9:0] save_state [0:1024];
always #(posedge clock or posedge reset) begin
if (reset) begin
count <= 0;
for (i=0; i<=1024; i=i+1)
save_state[i] <= 0;
end
else begin
count <= count + 1;
save_state[count] <= count;
end
end
The two statements inside the else block is applied at the same time and at the end of always block.
I have one input and one output. And I want to turn the output to 1, if the input was 100 ticks active (100 cycles).
module check_100(
input wire clock,
input wire reset,
input wire in_a,
output reg out_a);
reg[10:0] counter;
always #(posedge clock) begin
counter <= counter + 1;
if(in_a && (counter == 100)) begin
out_a <= 1;
end
end
But it doesn't seem to work properly.
Is this a good way to check, whether a signal is 100 ticks/cycles active or not?
Thank you! :)
One way is to use a continuous assignment to set your output when count==100. When the input goes low, the counter is reset. Hold the count value when it hits 100.
module check_100(
input wire clock,
input wire reset,
input wire in_a,
output wire out_a
);
reg [10:0] counter;
assign out_a = counter == 100;
always #(posedge clock) begin
if (reset) begin
counter <= 0;
end else if (!in_a) begin
counter <= 0;
end else if (counter < 100) begin
counter <= counter + 1;
end
end
endmodule