0
\$\begingroup\$

I'm trying to write an always block that will open a valve and then keep it open for a few seconds and then close it if needed. The valve opens when the input is 1 and it closes when it's zero. How can I make the code wait for a few seconds after the valve opens so that it doesn't close right after it opens?

Here is my code:

input in, alteraclock;
output reg out;
reg clock;
clock myclock(.clkin(alteraclock), .clkout(clock));
always@(in)
begin
if(in==1)
begin
out=1; //open valve
end
else
begin
out=0; //close valve
end
end

PS: I'm using an Altera DE2-115, if that helps at all.

asked Dec 12, 2015 at 20:40
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Use a state machine and a large counter. In one state, wait for the input to change. When the input changes, set the counter to a large number, update the output, and switch to the delay state. In the delay state, decrement the counter. When it reaches zero, switch back to the wait for input state.

Edit: I'm not going to write your code for you, but here is a template for a state machine that you can play with:

localparam [1:0]
 STATE_IDLE = 2'd0,
 STATE_1 = 2'd1,
 STATE_2 = 2'd2;
reg [1:0] state_reg = STATE_IDLE, state_next;
reg [16:0] count_reg = 0, count_next;
always @* begin
 state_next = STATE_IDLE;
 count_next = count_reg;
 case (state_reg)
 STATE_IDLE: begin
 // idle state
 if (condition) begin
 count_next = some_value;
 state_next = STATE_1;
 end else begin
 state_next = STATE_IDLE;
 end
 end
 STATE_1: begin
 // some state
 count_next = count_reg - 1;
 if (count_reg == 0) begin
 state_next = STATE_2;
 end else begin
 state_next = STATE_1;
 end
 end
 STATE_2: begin
 // another state
 if (some_condition) begin
 state_next = STATE_IDLE;
 end else begin
 state_next = STATE_2;
 end
 end
 endcase
end
always @(posedge clk) begin
 if (rst) begin
 state_reg <= STATE_IDLE;
 count_reg <= 0;
 end else begin
 state_reg <= state_next;
 count_reg <= count_next;
 end
end

Here is a way to do this without an explicit state machine:

reg [32:0] counter = 0;
always @(posedge clk) begin
 if (rst) begin
 counter <= 0;
 out <= 0;
 end else if (counter > 0) begin
 counter <= counter - 1;
 end else begin
 out <= in;
 if (out != in) begin
 counter <= some_delay_value;
 end
 end
end
answered Dec 12, 2015 at 20:59
\$\endgroup\$
8
  • \$\begingroup\$ Mind helping me with the code? \$\endgroup\$ Commented Dec 12, 2015 at 21:00
  • \$\begingroup\$ I think this is way too complicated for what I want to do. \$\endgroup\$ Commented Dec 12, 2015 at 21:29
  • \$\begingroup\$ What, a two always block state machine is too complicated? It is possible to compress it into a single always block, but it's slightly less readable. Also, the template I posted has 3 states; you only need 2. \$\endgroup\$ Commented Dec 12, 2015 at 21:44
  • \$\begingroup\$ Well, I suppose with only two states, you don't really need a whole state machine. \$\endgroup\$ Commented Dec 12, 2015 at 21:47
  • \$\begingroup\$ What is that rst in the first if condition? \$\endgroup\$ Commented Dec 12, 2015 at 22:27
0
\$\begingroup\$

The basic idea is to use a counter.

Most likely, you'll have a clock of 50Mhz which means you if you count to 50 million starting from 0 on your counter, it will take that clock around 1s. So you can output 1'b1 from your counter's module, once it's done counting. Hence, the output of this counter's module can give you a slowed down clk.

Implement it as explained above.

answered Dec 12, 2015 at 22:00
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.