Hamming (7,4) Code - Finite State Machine - verilog

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.)

Related

RTL if statements not matching with simulation

I am struggling to understand why the output flickers between 0 and 1, when the output should constantly remain 0 since the reduction OR gate of 000 is 0 not 1.
When I tried a different bit width, the problem suddenly disappeared. However, I would like to know what is going on rather than relying on randomness for correctness.
project_test .sv
`timescale 1ns/1ns
module project_test
( input logic clk, rst,
input logic in,
output logic [2:0] c
);
logic [2:0] out;
always#(posedge clk or posedge rst) begin
if(rst)
out <= 'b0;
else if(in) begin
if(|out)
out <= 'b0;
end
else
out <= out + 1'b1;
end
assign c = out;
endmodule: project_test
testbench.sv
`timescale 1ns/1ns
module testbench;
logic clk, rst;
logic in;
logic [2:0] c;
project_test project_test(
.clk(clk),
.rst(rst),
.in(in),
.c(c)
);
initial begin
clk = 0;
rst = 1;
in = 0 ;
#30
rst = 0;
#20;
in = 1;
#500;
rst=1;
#100ns;
$stop();
end
always#(clk) begin
#10ns clk <= !clk;
end
endmodule
Simulation output:
RTL viewer:
That is an improper way to generate a clock signal in the testbench. You should not have the clk signal in the sensitivity list because it keeps re-triggerring the always block. Your clock generator potentially adds events to the Verilog event queue, which can cause odd behavior. In fact, when I ran your code on the Cadence simulator, I did not see the clock toggling at all.
This is a more standard way to generate a clock:
always begin
#10ns clk = !clk;
end
You are using a very verbose implementation. Why can't you do something like below.
always#(posedge clk or posedge rst)
begin
if(rst)
out <= 'd0;
else
out <= (in) ? 'd0 : (out + 1'b1);
end

A simple clock divider module

