Verilog, FPGA, use of an unitialized register

cpu-registers, fpga, fsm, verilog, xilinx

Solution

I answer in the context of FPGAs (I have most experience with Xilinx FPGAs); I disagree with Tim's answer.

When an FPGA is programmed and initialized, many internal resources are initialized to a known state. This includes all flip flops and block rams. By adding blanket reset logic throughout your design, you may make it significantly more complicated than it needs to be, if you could otherwise count on internal elements initializing to a known state. High fanout reset nets can make implementation of your design much more difficult for the router, and mapping your design into slices is also complicated by your choice of resets - especially asynchronous ones.

My suggestions:

- Use initialization values for your registers. Double check Xilinx XST documentation for the version you are using for supported syntax. Contrary to widely held belief, initialization values will be honored in most cases. The side benefit of doing this, is that the initial state of your chip will match the initial state of your simulation.

- Only reset necessary control signals and leave your datapath registers alone to allow more efficient mapping (for example, a pipeline into a shift register).

Problem

I have a question about what seems to me odd behavior of an AGC/SPI controller I'm working on. It's done in Verilog, targeting a Xilinx Spartan 3e FPGA. The controller is a FSM that relies on external inputs to start. The state of the FSM is stored in state_reg which is not explicitly initialized, as I thought an uninitialized register would default to zero. When I implemented the controller the FSM would not run. Monitoring the SPI bus I observed no activity. To monitor the FSM i routed the state_reg to an output bus that went to an LED bank. That is what the line assign data_out = state_reg is doing. I found though that when I did this the FSM an AGC/SPI controller operated correctly as observed on the SPI bus. It seems that what is happening is that state_reg is in an undetermined state when it initializes and hence the FSM is never in any state so it doesn't run. But by assigning state_reg to an output it initialized to 00000000 as I expected it to do from the beginning. So my question is, is an uninitialized register supposed to assume a value of 0? By assigning an uninitialized register to an output, does that force it to assume zero as it seemed? Or is something else going on here that I don't understand? Below is my code. I've commented the relevant part where *state_reg** is assigned to output wire [7:0] data_out. I know this is a long question but I"m really trying to understand what type of behavior I should expect. Thanks. ``` module agc_control ( input wire [7:0] agc_data, input wire clk, input wire agc_start, input wire AMP_DO, output reg MOSI, output reg SCK, output reg CS_AMP, output wire inhibit_ADC, output wire [7:0] data_out ); //signals reg [4:0] state_reg, reg [2: 0] ampclkreg; reg ampclk; reg [7:0] agc_data_reg; reg agc_running; reg [7:0] data_out_reg; wire agc_done; //ampclk generation always @(posedge clk) begin ampclkreg = ampclkreg + 1; if (ampclkreg == 3) begin ampclkreg = 0; ampclk = ~ampclk; end end always @(posedge clk) begin if(agc_start == 1) begin agc_running = 1'b1; agc_data_reg = agc_data; end if(agc_done == 1) begin agc_running = 1'b0; end end //FSM always @(posedge ampclk) begin if (agc_running == 0) begin SCK = 0; state_reg = 0; CS_AMP = 1; end if (agc_running == 1) begin case (state_reg) 0: begin CS_AMP = 1; SCK = 0; state_reg = 1; end 1: begin CS_AMP = 0; MOSI = agc_data_reg[7]; state_reg = 2; end 2: begin SCK = 1; state_reg = 3; end 3: begin SCK = 0; MOSI = agc_data_reg[6]; state_reg = 4; end 4: begin SCK = 1; state_reg = 5; end 5: begin SCK = 0; MOSI = agc_data_reg[5]; state_reg = 6; end 6: begin SCK = 1; state_reg = 7; end 7: begin SCK = 0; MOSI = agc_data_reg[4]; state_reg = 8; end 8: begin SCK = 1; state_reg = 9; end 9: begin SCK = 0; MOSI = agc_data_reg[3]; state_reg = 10; end 10:begin SCK = 1; state_reg = 11; end 11:begin SCK = 0; MOSI = agc_data_reg[2]; state_reg = 12; end 12:begin SCK = 1; state_reg = 13; end 13:begin SCK = 0; MOSI = agc_data_reg[1]; state_reg = 14; end 14:begin SCK = 1; state_reg = 15; end 15:begin SCK = 0; MOSI = agc_data_reg[0]; state_reg = 16; end 16:begin SCK = 1; state_reg = 17; end 17:begin CS_AMP = 1; state_reg = 18; end 18:begin SCK = 0; state_reg = 19; end 19:begin state_reg = 19; end default: state_reg = 19; endcase end end //retrieve previous vlaues always @(posedge clk) begin case(state_reg) 2: begin if (ampclkreg == 2) data_out_reg[7] = AMP_DO; end 4: begin if (ampclkreg == 2) data_out_reg[6] = AMP_DO; end 6: begin if (ampclkreg == 2) data_out_reg[5] = AMP_DO; end 8: begin if (ampclkreg == 2) data_out_reg[4] = AMP_DO; end 10:begin if (ampclkreg == 2) data_out_reg[3] = AMP_DO; end 12:begin if (ampclkreg == 2) data_out_reg[2] = AMP_DO; end 14:begin if (ampclkreg == 2) data_out_reg[1] = AMP_DO; end 16:begin if (ampclkreg == 2) data_out_reg[0] = AMP_DO; end endcase end //output wire [7:0] data_out--to top module to drive 7 LEDs and display state_reg assign data_out = state_reg; assign agc_done = (state_reg == 19); assign inhibit_ADC = (agc_running == 1); endmodule ```

Original source