Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20641 Discussions

FPGA Development Board - strange shift operation behavior

Altera_Forum
Honored Contributor II
2,018 Views

My development board based on: 

Cyclone IV EP4CE10E22C8N 

 

Quartus: 17.0.0 Lite Edition 

 

top-level entity code: 

module led4_reg(clk, led); parameter BASE_LED_SEQUENCE = 12'b000011101101; input clk; output led; reg led; reg circle_count; initial begin led = 0; count = 0; circle_count = 0; led <= ~led; $monitor($time, " led = %b count = %d", led, circle_count); end reg count; always @(posedge clk) begin count <= count + 1; if (count == 1) begin count <= 0; circle_count <= circle_count + 1; end if (circle_count == 12) circle_count <= 0; end always @(circle_count) begin case (circle_count) 0: led <= BASE_LED_SEQUENCE; 1,2,3,4: led <= (led << 1); // 1: led <= 12'b000111011010; // 2: led <= 12'b001110110100; // 3: led <= 12'b011101101000; // 4: led <= 12'b111011010000; 5: led <= 12'b110110100001; 6: led <= 12'b101101000011; 7: led <= 12'b011010000111; 8: led <= 12'b110100001110; 9: led <= 12'b101000011101; 10: led <= 12'b010000111011; 11: led <= 12'b100001110110; default: led <= 12'b000_111_111_111; endcase end endmodule  

 

My test file: 

