I've been struggling with a very simple Verilog program. It's a 4 bit shift register that gets rotated at every clock cycle and drives four LEDs. (As you can tell I'm new to FPAGs and HDLs.)
The problem: Below code synthesises without warnings and is successfully programmed into the FPGA. Then, upon start, nothing happens, the LEDs stay dark. The i_Switch_1 input was added to make something happen at all and indeed when I push the switch the LEDs start rotating.
Here's the Verilog code:
Version 1 (fail)
module top
(input i_Clk,
input i_Switch_1,
output o_LED_1,
output o_LED_2,
output o_LED_3,
output o_LED_4
);
reg [3:0]shift_reg;
initial
shift_reg = 4'b0001; // has no effect
always @(posedge i_Clk)
begin
shift_reg <= i_Switch_1 ? 4'b0001 : {shift_reg[2:0], shift_reg[3]};
end
assign o_LED_1 = shift_reg[0];
assign o_LED_2 = shift_reg[1];
assign o_LED_3 = shift_reg[2];
assign o_LED_4 = shift_reg[3];
endmodule
Assessment: My conclusion so far is that shift_reg is not initialised to 1. The RTL view below shows that no initialisation is synthesized.
I read in many places that the initial block is synthesizable, so I'm really puzzled, now.
Question 1: Is my assessment correct?
Question 2: Assuming my assessment is correct, what is the remedy? I've tried various things and none of them work:
- Route in the reset pin, but that doesn't seem to be allowed.
- Use a
shift_reg==0comparison (version 2 below) - Use a
is_initflag (version 3 below)
I'm beginning to believe that I'm getting something fundamentally wrong. What is going on??
Version 2 (fail)
shift_reg <= (shift_reg==0 || i_Switch_1) ? 1 : {shift_reg[2:0], shift_reg[3]}
Version 3 (fail)
reg is_init;
initial
is_init = 0; // Must have this or else the is_init gets optimized out!
always @(posedge i_Clk)
begin
if(~is_init || i_Switch_1) begin
is_init <= 1;
shift_reg <= 4'b0001;
end
else begin
is_init <= 1;
shift_reg <= {shift_reg[2:0], shift_reg[3]};
end
end
Setup: LatticeSemi iCE40HX1K (nandland go board) using iCEcube2, synthesis tool is Synplify Pro.
--
Update
This here works:
Version 4 (success)
reg [3:0]shift_reg = 0;
always @(posedge i_Clk)
begin
case(shift_reg)
1: shift_reg <= 2;
2: shift_reg <= 4;
4: shift_reg <= 8;
8: shift_reg <= 1;
default:
shift_reg <= 1;
endcase
end
