onehot.v.txt
上传用户:saul_905
上传日期:2013-11-27
资源大小:184k
文件大小:6k
- //
- // Just a little demo of some FSM techniques, including One-Hot and
- // using 'default' settings and the case statements to selectively
- // update registers (sort of like J-K flip-flops).
- //
- // tom coonan, 12/98.
- //
- module onehot (clk, resetb, a, b, x, y);
- input clk;
- input resetb;
- input [7:0] a;
- input [7:0] b;
- output [7:0] x;
- output [7:0] y;
- // Use One-Hot encoding. There will be 16 states.
- //
- reg [15:0] state, next_state;
- // These are working registers. Declare the register itself (e.g. 'x') and then
- // the input bus used to load in a new value (e.g. 'x_in'). The 'x_in' bus will
- // physically be a wire bus and 'x' will be the flip-flop register ('x_in' must
- // be declared 'reg' because it's used in an always block.
- //
- reg [7:0] x, x_in;
- reg [7:0] y, y_in;
- // Update state. 'state' is the actual flip-flop register and next_state is the combinatorial
- // bus used to update 'state''s value. Check for the ZERO state which means an unexpected
- // next state was computed. If this occurs, jump to our initialization state; state[0].
- //
- // It is considered good practice by many designers to seperate the combinatorial
- // and sequential aspects of state registers, and often registers in general.
- //
- always @(posedge clk or negedge resetb) begin
- if (~resetb) state <= 0;
- else begin
- if (next_state == 0) begin
- state <= 16'h0001;
- end
- else begin
- state <= next_state;
- end
- end
- end
- // Implement the X flip-flop register. Always load the input bus into the register.
- // Reset to zero.
- //
- always @(posedge clk or negedge resetb) begin
- if (~resetb) x <= 0;
- else x <= x_in;
- end
- // Implement the Y flip-flop register. Always load the input bus into the register.
- // Reset to zero.
- //
- always @(posedge clk or negedge resetb) begin
- if (~resetb) y <= 0;
- else y <= y_in;
- end
- // Generate the next_state function. Also, based on the current state, generate
- // any new values for X and Y.
- //
- always @(state or a or b or x or y) begin
- // *** Establish defaults.
-
- // Working registers by default retain their current value. If any particular
- // state does NOT need to change a register, then it doesn't have to reference
- // the register at all. In these cases, the default below takes affect. This
- // turns out to be a pretty succinct way to control stuff from the FSM.
- //
- x_in <= x;
- y_in <= y;
-
- // State by default will be cleared. If we somehow ever got into an unknown
- // state, then the default would throw state machine back to zero. Look
- // at the sequential 'always' block for state to see how this is handled.
- //
- next_state <= 0;
-
- // One-Hot State Machine Encoding.
- //
- // *** Using a 1'b1 in the case statement is the trick to doing One-Hot...
- // DON'T include a 'default' clause within the case because we want to
- // establish the defaults above. ***
- //
- case (1'b1) // synopsys parallel_case
-
- // Initialization state. Set X and Y register to some interesting starting values.
- //
- state[0]:
- begin
- x_in <= 8'd20;
- y_in <= 8'd100;
- next_state[1] <= 1'b1;
- end
-
- // Just for fun.. Jump through states..
- state[1]: next_state[2] <= 1'b1;
- state[2]: next_state[3] <= 1'b1;
- state[3]: next_state[4] <= 1'b1;
- state[4]: next_state[5] <= 1'b1;
- state[5]: next_state[6] <= 1'b1;
- state[6]: next_state[7] <= 1'b1;
-
- // Conditionally decrement Y register.
- state[7]:
- begin
- if (a == 1) begin
- y_in <= y - 1;
- next_state[1] <= 1'b1;
- end
- else begin
- next_state[8] <= 1'b1;
- end
- end
-
- // Just for fun.. Jump through states..
- state[8]: next_state[9] <= 1'b1;
- state[9]: next_state[10] <= 1'b1;
- state[10]: next_state[11] <= 1'b1;
- // Conditionally increment X register.
- state[11]:
- begin
- if (b == 1) begin
- x_in <= x + 1;
- next_state[1] <= 1'b1;
- end
- else begin
- next_state[12] <= 1'b1;
- end
- end
- // Just for fun.. Jump through states..
- state[12]: next_state[13] <= 1'b1;
- state[13]: next_state[14] <= 1'b1;
- state[14]: next_state[15] <= 1'b1;
- state[15]: next_state[1] <= 1'b1; // Don't go back to our initialization state, but state following that one.
- endcase
- end
- endmodule
- // synopsys translate_off
- module test_onehot;
- reg clk, resetb;
- reg [7:0] a;
- reg [7:0] b;
- wire [7:0] x;
- wire [7:0] y;
- // Instantiate module.
- //
- onehot onehot (
- .clk(clk),
- .resetb(resetb),
- .a(a),
- .b(b),
- .x(x),
- .y(y)
- );
- // Generate clock.
- //
- initial begin
- clk = 0;
- forever begin
- #10 clk = ~clk;
- end
- end
- // Reset..
- //
- initial begin
- resetb = 0;
- #33 resetb = 1;
- end
- // Here's the test.
- //
- // Should see X and Y get initially loaded with their starting values.
- // As long as a and b are zero, nothing should change.
- // When a is asserted, Y should slowly decrement. When b is asserted, X should
- // slowly increment. That's it.
- //
- initial begin
- a = 0;
- b = 0;
- repeat (64) @(posedge clk);
- #1
-
- // Y should be decremented..
- a = 1;
- b = 0;
- repeat (256) @(posedge clk);
- #1
-
- // X should be incremented..
- a = 0;
- b = 1;
- repeat (256) @(posedge clk);
-
- $finish;
- end
- // Monitor the module.
- //
- initial begin
- forever begin
- @(posedge clk);
- #1;
- $display ("a = %b, b = %b, x = %0d, y = %0d", a,b,x,y);
- end
- end
-
- endmodule