`include "led4_reg.v" module main(); reg clk; wire leds; led4_reg reglight(clk, leds); initial begin clk = 0; forever# 1 clk = ~clk; end initial# 160_000_000 $finish; endmodule  

 

And test results: 

0 led = 000011101101 count = 0 16777217 led = 000111011010 count = 1 33554435 led = 001110110100 count = 2 50331653 led = 011101101000 count = 3 67108871 led = 111011010000 count = 4 83886089 led = 110110100001 count = 5 100663307 led = 101101000011 count = 6 117440525 led = 011010000111 count = 7 134217743 led = 110100001110 count = 8 150994961 led = 101000011101 count = 9  

 

But on the Dev Board LED for count item 1,2,3,4 always: 12'b000_000_000_000

I don't understand why. 

 

Additionally for some reason '0' - turn on light for LED. '1' - turn off for LED. Is it normal? 

 

Any idea? )) 

Thanks!
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
713 Views

Hi, 

 

Is your board an Altera/terasic dev board or a custom one based on Cyclone IV ? If its the Altera/terasic one, then most likely the LEDs are all active low , meaning, a writing a '0' will turn ON the LED and '1' will turn OFF the LED.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Hi, 

 

Is your board an Altera/terasic dev board or a custom one based on Cyclone IV ? If its the Altera/terasic one, then most likely the LEDs are all active low , meaning, a writing a '0' will turn ON the LED and '1' will turn OFF the LED. 

--- Quote End ---  

 

 

Looks like custome Dev Board ZEOWAA A-C4E6E10. 

Main problem in the part: 

led <= (led << 1);  

 

if I use explicit form like: 

led <= (12'b000111011010 << 1);  

it work pretty well on Dev Board.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

Hi, 

 

There are a few issues in the code.  

 

1. You cannot use initial blocks and $display tasks in RTL code for synthesis as these constructs are non-synthesizable . These are used only for simulation 

2. The code does not have a reset value or initial value. Use an asynchronous reset input and in the always block check for its negedge. When reset is asserted, initialize the count and output to '0'. 

3. The reason why led is always 0, is due to the fact that for the first case item (case 0) it will get the value from the parameter. For the next case items (case 1,2,3,4).. You are left shifting the value in the register which is always at 0. This is due to the fact that, after the case is hit, its value will get updated outside the always block. So the next time the code comes back to the case and hits the next one, the value of the led variable is 0. The previous value of led variable is not stored.  

 

You can accomplish this by modifying the default condition..  

default : led <= led;  

 

Although this will infer a latch that will store the last value of the register led.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Hi, 

There are a few issues in the code.  

 

--- Quote End ---  

 

 

Thank you for the response! 

Point 1,2 - thank you very much for remarks! 

 

3. I really can't understand why: 

1: led <= led; // will get previous value  

 

but 

1: led <= (led << 1); // can't get previous value  

 

Additionally, the default block never invoked. 

 

Am I understand correctly that I should implement simple latch for storing previous value?
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

You should ideally, store the previous value or initial value of the led in a register/flop. Then have it shifted out in the case. The default case may not work, but worth a try. You will understand what I mentioned if you look at how an always block will be executed.  

 

What you need to do is to latch in or register in the default value of the led (parameter) then use this value to shift left and get your corresponding outputs. For this to happen, the value of led register should be latched or stored, then used again in the case to update for the next case item.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

Try this code out. I just modified it to add the reset and logic to store initial value. 

module LED4(clk, reset, led); parameter BASE_LED_SEQUENCE = 12'b000011101101; input clk; input reset; output led; reg led; reg circle_count; //initial begin // led = 0; // count = 0; // circle_count = 0; // led <= ~led; // $monitor($time, " led = %b count = %d", led, circle_count); //end reg count; always @(posedge clk or negedge reset) begin if (!reset) begin count <= 28'd0; circle_count <= 4'd0; end else begin count <= count + 1; count <= 0; circle_count <= circle_count + 1; if (circle_count == 12) circle_count <= 0; end end always @(circle_count) begin led <= BASE_LED_SEQUENCE; case (circle_count) 0: led <= BASE_LED_SEQUENCE; 1,2,3,4: led <= (led << 1); // 1: led <= 12'b000111011010; // 2: led <= 12'b001110110100; // 3: led <= 12'b011101101000; // 4: led <= 12'b111011010000; 5: led <= 12'b110110100001; 6: led <= 12'b101101000011; 7: led <= 12'b011010000111; 8: led <= 12'b110100001110; 9: led <= 12'b101000011101; 10: led <= 12'b010000111011; 11: led <= 12'b100001110110; default: led <= 12'b000_111_111_111; endcase end endmodule
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Try this code out. I just modified it to add the reset and logic to store initial value. 

1,2,3,4: led <= (led << 1);  

--- Quote End ---  

 

 

Same result: 1,2,3,4 = 0; 

With D-latch same result: 

module led4_reg( input clk, input rst, output reg led ); parameter BASE_LED_SEQUENCE = 12'b000011101101; reg led_value; reg circle_count; reg count; always @(posedge clk or negedge rst) begin if (!rst) begin count <= 0; circle_count <= 0; end else begin count <= count + 1'b1; if (count == 1) begin count <= 1'b0; circle_count <= circle_count + 1'b1; end if (circle_count == 12) circle_count <= 0; end end always @(led) begin led_value <= led; end always @(circle_count or led_value) begin case (circle_count) 0: led <= BASE_LED_SEQUENCE; 1,2,3,4: led <= (led_value << 1); 5: led <= 12'b110110100001; 6: led <= 12'b101101000011; 7: led <= 12'b011010000111; 8: led <= 12'b110100001110; 9: led <= 12'b101000011101; 10: led <= 12'b010000111011; 11: led <= 12'b100001110110; default: led <= 12'b000_000_000_000; endcase end endmodule  

 

if I use: 

1,2,3,4: led <= led_value;  

it will get previous data.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Try this code out. I just modified it to add the reset and logic to store initial value. 

 

--- Quote End ---  

 

 

Same result.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

Try this one and check, it runs in my simulations.. 

module led4_reg(clk, reset, led); parameter BASE_LED_SEQUENCE = 12'b000011101101; input clk; input reset; output led; reg led; reg circle_count; //wire led_tmp; //initial begin // led = 0; // count = 0; // circle_count = 0; // led <= ~led; // $monitor($time, " led = %b count = %d", led, circle_count); //end reg count; always @(posedge clk or negedge reset) begin if (!reset) begin count <= 28'd0; circle_count <= 4'd0; end else begin count <= count + 28'd1; circle_count <= circle_count + 4'd1; if (circle_count == 4'd12) circle_count <= 4'd0; end end always@(circle_count or led) begin if (circle_count == 4'd0) begin led = BASE_LED_SEQUENCE; end else begin led = led << 1; end end endmodule
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

reg led; reg circle_count; ... always@(circle_count or led) begin if (circle_count == 4'd0) begin led = BASE_LED_SEQUENCE; end else begin led = led << 1; end end  

 

This is very inefficient logic for variables defined as registers. You have built a change detector on circle_count[3:0] that will trigger an asynchronous clocking of the led[11:0] registers when it triggers. 

 

Why not just add the statement: 

 

led <= circle_count == 4'd0 ? BASE_LED_SEQUENCE : led << 1; 

 

into the main loop, so it looks like this: 

 

always @(posedge clk or negedge reset) begin if (!reset) begin count <= 28'd0; circle_count <= 4'd0; led <= 12'b0; end else begin if (count == 1'b1) begin count <= 28'd0; circle_count <= circle_count == 4'd12 ? 4'd0 : circle_count + 4'd1; led <= circle_count == 4'd0 ? BASE_LED_SEQUENCE : led << 1; end else count <= count + 28'd1; end end  

 

which I think is a lot easier to follow.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

Thanks for pointing it out .. I agree with ak6dn. My bad. His code should work. Try it out.

0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

 

Why not just add the statement: 

 

led <= circle_count == 4'd0 ? BASE_LED_SEQUENCE : led << 1; 

 

into the main loop, so it looks like this: 

 

always @(posedge clk or negedge reset) begin if (!reset) begin count <= 28'd0; circle_count <= 4'd0; led <= 12'b0; end else begin if (count == 1) begin count <= 1'b0; circle_count <= circle_count == 4'd12 ? 4'd0 : circle_count + 4'd1; led <= circle_count == 4'd0 ? BASE_LED_SEQUENCE : led << 1; end else count <= count + 28'd1; end end  

 

which I think is a lot easier to follow. 

--- Quote End ---  

 

 

Thank you, 

It's pretty well working. 

But could you explain me why I can't get previous value for `led` in other always blocks?
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Thank you, 

It's pretty well working. 

But could you explain me why I can't get previous value for `led` in other always blocks? 

--- Quote End ---  

 

 

Not sure what you mean by this. led[11:0] is a register, so you can access it at any time in any logic equation within that module. The value will only change when the always block that encloses it is triggered and the value is updated.
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Not sure what you mean by this. led[11:0] is a register, so you can access it at any time in any logic equation within that module. The value will only change when the always block that encloses it is triggered and the value is updated. 

--- Quote End ---  

 

 

Code example: 

reg value; reg circle_count; reg count; always @(posedge clk) begin count <= count + 1'b1; if (count == 1) begin count <= 0; circle_count <= circle_count + 1'b1; if (circle_count == 12) circle_count <= 0; end end always @(circle_count) begin case (circle_count) 0: value <= 5'b00101; 1: value <= value; // 5'b00101 2,3,4: value <= (value << 1); // always 0 - why? // When I start simulation test - it will changes succesfully // On Board - it always ZERO when I try to shift it. default: value <= 12'b10101; endcase end endmodule
0 Kudos
Altera_Forum
Honored Contributor II
713 Views

 

--- Quote Start ---  

Code example: 

reg value; reg circle_count; reg count; always @(posedge clk) begin count <= count + 1'b1; if (count == 1) begin count <= 0; circle_count <= circle_count + 1'b1; if (circle_count == 12) circle_count <= 0; end end always @(circle_count) begin case (circle_count) 0: value <= 5'b00101; 1: value <= value; // 5'b00101 2,3,4: value <= (value << 1); // always 0 - why? // When I start simulation test - it will changes succesfully // On Board - it always ZERO when I try to shift it. default: value <= 12'b10101; endcase end endmodule  

--- Quote End ---  

 

 

The highlighted code is just bad coding practice. Stop doing it. It will work in simulation but it produces a very poor implementation.
0 Kudos
Reply