I am asked to design simple clock divider circuit for different types of inputs.
I have a enabler [1:0] input and an input clock, and an output named clk_enable.
If enabler=01 then my input clock should be enabled once in 2 clock signals.If enabler=10 then my input should be divided by 4 etc.
I managed to divide my input clock for different cases with using case keyword but for enabler=00 my input clock should be equal to my output clk_enable which i could not manage to do it.
Here is what i tried. I am asking a help for the enabler=00 situation.
module project(input [1:0] enabler,
input clock,
output reg clk_enable);
reg [3:0] count,c;
initial begin
count=4'b0000;
c=4'b0000;
end
always #( posedge clock)
case(enabler)
2'b00:clk_enable<=clock;
2'b01:clk_enable<=~clk_enable;
2'b10:begin
if (count >= 4'b0100-1)
count<=4'b0000;
else begin
count<=count + 4'b0001;
clk_enable<=(count<(4'b0100 / 2));
end
end
2'b11: begin
if (count >= 4'b1000-1)
count<=4'b0000;
else begin
count<=count + 4'b0001;
clk_enable<=(count<(4'b1000 / 2));
end
end
endcase
endmodule
This will generate gated pulsed clock with posedge rate matching the div_ratio input.
div_ratio output
0 div1 clock (clk as it is)
1 div2 (pulse every 2 pulses of clk)
2 div3
3 div4
This is usually preferable when sampling at negedge of divided clock is not needed
If you need 50% duty cycle I can give you another snippet
module clk_div_gated (
input [1:0] div_ratio,
input clk,
input rst_n, // async reset - a must for clock divider
output clk_div
);
reg [1:0] cnt;
reg clk_en;
always #(posedge clk or negedge rst_n)
if (~rst_n)
cnt <= 2'h0;
else
cnt <= (cnt == div_ratio)? 2'h0 : cnt + 1'b1;
// clk_en toggled at negedge to prevent glitches on output clock
// This is ok for FPGA, synthesizeable ASIC design must use latch + AND method
always #(negedge clk)
clk_en <= (cnt == div_ratio);
assign clk_div <= clk & clk_en;
endmodule
This looks like you have a strong background in software development? :)
My suggestion is that you always make a clean cut between combinational and sequential logic. This includes some thoughts on what part of the design actually has to be sequential and what can be combinational.
For your case, the clock division clearly has to be sequential, since you want to invert the generated CLK signal (frequency f/2, case 0'b01) at each positive edge of the incoming CLK signal (frequency f, case 0'b00). Same is valid for f/4 (case 0'b10).
This part needs to be sequential, since you want to invert the previous CLK state...this would cause a cmobinational loop if realized in combinational logic. So triggering on a CLK edge is really necessary here.
However, the actual selection of the correct CLK output signal can be combinational. You just want to assign the correct CLK signal to the output CLK.
An implementation of the sequential part could look like:
// frequency division from input CLK --> frequency: f/2
always #(posedge clk or negedge rst_neg) begin
if (rst_neg = 1'b0) begin
clk_2 <= 1'b0;
end else begin
clk_2 <= ~clk_2;
end
end
// frequency division from first divided CLK --> frequency: f/4
always #(posedge clk_2 or negedge rst_neg) begin
if (rst_neg = 1'b0) begin
clk_ 4 <= 1'b0;
end else begin
clk_4 <= ~clk_4;
end
end
// frequency division from first divided CLK --> frequency: f/8
always #(posedge clk_4 or negedge rst_neg) begin
if (rst_neg = 1'b0) begin
clk_ 8 <= 1'b0;
end else begin
clk_8 <= ~clk_8;
end
end
So this plain sequential logic takes care of generating the divided CLK signals of f/2 and f/4 that you need. I also included reset signals on negative edge, which you usually need. And you spare the counter logic (increments and comparison).
Now we take care of the correct selection with plain combinational logic:
always #(*) begin
case(enabler)
2'b00: clk_enable = clk;
2'b01: clk_enable = clk_2;
2'b10: clk_enable = clk_4;
2'b11: clk_enable = clk_8;
endcase
end
This is quite close to your hardware description (clk_enable needs to be a reg here).
However, another way for the combinational part would be the following (declare clk_enable as wire):
assign clk_enable = (enabler == 2'b00) ? clk
: (enabler == 2'b01) ? clk_2
: (enabler == 2'b10) ? clk_4
: (enabler == 2'b11) ? clk_8;

Verilog code 2 errors i can't find: Would be grateful for an extra pair of eyes to spot a mistake i might've overlooked

I'm writing a verilog code where i'm reading two files and saving those numbers into registers. I'm then multiplying them and adding them. Pretty much a Multiplication Accumulator. However i'm having a hard frustrating time with the code that i have. It read the numbers from the files correctly and it multiples but here is the problem? When i first run it using ModelSim, I reset everything so i can clear out the accumulator. I then begin the program, but there is always this huge delay in my "macc_out" and i cannot seem to figure out why. This delay should not be there and instead it should be getting the result out A*B+MAC. Even after the delay, it's not getting the correct output. My second problem is that if i go from reset high, to low (start the program) and then back to reset high ( to reset all my values), they do not reset! This is frustrating since i've been working on this for a week and don't know/can't see a bug. Im asking for an extra set of eyes to see if you can spot my mistake. Attached is my code with the instantiations and also my ModelSim functional Wave Form. Any help is appreciated!
module FSM(clk,start,reset,done,clock_count);
input clk, start, reset;
output reg done;
output reg[10:0] clock_count;
reg [0:0] macc_clear;
reg[5:0] Aread, Bread, Cin;
wire signed [7:0] a, b;
wire signed [18:0] macc_out;
reg [3:0] i,j,m;
reg add;
reg [0:0] go;
reg[17:0] c;
parameter n = 8;
reg[1:0] state;
reg [1:0] S0 = 2'b00;
reg [1:0] S1 = 2'b01;
reg [1:0] S2 = 2'b10;
reg [1:0] S3 = 2'b11;
ram_A Aout(.clk(clk), .addr(Aread), .q(a));
ram_B Bout(.clk(clk), .addr(Bread), .q(b));
mac macout(.clk(clk), .macc_clear(macc_clear), .A(a), .B(b), .macc_out(macc_out), .add(add));
ram_C C_in(.clk(clk), .addr(Cin), .q(c));
always #(posedge clk) begin
if (reset == 1) begin
i <= 0;
add<=0;
j <= 0;
m <= 0;
clock_count <= 0;
go <= 0;
macc_clear<=1;
end
else
state<=S0;
case(state)
S0: begin
// if (reset) begin
// i <= 0;
// add<=0;
// j <= 0;
// m <= 0;
// clock_count <= 0;
// go <= 0;
// macc_clear<=1;
// state <= S0;
// end
macc_clear<=1;
done<=0;
state <= S1;
end
S1: begin
add<=1;
macc_clear<=0;
clock_count<=clock_count+1;
m<=m+1;
Aread <= 8*m + i;
Bread <= 8*j + m;
if (m==7) begin
state <= S2;
macc_clear<=1;
add<=0;
end
else
state <=S1;
end
S2: begin
add<=1;
macc_clear<=0;
m<=0;
i<=i+1;
if (i<7)
state<=S1;
else if (i==8) begin
state<=S3;
add<=0;
end
end
S3: begin
add<=1;
i<=0;
j<=j+1;
if(j<7)
state<=S1;
else begin
state<=S0;
done<=1;
add<=0;
end
end
endcase
end
always # (posedge macc_clear) begin
Cin <= 8*j + i;
c <= macc_out;
end
endmodule
module mac(clk, macc_clear, A, B, macc_out, add);
input clk, macc_clear;
input signed [7:0] A, B;
input add;
output reg signed [18:0] macc_out;
reg signed [18:0] MAC;
always #( posedge clk) begin
if (macc_clear) begin
macc_out <= MAC;
MAC<=0;
end
else if (add) begin
MAC<=(A*B)+ MAC;
macc_out<=MAC;
end
end
endmodule
module ram_A( clk, addr,q);
output reg[7:0] q;
input [5:0] addr;
input clk;
reg [7:0] mem [0:63];
initial begin
$readmemb("ram_a_init.txt", mem);
end
always #(posedge clk) begin
q <= mem[addr];
end
endmodule
module ram_C(clk,addr, q);
input [18:0] q;
input [5:0] addr;
input clk;
reg [18:0] mem [0:63];
always #(posedge clk) begin
mem[addr] <= q;
end
endmodule
ModelSim Functional Simulation Wave Form
1) Take a look at the schematic view for your MACC module - I think some of your "problems" will be obvious from that;
2) Consider using an always#(*) (Combinational) block for your FSM control signals (stuff like add or macc_clear) rather than a always#(posedge clk) (sequential) - it makes the logic to assert them easier. Right now they're registered, so you have a cycle delay. ;
3) In your MAC, you clear the MAC register on a reset, but you don't clear the macc_out register.
In short, I think you need to step back, and consider which signals are combinational logic, and which ones are sequential and need to be in registers.

How to create synthesizeable delay?

i got a code like below with clk = #10 ~clk
always# (posedge clk)begin
for (g=0;g<8;g=g+1) begin
ws = 1;
#20
ws = 0;
#20;
end
so is there any other way to make the delay 20 synthesizaeble in the coding above?
A flip-flop is the only way of synthesising a delay:
always #(posedge clk)
q <= d;
With clk = #10 ~clk;, q will be #10 later than d.
The question appear not to be how to synthesis a #20 but how to control the timing for signals in to a RAM. Digital design are based around clock edges, with each positive or negative edge a set distance a part, this is the period of the clock or 1/frequency.
To sequence events as you describe you need a FSM (Finite state machine) to control or sequence it. I have included a small example below:
Available on EDA Playground
module tb;
//Tb component
reg clk;
reg rst_n;
initial begin :clk_and_reset
clk = 0;
rst_n = 0;
#40 rst_n = 1;
#40;
forever begin
#20 clk = ~clk;
end
end
//Design
reg [1:0] state;
reg [1:0] next_state;
reg [31:0] counter;
reg ws;
localparam S_IDLE = 'd0;
localparam S_WAIT = 'd1;
localparam S_OFF = 'd2;
always #(posedge clk, negedge rst_n) begin
if (~rst_n) begin
state <= S_IDLE;
end
else begin
case(state)
S_IDLE : begin
state <= S_WAIT;
counter <= 'b0;
S_WAIT :
if (counter < 32'd10) begin
state <= S_WAIT; //Wait for 10 clock cycles
counter <= counter + 1;
end
else begin
state <= S_OFF;
counter <= 'b0;
end
S_OFF : state <= S_IDLE;
default : state <= S_IDLE; //IDLE
end
end
//Output decode based on state
always #* begin
//ws goes high when in Wait state
ws = (state == S_WAIT);
end
//Test program
initial begin
repeat (10) begin
#(posedge clk);
$display("%4t : State %b: ws :%b", $realtime, state, ws);
end
$finish();
end
endmodule
This could be expanded by staying in idle until triggered then by having counter and staying in wait for x number of clocks, x number of clocks in OFF before going back to idle and waiting to be triggered again.
Update
I have updated the code example to stay in the WAIT state for 10 clock cycles to demonstrate how to control the delay between transitions.

Verilog HDL, User Input from an FPGA

I am currently working on a project in Verilog HDL with an FPGA obtained from my school (I am running Quartus II vers. 10.1 and 11.0 (I've tried both)). I am getting a very bizarre bug that I cannot figure out for the life of me.
I am developing a Morse Code program which detects dots and dashes, and then outputs the appropriate letter on a HEX display based upon this input. The HEX display works beautifully, but my UserInput module doesn't seem to do anything at all!
module UserInput(Clock, reset, in, out);
input Clock, reset, in;
output reg [1:0] out;
wire [2:0] PS;
reg [2:0] NS;
parameter NONE = 2'b00, DOT = 2'b01, DASH = 2'b11; //For Output
parameter UP = 3'b000, SHORT0 = 3'b001, SHORT1 = 3'b010, UP_DOT = 3'b011, LONG = 3'b100, UP_DASH = 3'b101;
//Active High
always#(PS or in)
case (PS)
UP: if (in) NS = SHORT0;
else NS = UP;
SHORT0: if (in) NS = SHORT1;
else NS = UP_DOT;
SHORT1: if (in) NS = LONG;
else NS = UP_DOT;
UP_DOT: NS = UP;
LONG: if (in) NS = LONG;
else NS = UP_DASH;
UP_DASH: NS = UP;
default: NS = 3'bxxx;
endcase
always#(PS)
case (PS)
UP: out = NONE;
SHORT0: out = NONE;
SHORT1: out = NONE;
UP_DOT: out = DOT;
LONG: out = NONE;
UP_DASH: out = DASH;
default: out = 2'bxx;
endcase
D_FF dff0 (PS[0], NS[0], reset, Clock);
D_FF dff1 (PS[1], NS[1], reset, Clock);
D_FF dff2 (PS[2], NS[2], reset, Clock);
endmodule
module D_FF (q, d, reset, clk);
input d, reset, clk;
output reg q;
always#(posedge clk or posedge reset)
begin
if (reset) q = 0;
else q = d;
end
endmodule
The input for the module is a KEY on the FPGA. The FSM represented by the UserInput module has the key be in the "UP" state at t=0. Then, if there is input, it will move through SHORT0 or SHORT1, and finally LONG. If it the key is released at any of these states, they go to their appropriate intermediary UP states and provide an output of "DOT" or "DASH".
However, when I connect this to my FPGA, I get nothing. From my testing, it seems that it never moves away from the "UP" state. Even my simulations give me nothing. Secondly, I've tried connecting a different UserInput module from a different project (one I know works), and still nothing. Is there something going on in the background of Verilog I am missing?
Here is an image of the simulation waveform:
DFf 0, 1, and 2 are the bits 0, 1, and 2 of PS. My simulation won't allow a showing of the NS.
Your code looks bad to me (which I guess you want to hear as your code doesn't work). It looks like a combination of timing problems and a design flaw.
Let's walk through your waveform view and see if we can't work out what's going on.
signal in goes high, which triggers an always block. PS is 0 so we set NS to 1. This is not in time for the rising clock edge so it's not triggered in the DFF (as you'd have suspected), never mind it'll be caught on the next clock edge.
signal in goes low, which triggers an always block, PS is 0 so we set NS to 0. This happens in time for the rising clock edge and is captured in the DFF (argh we missed the NS signal going to 1 as we wanted).
Also, someone mentioned that there's an error with your flip-flop being asserted while reset is asserted. This isn't a problem: the reset is synchronous. So on the next rising clock edge the DFF is reset to 0.
So, what's the solution (looks like homework to me, so hopefully you've fixed this already!):
It should look something like this (I haven't simulated it, so no guarantees):
Module UserInput (clk, reset, in, out);
input clk, reset, in;
output [1:0] out;
// output parameters
parameter IDLE = 2'b00;
parameter DOT = 2'b01;
parameter DASH = 2'b10;
// FSM states
parameter LOW = 3'b000;
parameter SHORT1 = 3'b001;
parameter SHORT2 = 3'b010;
parameter LONG = 3'b100;
reg [2:0] state;
wire [1:0] next_out;
wire [2:0] next_state;
always #(posedge clk)
begin
if (reset)
begin
out <= IDLE;
state <= LOW;
end;
else
begin
out <= next_out;
state <= next_state;
end
end if;
end
always #(*)
begin
case (state)
LOW:
next_out = IDLE;
next_state = (in? SHORT1 : LOW);
SHORT1:
begin
next_state = (in? SHORT2: LOW);
next_out = (in? IDLE : DOT);
end;
SHORT2:
next_state = (in? LONG: LOW);
next_out = (in? IDLE : DOT);
LONG:
next_state = (in? LONG : LOW);
next_out = (in? IDLE : DASH);
default:
// we shouldn't get here!!
next_state = LOW;
next_out = IDLE;
end;
end module;
So what's going on here:
I think this should be fairly obvious. When the in signal moves from high to low then we want to output the current state (LONG as a DASH, SHORT1 and SHORT2 as a DOT), otherwise we output IDLE. If the in signal is high then we want to move the state along depending on how long it's been high for.
There's an error with this code which won't effect simulation, but which will almost certainly effect you on the FPGA: if you are getting input from an external source then you'll need to buffer it through a (series?) of flip-flops to prevent metastability problems. This can be fixed by adding a series of D flip-flops to capture the in signal and then passing this "cleaned" buffered_in to the UserInput.
ie:
module in_buffer (clk, reset, in, out);
input clk, reset, in;
output out;
reg buf1, buf2;
always # (posedge clk)
begin
if (reset)
begin
out <= 0;
buf1 <= 0;
buf2 <= 0;
end
else
out <= buf2;
buf2 <= buf1;
buf1 <= in;
end
end

Resources