J
Jonathan Nicolas
Guest
Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...
Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays. Within the CPU
module, I assign those to different values to display debugging
information.
The CPU core is basically a simple state machine, looking something
like this:
reg [1:0] state_reg, state_next;
reg[15:0] r0_reg, r0_next; // And the same for all other registers
always @(posedge clk)
begin
state_reg <= state_next;
r0_reg <= r0_next;
// ... same for all others
end
always @*
begin
// Default values
state_next = state_reg;
r0_next = r0_reg;
// ...
// FSM code
case(state_reg)
2'b00: begin [[code for state 0 ]] state_next =
2'b01; end
2'b01: begin [[code for state 1 ]] state_next =
2'b10; end
2'b10: begin [[code for state 2 ]] state_next =
2'b11; end
2'b11: begin [[code for state 3 ]] state_next =
2'b00; end
endcase
end
The CPU always go through these 4 states for each instruction. [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.
Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:
assign dbg1 = {5'b0 , state_reg};
'dbg1' is defined as "output wire [7:0] dbg1" in the module header
This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)
Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;
Now, if I do that, everything stops working. The CPU doesn't cycle
through its states anymore.
I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register). When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00". Nothing at all is happening in the state machine.
I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc.. If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.
I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine. But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.
I even tried using this line instead :
assign dbg1 = {4'b0,
(state_reg==2'b00) ? 4'b0001 :
(state_reg==2'b01) ? 4'b0010 :
(state_reg==2'b10) ? 4'b0100 : 4'b1000 };
My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.
Please help me out !!
Jonathan
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...
Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays. Within the CPU
module, I assign those to different values to display debugging
information.
The CPU core is basically a simple state machine, looking something
like this:
reg [1:0] state_reg, state_next;
reg[15:0] r0_reg, r0_next; // And the same for all other registers
always @(posedge clk)
begin
state_reg <= state_next;
r0_reg <= r0_next;
// ... same for all others
end
always @*
begin
// Default values
state_next = state_reg;
r0_next = r0_reg;
// ...
// FSM code
case(state_reg)
2'b00: begin [[code for state 0 ]] state_next =
2'b01; end
2'b01: begin [[code for state 1 ]] state_next =
2'b10; end
2'b10: begin [[code for state 2 ]] state_next =
2'b11; end
2'b11: begin [[code for state 3 ]] state_next =
2'b00; end
endcase
end
The CPU always go through these 4 states for each instruction. [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.
Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:
assign dbg1 = {5'b0 , state_reg};
'dbg1' is defined as "output wire [7:0] dbg1" in the module header
This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)
Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;
Now, if I do that, everything stops working. The CPU doesn't cycle
through its states anymore.
I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register). When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00". Nothing at all is happening in the state machine.
I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc.. If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.
I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine. But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.
I even tried using this line instead :
assign dbg1 = {4'b0,
(state_reg==2'b00) ? 4'b0001 :
(state_reg==2'b01) ? 4'b0010 :
(state_reg==2'b10) ? 4'b0100 : 4'b1000 };
My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.
Please help me out !!
Jonathan