Implementing combinational lock in verilog - verilog

Problem Statement:
Design and implement a control unit for a digital lock. The digital
lock has the passcode “1010”. The code should be entered via 2 Push
Buttons: one button for entering 1’s (B1) and another for entering 0’s
(B0). Use a third push button (Reset) to add reset functionality.
Based on the entered code, glow an LED for the following outputs
LED_0 will glow indicating PASS, if the entered 4-digit binary code is correct
LED_1 will glow indicating FAIL, if the entered 4-digit binary code is incorrect
We need to make sure output is given only after all four inputs are taken.
Error: My coded module won't ever show a pass or fail output.
FSM State diagram to be implemented
module lock_FSM(
input B0,
input B1,
input Reset,
input Clk,
output reg PASS,
output reg FAIL
);
reg [3:0] present_state, next_state;
parameter S0 = 4'b0000, S1 = 4'b0001, S2 = 4'b0010, S3 = 4'b0011, S4 = 4'b0100;
parameter E1 = 4'b0101, E2 = 4'b0110, E3 = 4'b0111, E4 = 4'b1000;
//State register
always #(posedge Clk, posedge Reset)
begin
if(Reset == 1)
present_state = S0;
end
always #(posedge B0, posedge B1)
begin
present_state = next_state;
end
//Input block
always # (present_state, B0, B1)
begin
if(B0 == 0 && B1 == 0)
next_state = present_state;
else
case (present_state)
S0 : next_state = B1 ? S1 : E1;
S1 : next_state = B0 ? S2 : E2;
S2 : next_state = B1 ? S3 : E3;
S3 : next_state = B0 ? S4 : E4;
E1 : next_state = E2;
E2 : next_state = E3;
E3 : next_state = E4;
endcase
end
//Output
always#(present_state)
begin
case(present_state)
S4: begin PASS = 1; FAIL = 0; end
E4: begin PASS = 0; FAIL = 1; end
default : begin PASS = 0; FAIL = 0; end
endcase
end
endmodule
The output should have been PASS = 1 after 4th posedge in (B0 or B1) and stayed there until Reset is pressed.
I need to update the states only when one of B0 or B1 is pressed (as B1 and B0 are push buttons).

There is a problem with how you coded your state register. All assignments to a signal should be made within a single always block, not from 2 blocks. Change:
always #(posedge Clk, posedge Reset)
begin
if(Reset == 1)
present_state = S0;
end
always #(posedge B0, posedge B1)
begin
present_state = next_state;
end
to:
always #(posedge Clk, posedge Reset) begin
if (Reset == 1) begin
present_state <= S0;
end else begin
present_state <= next_state;
end
end
In a typical FSM, updating the present state should be unconditional (not dependent upon signals like B0). You should account for those conditions in your next_state logic. Also, good coding practices recommend nonblocking (<=) assignments in sequential always blocks.
Another issue is that you have no way to exit the E4 state (aside from an asynchronous reset). Perhaps you should add a case to your case statement for that. Also, since you declared only 9 of the possible 16 states, the convention is to use a default statement to handle the undefined states.

Related

How to write a verilog code in two-always-block style with multiple state regs?

