Leep
Junior Member level 3
I've written a FSM to take a 14-bit binary number (decimal 0-9999) and convert it to 16-bit BCD using the following algorithm:
1. Shift the binary number left one bit.
2. If 14 shifts have taken place, stop.
3. If the binary value in any of the BCD columns (units, tens, hundreds, thousands) is 5 or greater, add 3 to that value in that BCD column.
4. Go to 1.
I have 3 states (RESET, SHIFT, IDLE) and a 0-13 counter. Setting reset high puts the FSM into RESET mode which initializes things and puts it in SHIFT mode where it stays in state SHIFT for 14 cycles (controlled by the counter) and performs the algorithm each time, then enters IDLE mode.
The problem I'm having is that it seems like it's incrementing the counter and changing the output fields (thousands, hundreds, tens, and units) one more time after entering IDLE. I'm sure this isn't literally the case, but I'm at a loss for what's going on.
I'm outputing the tens and units values to the right two seven-segment displays and for debug I'm outputting the current state and the counter to the left two seven-segment displays. Here's the sequence I get after hitting reset (I slowed the FSM clock WAY down to about 2Hz, to see the display changing):
The last values (state == 1, counter == 14, tens = 3, units = 3) stay until reset is hit again.
When I run this in the simulator (with the full speed clock, I just changed clk_slow in the two always blocks to clk) I get:
(sorry for the small image, I couldn't figure out how to get it bigger in-line... click it to see full size)
which seems to be the correct results (thousands, hundreds, tens and units are all 9), not what I get when I synthesize it and run it on the Nexys 3.
Here's my code:
What am I doing wrong? Am I approaching the FSM wrong? Am I thinking too much like "programming" and not "describing hardware"? I'm still very new to all this, so any advice at all will be welcomed!
-----
Leep
1. Shift the binary number left one bit.
2. If 14 shifts have taken place, stop.
3. If the binary value in any of the BCD columns (units, tens, hundreds, thousands) is 5 or greater, add 3 to that value in that BCD column.
4. Go to 1.
I have 3 states (RESET, SHIFT, IDLE) and a 0-13 counter. Setting reset high puts the FSM into RESET mode which initializes things and puts it in SHIFT mode where it stays in state SHIFT for 14 cycles (controlled by the counter) and performs the algorithm each time, then enters IDLE mode.
The problem I'm having is that it seems like it's incrementing the counter and changing the output fields (thousands, hundreds, tens, and units) one more time after entering IDLE. I'm sure this isn't literally the case, but I'm at a loss for what's going on.
I'm outputing the tens and units values to the right two seven-segment displays and for debug I'm outputting the current state and the counter to the left two seven-segment displays. Here's the sequence I get after hitting reset (I slowed the FSM clock WAY down to about 2Hz, to see the display changing):
Code:
0000 <-- state == 0, counter == 0
2000 <-- state == 2, counter == 0
2101 <-- state == 2, counter == 1
2202 <-- state == 2, counter == 2
2304 <-- state == 2, counter == 3
240c <-- state == 2, counter == 4
251c <-- state == 2, counter == 5
263c <-- state == 2, counter == 6
27ab <-- state == 2, counter == 7
2889 <-- state == 2, counter == 8
2912 <-- state == 2, counter == 9
2a24 <-- state == 2, counter == 10
2b4c <-- state == 2, counter == 11
2ccc <-- state == 2, counter == 12
2d99 <-- state == 2, counter == 13, tens and units both have 9, which is correct at this point.
1e33 <-- state == 1, counter == 14 (????), tens and units have changed (????)
The last values (state == 1, counter == 14, tens = 3, units = 3) stay until reset is hit again.
When I run this in the simulator (with the full speed clock, I just changed clk_slow in the two always blocks to clk) I get:
(sorry for the small image, I couldn't figure out how to get it bigger in-line... click it to see full size)
which seems to be the correct results (thousands, hundreds, tens and units are all 9), not what I get when I synthesize it and run it on the Nexys 3.
Here's my code:
Code:
module seven_seg_test
(
input wire clk,
input wire reset,
output wire [3:0] an, // enable, 1-out-of-4 asserted low
output wire [7:0] sseg // led segments
);
parameter STATE_SIZE = 2;
parameter RESET = 2'b00, IDLE = 2'b01, SHIFT = 2'b10;
parameter CLOCK_SIZE = 26;
reg [STATE_SIZE-1:0] state, next_state;
reg [13:0] decimal;
reg [3:0] thousands, hundreds, tens, units;
reg [3:0] bits_to_go;
reg [CLOCK_SIZE-1:0] counter;
wire [7:0] led3, led2, led1, led0;
wire clk_slow;
hex_to_sseg sseg_unit_0
(
.hex(units),
.dp(1'b1),
.sseg(led0)
);
hex_to_sseg sseg_unit_1
(
.hex(tens),
.dp(1'b1),
.sseg(led1)
);
hex_to_sseg sseg_unit_2
(
.hex(bits_to_go),
.dp(1'b1),
.sseg(led2)
);
hex_to_sseg sseg_unit_3
(
.hex({2'b0, state}),
.dp(1'b1),
.sseg(led3)
);
disp_mux disp_unit
(
.clk(clk),
.reset(1'b0),
.in0(led0),
.in1(led1),
.in2(led2),
.in3(led3),
.an(an),
.sseg(sseg)
);
assign clk_slow = counter[CLOCK_SIZE-1];
always @(posedge clk)
begin
counter <= counter + 1'b1;
end
always @(posedge clk_slow, posedge reset)
begin
if(reset)
begin
state = RESET;
end else begin
state = next_state;
end
end
always @(posedge clk_slow)
begin
case (state)
RESET:
begin
{thousands, hundreds, tens, units} = 16'b0;
decimal = 14'd9999;
bits_to_go = 1'b0;
next_state = SHIFT;
end
SHIFT:
begin
{thousands, hundreds, tens, units, decimal} = {thousands[2:0], hundreds, tens, units, decimal, 1'b0};
bits_to_go = bits_to_go + 1'b1;
if(bits_to_go != 4'd13 && units >= 5) units = units + 2'd3;
if(bits_to_go != 4'd13 && tens >= 5) tens = tens + 2'd3;
if(bits_to_go != 4'd13 && hundreds >= 5) hundreds = hundreds + 2'd3;
if(bits_to_go != 4'd13 && thousands >= 5) thousands = thousands + 2'd3;
if(bits_to_go == 4'd13)
begin
next_state = IDLE;
end
end
default:
begin
end
endcase
end
endmodule
What am I doing wrong? Am I approaching the FSM wrong? Am I thinking too much like "programming" and not "describing hardware"? I'm still very new to all this, so any advice at all will be welcomed!
-----
Leep