I have to design an infrared transmitter using a FPGA and Verilog.
One of the conditions is to send a packet every 10Hz , I have a counter that creates a secondary clock at 10Hz from the master clock (100MHz).
The packet contains Start-Gap-Select-Gap-Right-Gap-Left-Gap-Forward-Gap-Backwards-Gap. I have a FSM that do this transition at the postive edge of the 10Hz secondary clock.
Each of these blocks within the packet has its size, with Gap being just empty space that separates them. The direction blocks have bigger size when selected and smaller otherwise.
With the condition that the receiver has a pulse frequency of 36kHz I have another counter that reduces the master clock to 36kHz which i use to generate the pulse sizes for the Start, Select etc. and make the output led 1 while the counter counts up to that size (for cases start, select..) and 0 for Gap state.
However when I look at the LED through my smartphone camera it shows it is on all the time which is what I expect to see as it should send packets 10 times per second.
The problem is that the car is not moving at all, my question is is this the correct logic of doing the things or I am missing something?
Thanks
Requested code:
The counter for the 36kHz pulse
always#(posedge CLK) begin
if(RESET) begin
Counter <= 0;
SEC_CLK <= 0;
end
else if(Counter == 2778) begin
Counter <= 0;
SEC_CLK <= 1'b1;
end
else begin
Counter <= Counter + 1;
SEC_CLK <= 1'b0;
end
end
The 10Hz counter, don't know whether is good to reduce the 36kHz or use the Master Clock, but it is a nice round number so I used the Master CLock
always#(posedge CLK) begin
if(sec_counter == 100000) begin
sec_counter <= 0;
send <= 1;
end
else begin
sec_counter <= sec_counter +1;
send <= 0;
end
end`
The FSM LOGIC:
always#(Curr_State) begin
case(Curr_State)
1'd0: begin //START
Next_State <= 1'd1;
Previous_State <= Next_State;
max_count <= StartBurstSize;
flag <= 0;
end
1'd1: begin //GAP
if(Previous_State <= 1'd7)
Next_State<=1'd0;
else
Next_State <= Previous_State +1;
max_count <= GapSize;
flag <= 1;
IR_LED = 1'b1;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
end
1'd2: begin //SELECT
Next_State <= 1'd1;
Previous_State <= Curr_State;
max_count <= CarSelectBurstSize;
IR_LED = 1'b0;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
end
1'd3: begin //RIGHT
if(BTNR)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd4: begin //LEFT
if(BTNL)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd5: begin //FORWARD
if(BTNU)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd6: begin //Backwards
if(BTND)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
endcase
end
SENDING THE PULSES TO THE IR LED
always#(posedge SEC_CLK) begin
if(send) begin
if(Pcounter == max_count) begin //COUNTING BLOCK SIZE
Pcounter <= 0;
IR_LED=1'b0;
end
else begin
if(flag)
IR_LED=1'b0; //GAP
else
IR_LED=1'b1;
Pcounter <= Pcounter+1;
end
end
end
There is no reset on sec_counter, so the behavior could be unpredictable (unless you specified an initial value when you declared the reg). Since you didn’t include the declaration portion of the code, it’s difficult to tell.
Your state machine design is a little unusual and I think you are not getting the behavior you expect. Generally state machines are coded in one of two ways. One method places the next_state calculation into a combinatorial block with all the state machine inputs and the current state in the sensitivity list of the block. A second synchronous always block (i.e. the sensitivity list posedge clk) of code assigns the next_state to the current_state at the posedge of the state machine clock. A second method uses a single synchronous always block for both the state machines and outputs. In this case there is no next_state variable, you simply assign the new value directly to the state variable, making sure to assign the state value for each branch of a case or if/else statement. The second version can run faster since all outputs are registered, the first version uses less logic and I personally find it easier to decode. Since your design is very slow, I’d suggest using that first version.
Your state machine doesn’t actually hold state since no clock is in use—so it’s not actually a state machine. Try running it off your clk signal. Also, make sure to handle the clock domain crossing properly to avoid metastability issues.
I don't know if you still care about this question, but in your case statements you have something like
1'd2: begin //SELECT
or even
Previous_State <= 1'd7
However, 1'd means a decimal number 1-bit wide, so it cannot ever be anything different than 0 or 1, the most significant bits just get discarded.
Have you tried to simulate this?
Related
I have a newbie FSM Verilog question. In the below code, around line 96, I am incrementing led_num with the non blocking led_num <= led_num+1; However, because of the way my code is setup I have a non blocking curr_state <= next_state at line 82, and then I am doing a next_state <= "NEXT STATE" in every one of my case statements. This is causing me to be in each state 2 clocks and is causing my led_num <= led_num+1 to execute twice, and I want just a single time.
How do I go about fixing this so I am in each state a single clock or how do I prevent the led_num being incremented by two each time? I had one person tell me to non blocking all of the time, but some examples mix them and I am pretty sure I need to move my nextState to use a blocking assignment but I have tried several things so far and I keep messing it up.
`timescale 1ns / 1ps
module ws2812_b(clk, rst, send_the_data, led_data_out);
input clk;
input rst;
input send_the_data;
output reg led_data_out;
parameter NUMBER_LEDS = 5;
parameter ADDRESS_BITS =8;
parameter NUM_BITS = 24;
parameter STATE_BITS = 4;
parameter T0_HIGH_0_COUNT = 6; // .35us (System clock = 12Mhz, 83.3 ns/cycle.
parameter T0_HIGH_1_COUNT = 16; // .9us
parameter CYCLE_COUNT = (T0_HIGH_0_COUNT+T0_HIGH_1_COUNT); //.9+.35
parameter RESET_COUNT = 1500; // 50us
localparam ST_IDLE = 4'd0,
ST_GET_WORD = 4'd1,
ST_SEND_START = 4'd2,
ST_UPDATE_WORD = 4'd3,
ST_DELAY_0 = 4'd4,
ST_DRIVE_0 = 4'd5,
ST_DELAY_1 = 4'd6,
ST_CHECK_WORD_DONE = 4'd7,
ST_SEND_RESET = 4'd8,
ST_NDEF_9 = 4'd9,
ST_NDEF_10 = 4'd10,
ST_NDEF_11 = 4'd11,
ST_DELAY_1S = 4'd12,
ST_NDEF_13 = 4'd13,
ST_NDEF_14 = 4'd14,
ST_NDEF_15 = 4'd15;
reg [STATE_BITS-1:0]currState;
reg [STATE_BITS-1:0]nextState;
reg [14:0] delay_value;
reg [NUM_BITS-1:0] led_word;
reg [5:0] bit_num;
reg [13:0] delay0, delay1;
reg [8:0] led_num;
`define rundelay currState <= ST_DELAY_1S
`define returndelay currState <= nextState
always #(posedge clk, posedge rst)
begin
if (rst) begin
currState <= ST_IDLE;
nextState <= ST_IDLE;
led_data_out <=0;
led_word <= 0;
bit_num <= 0;
delay0 <= 0;
delay1 <=0;
delay_value <=0;
led_num <= 0;
end
else
begin
currState <= nextState;
case (currState)
ST_IDLE: //0
begin
led_data_out <= 0;
nextState <= ST_GET_WORD;
led_num <= 0;
end
ST_GET_WORD: //1
begin
led_word <= 24'h335599;
bit_num <= 0;
nextState <= ST_SEND_START;
led_num <= led_num + 1 ; // ***** DOUBLE INCREMENTS ****
end
ST_SEND_START: //2
begin
led_data_out <= 1;
if (led_word[0]==1)
begin
delay0 <= T0_HIGH_1_COUNT;
delay1 <= (CYCLE_COUNT - T0_HIGH_1_COUNT + 1);
end else
begin
delay0 <= T0_HIGH_0_COUNT;
delay1 <= (CYCLE_COUNT - T0_HIGH_0_COUNT + 1);
end
nextState <= ST_UPDATE_WORD;
end
ST_UPDATE_WORD: //3
begin
led_word[23:0] <= {1'b0,led_word[23:1]};
bit_num <= bit_num+1;
nextState <= ST_DRIVE_0;
delay_value <= delay0;
`rundelay;
end
ST_DRIVE_0: //5
begin
led_data_out <= 0;
nextState <= ST_CHECK_WORD_DONE;
delay_value <= delay1;
`rundelay;
end
ST_CHECK_WORD_DONE: //4
begin
if (bit_num<24)
begin
nextState <= ST_SEND_START;
end else
begin
if (led_num<3)
begin
nextState <= ST_GET_WORD;
end else
begin
nextState <= ST_SEND_RESET;
end
end
end
ST_SEND_RESET:
begin
led_data_out <= 0;
nextState <= ST_IDLE;
delay_value <= 2000;
`rundelay;
end
ST_DELAY_1S: // Delay of ~1sec. Note that the total delay is one clock cycle more because of the state transition.
begin
if (delay_value)
begin
delay_value <= delay_value -1; // as long as delay_value is larger than zero ( bitwise or)
// decrement (decrementing counters synthesize smaller than
// incrementing counters as no comparator is needed, only a
// zero check which is a bitwise or.
currState <= currState;
end
else
begin
//currState <= nextState; // if it hits zero ; throw the target state into currentstate.
`returndelay;
end
end
default:
begin
currState <= ST_IDLE;
end
endcase
end
end
endmodule
As Greg pointed out, FSMs are implemented one of two ways:
Single always block (like you've implemented) In this case, every clock runs through the "always block" once and you only need one "State" variable. All variables are "non-blocking" ("<=" symbol) which implies that all statements are executed in parallel.
Double always blocks. In this case, the first always block is purely combinational, which is fully "blocking" assigns so that you can have sequential arithmetic to calcuate your final value. The second always block behaves like a set of registers to let the whole state-machine "step" to the next state on the clock edge. This setup requires "currState" and "nextState". The first combinational always block calculates "nextState" from "currState". The second (sequential) always block simply transfers nextState to currState on a clock edge.
In your case, it looks like you're trying to jump to a "delay" state for a certain number of cycles and then jump back to the next state in the sequence like a subroutine in C code that delays.
While I haven't run it, I think the following is closer to what you're trying to do. When you jump to ST_DELAY_1S, you need to save the state you want to return to in a separate variable (I used afterDelayState) so that you can spin in the delay state and then return (much like the instruction pointer on the stack) to the proper place.
`timescale 1ns / 1ps
module ws2812_b(clk, rst, send_the_data, led_data_out);
input clk;
input rst;
input send_the_data;
output reg led_data_out;
parameter NUMBER_LEDS = 5;
parameter ADDRESS_BITS =8;
parameter NUM_BITS = 24;
parameter STATE_BITS = 4;
parameter T0_HIGH_0_COUNT = 6; // .35us (System clock = 12Mhz, 83.3 ns/cycle.
parameter T0_HIGH_1_COUNT = 16; // .9us
parameter CYCLE_COUNT = (T0_HIGH_0_COUNT+T0_HIGH_1_COUNT); //.9+.35
parameter RESET_COUNT = 1500; // 50us
localparam ST_IDLE = 4'd0,
ST_GET_WORD = 4'd1,
ST_SEND_START = 4'd2,
ST_UPDATE_WORD = 4'd3,
ST_DELAY_0 = 4'd4,
ST_DRIVE_0 = 4'd5,
ST_DELAY_1 = 4'd6,
ST_CHECK_WORD_DONE = 4'd7,
ST_SEND_RESET = 4'd8,
ST_NDEF_9 = 4'd9,
ST_NDEF_10 = 4'd10,
ST_NDEF_11 = 4'd11,
ST_DELAY_1S = 4'd12,
ST_NDEF_13 = 4'd13,
ST_NDEF_14 = 4'd14,
ST_NDEF_15 = 4'd15;
reg [STATE_BITS-1:0] State;
reg [STATE_BITS-1:0] afterDelayState;
reg [14:0] delay_value;
reg [NUM_BITS-1:0] led_word;
reg [5:0] bit_num;
reg [13:0] delay0, delay1;
reg [8:0] led_num;
//`define rundelay currState <= ST_DELAY_1S
//`define returndelay currState <= nextState
always #(posedge clk, posedge rst)
begin
if (rst) begin
State <= ST_IDLE;
afterDelayState <= ST_IDLE;
led_data_out <=0;
led_word <= 0;
bit_num <= 0;
delay0 <= 0;
delay1 <=0;
delay_value <=0;
led_num <= 0;
end
else
begin
case (State)
ST_IDLE: //0
begin
led_data_out <= 0;
State <= ST_GET_WORD;
led_num <= 0;
end
ST_GET_WORD: //1
begin
led_word <= 24'h335599;
bit_num <= 0;
State <= ST_SEND_START;
led_num <= led_num + 1 ; // ***** DOUBLE INCREMENTS ****
end
ST_SEND_START: //2
begin
led_data_out <= 1;
if (led_word[0]==1)
begin
delay0 <= T0_HIGH_1_COUNT;
delay1 <= (CYCLE_COUNT - T0_HIGH_1_COUNT + 1);
end else
begin
delay0 <= T0_HIGH_0_COUNT;
delay1 <= (CYCLE_COUNT - T0_HIGH_0_COUNT + 1);
end
State <= ST_UPDATE_WORD;
end
ST_UPDATE_WORD: //3
begin
led_word[23:0] <= {1'b0,led_word[23:1]};
bit_num <= bit_num+1;
State <= ST_DRIVE_0;
delay_value <= delay0;
// delay "delay0" cycles and then jump to ST_DRIVE_0
delay_value <= delay0;
State <= ST_DELAY_1S;
afterDelayState <= ST_DRIVE_0;
end
ST_DRIVE_0: //5
begin
led_data_out <= 0;
// delay "delay1" cycles and then jump to ST_CHECK_WORD_DONE
delay_value <= delay1;
State <= ST_DELAY_1S;
afterDelayState <= ST_CHECK_WORD_DONE;
end
ST_CHECK_WORD_DONE: //4
begin
if (bit_num<24)
begin
State <= ST_SEND_START;
end else
begin
if (led_num<3)
begin
State <= ST_GET_WORD;
end else
begin
State <= ST_SEND_RESET;
end
end
end
ST_SEND_RESET:
begin
led_data_out <= 0;
// delay 2000 cycles and then jump to ST_IDLE
delay_value <= 2000;
State <= ST_DELAY_1S;
afterDelayState <= ST_IDLE;
end
// This is a special "delay" loop that jumps to a specified "afterDelayState" when the delay_value runs to zero
ST_DELAY_1S: // Delay of ~1sec. Note that the total delay is one clock cycle more because of the state transition.
begin
if (delay_value)
begin
// every clock cycle stay in the ST_DELAY_1S state until the "delay_value" runs to zero
delay_value <= delay_value -1; // as long as delay_value is larger than zero ( bitwise or)
// decrement (decrementing counters synthesize smaller than
// incrementing counters as no comparator is needed, only a
// zero check which is a bitwise or.
//
// no change in State, so we stay here
// State <= State
end
else
begin
//after it hits zero, jump to the state we stored in afterDelayState
State <= afterDelayState;
end
end
default:
begin
State <= ST_IDLE;
end
endcase
end
end
endmodule
In the code above, each state has only one State <= (new state) command.
We only assign the afterDelayState variable when jumping to the ST_DELAY_1S "subroutine" so we know where to go back to.
I took out the `defines to make all assignments more explicit.
One side recommendation is to install VSCode and iverilog so that you can do syntax checking, auto-formatting and compile checking inside the editor. This quickly helped me clean things up.
New to Verilog, Basys3 board and Vivid 2021.2.
Trying to implement a typical stopwatch with Stop/Start and Lap/Reset buttons.
A divider produces 1kHz and 100Hz clock from the board clock, 100Hz is for button debounce (and seven segment display multiplexing, next todo), the 1kHz drives a 20 bit 5 x 4 bit BCD counter, the low 16 bits of which drive a latch to freeze the display, the latch drives the 16 on board LEDs.
I've test 'wired' this up and the modules perform as expected. It's only when I add the FSM I run into trouble.
The FSM is simple, the two buttons determine the state changes and the state sets three outputs to control the counter.
The state module as been through many versions, tried using buttons in the sensitivity list, tried with button edges and levels, tried *, tried blocking and non-blocking assignments, can't get it right. The current error is:
[Synth 8-3332] Sequential element (state/transfer_reg) is unused and will be removed from module stopwatch.
The error changes but it's always Synth 8-3332 removing something, even curr_state or next_state.
The RTL synthesis schematic shows exactly what I expect, later schematics show the two buttons, 16 LEDs and nothing in between.
I'm lost at this stage, have I missed something fundamental?
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
//
// Create Date: 02/02/2022 0800
//
// Module Name: state
// Project Name: Stop Watch
// Target Devices: BASYS 3
//
// state machine
//
// inputs:
// start-stop button via debounce (both edg and level are available)
// lap-reset buttonvia debounce (both edg and level are available)
//
// outputs:
// control 4 x 4 bit BCD counters and output latch
// clear state
// enabvble couter to count
//. transfer counter value to latch
//
////////////////////////////////////////////////////////////////////////////////
module state (
input clk,
input lap_reset,
input start_stop,
output reg clear,
output reg enable,
output reg transfer
);
// state encodings
localparam
RESET_0 = 3'd0,
STOPPED_1 = 3'd1,
RUNNING_2 = 3'd2,
PRELAP_3 = 3'd3,
LAP_4 = 3'd4;
// state reg
reg[2:0] curr_state;
reg[2:0] next_state;
// setup
initial
begin
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end
// sync state transitons to clk
// always # (posedge clk)
// begin
// curr_state <= next_state;
// end
// state machine
always # (posedge clk)
begin
curr_state <= next_state;
case (curr_state)
RESET_0:
begin
// init, stop counter, clear counter
// transfer count to latch
enable <= 0;
clear <= 1;
transfer <= 1;
next_state <= STOPPED_1;
end
STOPPED_1:
begin
// stop counter, clear counter
enable <= 0;
clear <= 0;
transfer <= 0;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= RESET_0;
else
next_state <= curr_state;
end
RUNNING_2:
begin
// start or continue counting
// transfer count to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
PRELAP_3:
begin
// start or continue counting
// don't update latch
enable <= 1;
clear <= 0;
transfer <= 0;
next_state <= LAP_4;
end
LAP_4:
begin
// continue counting
// transfer counter to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= RUNNING_2;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
default:
begin
enable <= 0;
clear <= 0;
transfer <= 0;
next_state <= RESET_0;
end
endcase
end
endmodule
Getting somewhere at last, thankyou all.
After correcting a logical error and a couple of constants 0'b0 which make little sense (the compiler didn't complain about them) and doing suggested fixes my stopwatch works.
The SM structure is the 3 blocks, sync transitions, next state 'gotos' and state actions. I started with the suggested always # (*) but had to change to a posedge clk for it to work, not sure why.
Got rid of the inferred latches and now understand why they come about.
About generating a reset signal, I assume the Artix chip has one but it doesn't get a mention in the supplied xdc file, I was trying to simulate a reset held low (active) then going high a short time later, determined by a clock divider - which should have a reset... Also read Xilinx WP272 which tells a different story.
Thanks again.
Just from www.javatpoint.com/verilog-initial-block:
"An initial block is not synthesizable and cannot be converted into a
hardware schematic with digital elements. The initial blocks do not
have more purpose than to be used in simulations. These blocks are
primarily used to initialize variables and drive design ports with
specific values."
I am not sure now about the code for that FPGA, but in common ASICs I would remove the "initial" code section, which you use to implement the reset behaviour and add an actual reset section in the always#.
always#(posedge clk)
begin
if (rst) begin
// do the reset
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end else begin
// the rest
end
end
EDITED:
Never leave a signal without a default value, as it will infer latches instead of flip-flops, which create problems when inferring sequential logic (of course latches are useful in some scenarios).
When one wants to build a finite state machine (FSM) there are two common approaches: Mealy and Moore. I will explain how the sequential logic should be implemented with a Moore FSM:
A synchronous always# block to write the state: cur_state <= next state.
A combinational block to generate next_state value based on cur_state and inputs.
A combinational block to generate outputs based on the state.
always#(posedge clk, rst)
begin
if (rst = '1') begin
cur_state <= State_0;
end else begin
cur_state <= next_state;
end
end
always_comb(cur_state, my_inputA)
begin
if (cur_state = State_0) begin
if(my_inputA)
next_state = State_1;
else
next_state = Stage_0;
end else if (cur_state = State_1) begin
next_state = State_2;
end
end
always_comb(cur_state)
begin
if (cur_state = State_0) begin
my_outputA = '1';
end else if (cur_state = State_1) begin
my_outputA = '0';
end else if (cur_state = State_2) begin
my_outputA = '1';
end
end
the picture indicates what I want the output signal is: the high signal double and the low signal keep same.
I wrote the code like:
integer x=0, count_valid=1, count_down=0;
reg valid_1, valid_reg;
always#(posedge clk)
begin
if(tag==1) begin
if(valid) begin
count_valid <= count_valid +1;
x<=x+1;
valid_reg <= 1;
end
else begin
x<=0;
count_down <= count_down+1;
if(count_valid>0) begin
valid_reg <= 1;
count_valid <= count_valid -1;
end
else if(count_down>0) begin
valid_reg <= 0;
count_down <= count_down-1;
end
end
end
else begin
valid_reg <= valid;
if (valid) x<=x+1;
else x<=0;
end
valid_1 <= valid_reg;
end
valid is the original signal in the picture and valid_reg is the modified signal. the count_valid is used to count how many cycles for high and use it to sub one to achieve the doubling. then count_down is for counting the cycles of low signal. but I realized when valid high the valid_reg will high.
can anyone give me some idea how to make the low signal run same cycles in output signal? any idea is also great.
You didn't mention if the input signal was periodic or not. Given the fact that your output is stretched over time, if the input is not periodic, then you would need infinite storage to keep track of what the input signal looked like. If it is periodic, or quasi-periodic, you can do something like below.
Keep track of the high count and low count in one block, and generate the output signal in another block, using the current registered values of the counts. Getting the output's first edge to line up with the input's is kind of tricky, requiring a mux, selected depending on whether it's the first time through the loop or not.
integer count, count_q, countdown, countdown_q, outcount;
logic valid_q, valid_reg, out_q;
logic new;
always #(posedge clk or negedge reset_n)
begin
if(~reset_n)
begin
if(~reset_n)
begin
new <= 1;
valid_q <= 0;
count_q <= 0;
countdown_q <= 0;
end
else
begin
valid_q <= valid;
if(valid & ~valid_q)//rising edge
begin
count <= 1;
countdown_q <= countdown;
end
else if(~valid & valid_q)//falling edge
begin
new <= 0;
count_q <= count;
countdown <= 1;
end
else if(valid)
count <= count+1;
else
countdown <= countdown+1;
end
end
end
always #(posedge clk or negedge reset_n)
begin
if(~reset)
begin
outcount <= 0;
out_q <= 0;
end
else
begin
if(new & valid & ~valid_q)
begin
out_q <= 1;
outcount <= 2;//valid_reg is already high here
end
else
if(out_q && (outcount == (count_q<<1)))
begin
out_q <= 0;
outcount <= 1;
end
else if(~out_q && (outcount == (countdown_q)))
begin
out_q <= 1;
outcount <= 1;
end
else
outcount <= outcount + 1;
end
end
assign valid_reg = new? valid : out_q;//this gets your initial rising edge lined up
I am new to Verilog, so I am not sure how to go about doing this. I have a clock, 'samp_clk', that toggles every 10 clock cycles of the system clock, 'clock' (or that's what I tried to do). This is what I have so far:
//'counter' counts the number of rising edges for system clock
//'samp_clk' is the sample clock, 'clock' is system clock
always # (posedge clock)begin
if(~reset)begin
if(counter == 10)begin
samp_clk <= 1;
counter <= 0;
end
else begin
samp_clk <= 0;
counter <= counter + 1;
end
end
end
The way I wrote it, I feel like my samp_clk will only stay asserted for one clock cycle. How can I make it so that it toggles between 1 and 0 every ten clock cycles?
From your code:
if(counter == 10)begin
samp_clk <= 1;
counter <= 0;
end
This will result to 11 clock cycles since we start counting from 0 to 10.
First step, define a counter wherein it resets to a certain
number (clock cycles). For example, you want to detect 10 clock
cycles (n = 10), when counter is more than or equal to 9,
it sets back to 0.
always # (posedge clk)begin
if(~reset)begin
counter <= 0;
end
else begin
if(counter >= 9)begin
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
end
Then simply, toggle samp_clk based from the counter when it's equal to n-1 (10 - 1 = 9).
always #(posedge clk) begin
if (~reset) begin
samp_clk <= 0;
end
else begin
if (counter == 9) begin
samp_clk <= ~samp_clk;
end
end
end
Notice that I've separated two flip-flops to make debugging easy
and clear enough to understand its logic.
Here is the code with a test bench included.
module ten_clock(input clk, reset, output reg samp_clk);
reg [7:0] counter;
//'counter' counts the number of rising edges for system clock
always # (posedge clk)begin
if(~reset)begin
counter <= 0;
end
else begin
if(counter == 10)begin
//samp_clk <= 1;
counter <= 0;
end
else begin
//samp_clk <= 0;
counter <= counter + 1;
end
end
end
//'samp_clk' is the sample clock, 'clock' is system clock
always #(posedge clk) begin
if (~reset) begin
samp_clk <= 0;
end
else begin
if (counter == 9) begin
samp_clk <= ~samp_clk;
end
end
end
endmodule
module test;
reg clk, reset;
wire samp_clk;
ten_clock ten_clock(.*);
initial begin
clk = 0;
forever #1 clk = !clk;
end
initial begin
reset <= 1;
repeat (2) #(posedge clk);
reset <= 0;
repeat (2) #(posedge clk);
reset <= 1;
repeat (100) #(posedge clk);
$finish;
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
end
endmodule
You can try to run this
code and see the wave form
if this behavior is what you expect.
You want to toggle it, so toggle it.
Also note that to toggle every 10 clocks, you will have to set your counter to 0 when its value is 10-1.
Try this (not tested):
//'counter' counts the number of rising edge s for system clock
//'samp_clk' is the sample clock, 'clock' is sy stem clock
always # (posedge clock)begin
if(~reset)begin
if(counter == 9)begin
samp_clk <= ~samp_clk;
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
else begin
samp_clk <= 0;
end
end
You are correct, this code sets samp_clk to be 1 when the counter is 10 and otherwise sets it to 0. This means you will have a signal which is asserted for 1 clock cycle and low for 10 clock cycles. The basic logic is correct (count for 10 clock cycles) but the value given to samp_clk is incorrect.
What you want to have is that samp_clk is the same value as it was in the previous cycle if counter ins't 10 and to flip samp_clk when it is. To flip a signal you want to assign the signal to the inverse of a signal: samp_clk <= ~samp_clk.
After you have that working you might need to refactor your code because I think it is going to produce latches in its current state.
`timescale 1ns / 1ps
module stopwatch(
input clock,
input reset,
input increment,
input start,
output [6:0] seg,
output dp,
output [3:0] an
);
reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
reg [22:0] ticker;
wire click;
//the mod 1kHz clock to generate a tick ever 0.001 second
always # (posedge (clock) or posedge (reset))
begin
if(reset)
begin
ticker <= 0;
end
else
begin
if (start)
begin
if(ticker == (100000 - 1)) //if it reaches the desired max value reset it
ticker <= 0;
else if (increment)
ticker <= ticker;
else
ticker <= ticker + 1;
end
end
end
//increment a second everytime rising edge of down button
reg [3:0] inc_temp;
always # (posedge (increment))
begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
assign click = ((ticker == (100000 - 1))?1'b1:1'b0); //click to be assigned high every 0.001 second
//update data start from here
always # (posedge (clock) or posedge (reset))
begin
if(reset)
begin
reg_d0 <= 0;
reg_d1 <= 0;
reg_d2 <= 0;
reg_d3 <= 0;
end
else
begin
if (increment)
begin
reg_d3 <= inc_temp;
reg_d0 <= reg_d0;
reg_d1 <= reg_d1;
reg_d2 <= reg_d2;
end
else if (click) //increment at every click
begin
if(reg_d0 == 9) //xxx9 - 1th milisecond
begin
reg_d0 <= 0;
if (reg_d1 == 9) //xx99 - 10th milisecond
begin
reg_d1 <= 0;
if (reg_d2 == 9) //x999 - 100th milisecond
begin
reg_d2 <= 0;
if(reg_d3 == 9) //9999 - The second digit
reg_d3 <= 0;
else
reg_d3 <= reg_d3 + 1;
end
else
reg_d2 <= reg_d2 + 1;
end
else
reg_d1 <= reg_d1 + 1;
end
else
reg_d0 <= reg_d0 + 1;
end
else
begin
reg_d3 <= reg_d3;
reg_d0 <= reg_d0;
reg_d1 <= reg_d1;
reg_d2 <= reg_d2;
end
end
end
//Mux for display 4 7segs LEDs
localparam N = 18;
reg [N-1:0]count;
always # (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always # (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = reg_d0;
an_temp = 4'b1110;
reg_dp = 1'b1;
end
2'b01:
begin
sseg = reg_d1;
an_temp = 4'b1101;
reg_dp = 1'b0;
end
2'b10:
begin
sseg = reg_d2;
an_temp = 4'b1011;
reg_dp = 1'b1;
end
2'b11:
begin
sseg = reg_d3;
an_temp = 4'b0111;
reg_dp = 1'b0;
end
endcase
end
assign an = an_temp;
//update the data to display to LEDs
reg [6:0] sseg_temp;
always # (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000;
4'd1 : sseg_temp = 7'b1111001;
4'd2 : sseg_temp = 7'b0100100;
4'd3 : sseg_temp = 7'b0110000;
4'd4 : sseg_temp = 7'b0011001;
4'd5 : sseg_temp = 7'b0010010;
4'd6 : sseg_temp = 7'b0000010;
4'd7 : sseg_temp = 7'b1111000;
4'd8 : sseg_temp = 7'b0000000;
4'd9 : sseg_temp = 7'b0010000;
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign seg = sseg_temp;
assign dp = reg_dp;
endmodule
I'm trying to design a stop watch, but I'm stuck at the increment thing. The intent is when I press increment(a button), the reg_d3 will increment by one and hold its state until the button is released. I'm able to make the clock stop when the button is pressed, but I can't update the reg_d3. I always receive
[Place 30-574] Poor placement for routing between an IO pin and BUFG
I don't know why; I use increment in the clkdivider just find.
I think the problem is related to this part of your code:
always # (posedge (increment))
begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
You are basically using an input signal as a clock, and that is completely discouraged when designing for a FPGA. The P&R tries to re-route an IO pin to a BUFG (global buffer) inside the FPGA so it can be used as a clock.
For FPGA design, you should use one clock signal for all your always #(posedge...) constructions, and use input signals to conditionally load/update the register.
To do that, you have first to synchronize your increment signal to your clk, so avoiding metastability issues:
reg incr1=1'b0, incr2=1'b0;
always #(posedge clk) begin
incr1 <= increment;
incr2 <= incr1;
end
wire increment_synched = incr2;
Then, deglitch increment_synched and detect a rising edge in it:
reg [15:0] incrhistory = 16'h0000;
reg incr_detected = 1'b0;
always #(posedge clk) begin
incrhistory <= { incrhistory[14:0] , increment_synched };
if (incrhistory == 16'b0011111111111111)
incr_detected <= 1'b1;
else
incr_detected <= 1'b0;
end
To detect a valid rising edge, we store a history of the last 16 values of increment_synched. When a valid steady change from 0 to 1 is produced, the history pattern will match the pattern 0011111111111111. Then, and only then, we signal it by raising incr_detected to 1. The next clock cycle, the history pattern won't match the above sequence, and incr_detected will go down to 0 again.
Prior to that, multiple bounces in the push button increment is connected to would cause many transitions, leading to many increments. Using a pattern matching like that eliminates those glitches caused by multiple bounces. With 1Khz clock as you seem to use, this pattern should be enough.
Now you can use incr_detected in your original code, incr_detected wil be 1 for just a single clk cycle.
always # (posedge clk) begin
if (incr_detected) begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
end
You can test these additions using the following simulation:
http://www.edaplayground.com/x/AQY
What you will see there is a module that takes your increment input signal from the outside, and generate a glitch-free one-cycle pulse when the input signal makes a final transition from low to high level.
Actually, I've written two versions. The second one tries to mimic the behaviour of a monostable, so the input won't be sampled for a specific period of time after the first low to high transition is detected.
You will see that the second version produces a pulse much sooner than the first version, but it's also prone to take a glitch as valid rising edge, as showed in the simulation. I'd stick with the first version then.