I'm a begginer of Verilog. I read a several materials about recommended Verilog coding styles like this paper and stackoverflow's questions.
Now, I learned from them that "two always block style" is recommended; separate a code into two parts, one is a combinational block that modifies next, and the another is a sequential block that assigns it to state reg like this.
reg [1:0] state, next;
always #(posedge clk or negedge rst_n)
if (!rst_n)
state <= IDLE;
else
state <= next;
always #(state or go or ws) begin
next = 'bx;
rd = 1'b0;
ds = 1'b0;
case (state)
IDLE : if (go) next = READ;
else next = IDLE;
...
And here is my question. All example codes I found have only one pair of registers named state and next.
However, if there are multiple regs that preserve some kinds of state, how should I write codes in this state-and-next style?
Preparing next regs corresponding to each of them looks a little redundant because all regs will be doubled.
For instance, please look at an UART sender code of RS232c I wrote below.
It needed wait_count, state and send_buf as state regs. So, I wrote corresponding wait_count_next, state_next and send_buf_next as next for a combinational block. This looks a bit redundant and troublesome to me. Is there other proper way?
module uart_sender #(
parameter clock = 50_000_000,
parameter baudrate = 9600
) (
input clk,
input go,
input [7:0] data,
output tx,
output ready
);
parameter wait_time = clock / baudrate;
parameter send_ready = 10'b0000000000,
send_start = 10'b0000000001,
send_stop = 10'b1000000000;
reg [31:0] wait_count = wait_time,
wait_count_next = wait_time;
reg [9:0] state = send_ready,
state_next = send_ready;
reg [8:0] send_buf = 9'b111111111,
send_buf_next = 9'b111111111;
always #(posedge clk) begin
state <= state_next;
wait_count <= wait_count_next;
send_buf <= send_buf_next;
end
always #(*) begin
state_next = state;
wait_count_next = wait_count;
send_buf_next = send_buf;
case (state)
send_ready: begin
if (go == 1) begin
state_next = send_start;
wait_count_next = wait_time;
send_buf_next = {data, 1'b0};
end
end
default: begin
if (wait_count == 0) begin
if (state == send_stop)
state_next = send_ready;
else
state_next = {state[8:0], 1'b0};
wait_count_next = wait_time;
send_buf_next = {1'b1, send_buf[8:1]};
end
else begin
wait_count_next = wait_count - 1;
end
end
endcase
end
assign tx = send_buf[0];
assign ready = state == send_ready;
endmodule
I think you did a good job and correctly flopped the variables. The issue is that without flops you would have a loop. i.e. if you write something like the following, the simulation will loop and silicon will probably burn out:
always_comb wait_count = wait_count - 1;
So, you need to stage this by inserting a flop:
always_ff #(posedge clk)
wait_count <= wait_count - 1;
Or in your case you you used an intermediate wait_count_next which is a good style:
always_ff #(posedge clk)
wait_count_next <= wait_count;
always_comb
wait_count = wait_count_next;
You might or might not have an issue with the last assignments. Which version of the signals you want to assign to tx and ready? the flopped one or not?
And yes, you can split theses blocks in multiple blocks, but in this case there seems to be no need.
And yes, the other style would be write everything in a single flop always block. But this will reduce readability, will be more prone to your errors and might have synthesis issues.

Keeping count of button clicks in verilog

I am creating a vending machine in verilog. There is one button on the FPGA board to act as the coin inserter, every time the button is pushed it will add a 'quarter' to the total amount the user can spend, and display the total on the left and right seven segment displays.
Ex.
1st button push : 25 cents
2nd button push : 50 cents
3rd button push : 75 cents
4th button push : $1.00 (10 on the seven segment display).
Wont increment after the 4th button press.
input quarterIn,
output reg [4:0] state,
output reg [4:0] next_state,
output reg totalChange,
output reg [7:0] RSSD,
output reg [7:0] LSSD
);
/***coin implementation***/
parameter
c0 = 0,
c1 = 1,
c2 = 2,
c3 = 3,
c4 = 4;
always #(posedge clock)
begin
state = next_state;
end
always # (quarterIn or totalChange)
begin
case(totalChange)
0: begin if(quarterIn == 1) totalChange = 1; state = c1; end
1: begin if(quarterIn == 1) totalChange = 2; state = c2; end
2: begin if(quarterIn == 1) totalChange = 3; state = c3; end
3: begin if(quarterIn == 1) totalChange = 4; state = c4; end
4: begin if(quarterIn == 1) totalChange = 4; state = c4; end
endcase
end
I am getting stuck on how to keep count of the button clicks. I can see the first value on the seven segment display, but am unsure as to how to increment the total coins. I couldn't find any sort of information on this from trying to research on my own.
From what I understood, you need a saturating counter to keep track of the button presses.
In order to count, you need a clock in the system:
input clock;
And you'll need a reset signal to initialize the counter to a known value, zero in this case:
input reset;
And the counter (equivalent to the state variable, let me just call it num_push):
reg [2:0] num_push;
The saturating counter can be specified this way:
always #(posedge clock) begin
if (reset) begin // Active high, synchronous reset
num_push <= 3'b0;
end else begin
if (quarterIn == 1'b1 && num_push != 3'b100) begin
num_push <= num_push + 3'b1;
end
end
end
This will synthesize to a counter with a count-enable on your FPGA and the enable will be equal to quarterIn == 1'b1 && num_push != 3'b100. You could press reset to start over.
Now, there are a few issues to be addressed before we put this on an FPGA. First of all, quarterIn needs to be synced for metastability:
reg quarterIn_f;
reg quarterIn_sync;
always #(posedge clock) begin
quarterIn_f <= quarterIn;
quarterIn_sync <= quarterIn_f;
end
We should use only quarterIn_sync in the design and never quarterIn directly. You should do the same with for the reset signal as well.
Second, the signals that come from the keys need to be debounced. Debouncing is a whole topic in itself, so I'll skip it for the time being :(
Another thing is that the clock needs to be pulled from the onboard clock generator circuitry and this clock will be running at a few MHz. A typical button-press lasts for about 500ms and this means our counter will sample a few hundred thousand keypresses in a single press. To avoid this, we should count the edge of quarterIn_sync, and not the level:
wire quarterIn_edge;
req quarterIn_sync_f;
always #(posedge clock) begin
if (reset) begin
quarterIn_sync_f <= 1'b0;
end else begin
quarterIn_sync_f <= quarterIn_sync;
end
end
assign quarterIn_edge = quarterIn_sync & ~quarterIn_sync_f; // Detects rising edge
Now, replace the quarterIn in the saturating counter code with quarterIn_edge:
always #(posedge clock) begin
if (reset) begin
num_push <= 3'b0;
end else begin
if (quarterIn_edge == 1'b1 && num_push != 3'b100) begin
num_push <= num_push + 3'b1;
end
end
end
And we're done!

one hot encoding in Verilog

Im just starting to learn how to code in Verilog. Can anyone help me figure out how to implement the following code in verilog using one-hot encoding
module Controller(b, x, clk, rst);
input b, clk, rst;
output x;
reg x;
parameter Off = 2'b00,
On1 = 2'b01,
On2 = 2'b10,
On3 = 2'b11;
reg [1:0] currentstate;
reg [1:0] nextstate;
//state register
always # (posedge rst or posedge clk)
begin
if(rst==1)
currentstate <= Off;
else
currentstate <= nextstate;
end
//combinational
always # (*)
begin
case (currentstate)
Off: begin
x <= 0;
if(b==0)
nextstate <= Off;
else
nextstate <= On1;
end
On1 : begin
x <= 1;
nextstate <= On2;
end
On2 : begin
x <= 1;
nextstate <= On3;
end
On3 : begin
x <= 1;
nextstate <= Off;
end
endcase
end
I tried changing the parameters to:
parameter Off = 4'b0001,
On1 = 4'b0010,
On2 = 4'b0100,
On3 = 4'b1000;
However, ive read that this is not a good implementations.
Some of the advantages of onehot encoding in FSMs are as follows:
Low switching activity. Since only single bit is switched at a time, the power consumption is less and it is less prone to glitches.
Simplified encoding. One can determine the state just by looking at the bit position of '1' in the current state variable.
The disadvantage of this technique is that it requires more number of flops. So, if one has a FSM with 10 different states, one needs 10 flops, while one needs only 4 flops when using decimal encoding.
Coming to your question, it is simple to change to onehot encoded FSM. One needs to implement a case statement based on the position of 1 in the currentstate variable. The code snippet can be implemented as follows:
parameter Off = 2'b00,
On1 = 2'b01,
On2 = 2'b10,
On3 = 2'b11;
//...
always # (*)
begin
nextstate = 4'b0000;
case (1'b1)
currentstate[Off] : begin
x = 0;
if(b==0)
nextstate[Off] = 1'b1;
else
nextstate[On1] = 1'b1;
end
currentstate[On1] : begin
x = 1;
nextstate[On2] = 1'b1;
end
//...
A simple example is available at this link and explanation is over here. Cummings paper is also a good source for more info.
EDIT: As #Greg pointed out, it was a copy-paste error. A combinational block must use blocking assignments.

Hamming (7,4) Code - Finite State Machine

So I am working on a lab assignment for a Computer Engineering class. I have a assignment due and I am trying to get all the help I can, as for the professor I have to wait until a few days before I can speak with them for help. So I am seeing if I can get help her.
My issue is that my finite state machine is not working how it should be as asked from the lab assignment. The state machine is supposed to have 3 states; idle, s1, s2. Idle is supposed to show all zeros in the waveform, State 1 will show the randomly generated 4-bit number from the LFSR, and State 2 will show the result from the 4-bit number after hamming (7,4) is done. The clock is changed to a 1HZ clock, clk division used.
Code is as follows:
CLOCK_1HZ
module clock_1hz (clk, reset, clk2);
input clk, reset;
output clk2;
reg temp;
reg [25:0] cnt;
always #(posedge clk or posedge reset)
begin
if (reset)
begin
cnt = {25{1'b0}};
end
else
begin
if (cnt == 26'b10111110101111000001111111)
begin
cnt = {25{1'b0}};
temp = 1'b1;
end
else if (cnt < 26'b01011111010111100000111111)
begin
cnt = cnt + 1;
temp = 1'b1;
end
else
begin
cnt = cnt + 1;
temp = 1'b0;
end
end
end
assign clk2 = temp;
endmodule
LFSR
module lfsr (out, clk, rst);
output [4:1] out;
input clk, rst;
reg [4:1] w;
always #(posedge clk or posedge rst)
begin
if (rst)
begin
w = 4'b1011;
end
else
w = {w[3],w[2],w[1]^w[4], w[4]};
end
assign out=w;
endmodule
HAMMING
module hamming(din, dout);
output [6:0] dout;
input [3:0] din;
assign dout[6] = din[3];
assign dout[5] = din[2];
assign dout[4] = din[1];
assign dout[3] = din[1] ^ din[2] ^ din[3];
assign dout[2] = din[0];
assign dout[1] = din[0] ^ din[2] ^ din[3];
assign dout[0] = din[0] ^ din[1] ^ din[3];
endmodule
All this code works properly and computes the correct HAMMING and the clock division works well with the LFSR and works when it is combined as hierarchy design.
When I make the FSM for this code it works upto it computing the hamming number but does not change state when indicated.
When Switch 1 set: State IDLE
When Switch 2 set: State 1, Shows 4-bit LFSR number
When Switch 2 set: State 2, Shows 7-bit Hamming result
The following is my code for the Finite State Machine and following that is the waveform output.
module fsm ( clk , reset , sw1 , sw2 , sw3 , lights );
input clk, reset, sw1, sw2, sw3;
output reg [6:0] lights;
reg[2:0] state;
wire clkhz;
wire [3:0] lfsr_out;
wire [6:0] hout;
parameter S0 = 3'b000, S1 =3'b001, S2 = 3'b010; // states
clock_1hz u1(.clk(clk),
.reset(reset),
.clk2(clkhz));
lfsr u2(.rst(reset),
.clk(clkhz),
.out(lfsr_out));
hamming u3(.din(lfsr_out),
.dout(hout));
always #(posedge clk or posedge reset)
begin
if (reset == 1)
begin
state <= S0;
end
else
case(state)
S0: if(sw1 == 1)
begin
state <= S0;
end
S1: if(sw2 == 1)
begin
state <= S1;
end
S2: if(sw3 == 1)
begin
state <= S2;
end
default state <= S0;
endcase
end
always #(*)
begin
case(state)
S0: lights = 7'b0000000; //led are all off
S1: lights = lfsr_out; //4bit lfsr shown on led
S2: lights = hout; // display hamming code result
default lights = 7'b0000000; //led are all off
endcase
end
endmodule
WAVEFORM OF FINITE STATE MACHINE:
I don't think it is a state machine that you need here. From you description of the requirements, perhaps you just need to remember the current switch pressed? If that is the case, you could do something along the lines of:
always #(posedge clk or posedge reset)
if (reset == 1)
state <= S0;
else
if (sw1)
state <= S0;
else if (sw2)
state <= S1;
else if (sw3)
state <= S2;
Now state is remembering the current switch pressed. From your description of the requirements, doing this does not seem to depend on which switch which switch was pressed before that and so it doesn't look like you need a state machine - the behaviour does not depend on the state.
(You don't need all those begins and ends, either. You don't need them if there is only one statement in the branch.)

The states in this FSM machine are changing too quickly due to an issue with the clock updating the present state

I'm in the process of implementing a finite state machine in verilog, and I've encountered an issue. However, I know what the problem is, but I'm not sure how to fix it.
This is my current code:
module moore_SM(clk, rstn, btn, z, rstLED, state);
//Port Assignments
input clk, rstn;
input [2:0] btn;
output z;
output reg rstLED;
output reg [5:0] state;
//Internal Port Assignments
reg [1:0] w, x; //NOTE: This is typically the input in FSM,
//but it is internal because there is a conversion from btn to w.
reg [2:0] y, Y; //Present state and next state respectively
reg [2:0] pstBtn;
reg [31:0] cnt;
//Define some parameters
//Input Type (i.e. A, B or C)
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10; //DC => don't care - shouldn't affect FSM
//State (i.e. S1, S2, S3, S4, S5 or S6)
parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;
initial begin
state = 0;
end
//Determine which button is active
always #(*)
begin
case(btn)
3'b110: begin w = A; end
3'b101: begin w = B; end
3'b011: begin w = C; end
// default: w = DC;
endcase
end
//Define the next state and output combinational circuits
always #(w,y)
begin
case(y)
S1: begin
state = 6'b000001;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
S2: begin
state = 6'b000010;
if(w == B) begin Y = S3; end
else begin if(w == A) begin Y = S2; end
else Y = S1; end
end
S3: begin
state = 6'b000100;
if(w == A) begin Y = S2; end
else begin if(w == B) begin Y = S4; end
else Y = S1; end
end
S4: begin
state = 6'b001000;
if(w == A) begin Y = S5; end
else begin Y = S1; end
end
S5: begin
state = 6'b010000;
if(w == A) begin Y = S2; end
else begin if(w == B) begin Y = S3; end
else Y = S6; end
end
S6: begin
state = 6'b100000;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
//default: Y = 3'b111;
endcase
end
//assign z = (Y == S2);
//Define the sequential block
always #(posedge clk)
begin
y <= Y;
end
endmodule
This code is supposed to identify the pattern ABBAC. I believe the logic accomplishes this purpose.
However, I've encountered a problem. When I press one of the three buttons, the first always block - always #(*) - executes and evaluates the change. The state of the button is encoded and saved into w. At the same time, the next always block - always #(w,y) - senses a change and determines in which state to reside. Like I expected, if I send input A, the machine moves from S1 into S2.
Now if I send input B, the machine moves back into state S1. After I changed a few things around, I identified what I believe to be the problem. Note the last always block: always #(posedge clk). This always block continuously updates the present state, y. When I press a button, I assume what is happening is that the second always block, always #(w,y), is receiving an updated y at 50mHz (in my case), which is obviously much faster than I can press and release a button. Assuming I'm pressing the B button while in state S2, the state quickly changes to S3 to S4 and then to S1 because of the continuous update.
That said, I'm having some trouble coming up with a way to fix this issue. I basically need some way to change only one state per button press.
Note that I'm primarily testing this code on an experimental board. I did write a testbench, but the simulation does not seem to match what I'm seeing on the design board. In case anyone wants to see the testbench code, I posted it below:
`timescale 1ns/1ns
module moore_SM_TB();
reg clk;
reg [2:0] btn;
wire [5:0] state;
wire z;
wire rstLED;
initial begin
clk = 1;
#0 btn = 3'b111;
#50 btn = 3'b110;
#50 btn = 3'b111;
#50 btn = 3'b101;
#50 btn = 3'b111;
#50 btn = 3'b011;
#50 btn = 3'b111;
end
always begin
#20 clk = ~clk;
end
//MUT
moore_SM MUT (clk, 0, btn, z, rstLED, state);
endmodule
NOTE: I believe the solution will ultimately involve modifying how the buttons are handled. When I release a button, this also registers as a change. Hence, I had to comment out the default case because it would also mess up which state the machine is in.
UPDATE: I wrote a reduced version of the FSM I posted above to try and debug the code. It tries to detect the sequence AB.
module moore_SM(clk, btn, rstN, state, rstLED);
//Port assignments
input clk;
input rstN;
input [2:0] btn;
output reg rstLED;
output reg [5:0] state;
//Internal Port Assignments
reg [1:0] w;
reg [2:0] y, Y;
reg [2:0] pstBtn;
//Define some parameters
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10;
parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;
//Initialize some values to prevent Quartus from doing
initial
begin
y = S1;
Y = y;
state = 0;
rstLED = 0;
end
always #(*)
begin
if(btn == pstBtn) begin w = DC; end
else begin
case(btn)
3'b110: w = A;
3'b101: w = B;
3'b011: w = C;
default: w = DC;
endcase
end
end
always #(*)
begin
case(y)
S1: begin
state = 6'b000001;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
S2: begin
state = 6'b000010;
if(w == B) begin Y = S3; end
if(w == DC) begin Y = S2; end
else begin Y = S1; end
end
S3: begin
state = 6'b000100;
if(w == DC) begin Y = S3; end
else begin Y = S1; end
end
default: begin state = 6'b100000; Y = S1; end
endcase
end
//Update state and check for reset signal
always #(posedge clk, negedge rstN)
begin
pstBtn <= btn;
if(rstN == 0) begin y <= S1; rstLED <= 1; end
else begin y <= Y; rstLED <= 0; end
end
endmodule
Note that I'm trying to "sample" the button state in the last always block. I've used this method in the past, but it does not seem to work here. Whenever I press a button, there is no change in state. I'm wondering if this is a timing issue now.
If the button input is coming a switch rather than test stimulus it will be asynchronous and so should be put through 2 meta-stability flip-flops. To change one state per button press create an edge detection.
Edge detection will create a 1 clock period wide pulse, resulting in 1 transition per press.
reg [2:0] btn0_meta;
always #(posedge clk or negedge rstN) begin
if (~rstN) begin
btn0_meta <= 'b0;
end
else begin
btn0_meta <= {btn0_meta[1:0], btn[0]};
end
end
reg btn0_posedge;
always #* begin
btn0_posedge = btn0_meta[1] & ~btn_meta[2];
end
Do this for all button inputs and use the btnX_posedge in your state machine.

Resources