verilog with out control variables cnt - counter

module count(clk,rst,cnt);
want to wrire the verilog code which counts upto 7 and then down to
0 and repeats forever as follows. 0,1,2,3,4,5,6,7,6,5,4,4,3,2,1
endmodule
Blockquote

Repeat state 4 for two times while counting down:
module count(
input clk,
input rst,
output cnt
);
reg [2:0] counter;
assign cnt = counter;
// Count up if flag is 1'b0, count down if flag is 1'b1
wire flag;
assign flag = (counter == 3'b1) ? 1'b1 : (counter == 3'b0) ? 1'b0;
// Repeat counter once if special_flag is 2'b01
reg [1:0] special_flag;
always #(posedge clk)
begin
if (flag == 1'b0)
begin
counter = counter + 1;
end
else if (counter == 3'b100 && special_flag == 2'b01)
begin
// Do not decrease counter, reset special_flag back to 2'b0
special_flag = 2'b0;
end else
begin
counter = counter - 1;
end
// Set special_flag to be 2'b01 when counter is 3'b1
if (counter == 3'b1)
begin
special_flag = 2'b01;
end
end
endmodule

module count(
input clk,
input rst,
output cnt
);
reg [2:0] counter;
assign cnt = counter;
// Count up if flag is 1'b0, count down if flag is 1'b1
wire flag;
assign flag = (counter == 3'b1) ? 1'b1 : (counter == 3'b0) ? 1'b0;
always #(posedge clk)
begin
if (flag == 1'b0)
begin
counter = counter + 1;
end
if (flag == 1'b1)
begin
counter = counter - 1;
end
end
endmodule

Related

Expected unique0-if behavior inside a for loop

I am creating a parameterized module to direct register traffic to multiple targets. The parameters are the number of targets and the address ranges that each target responds to. I have coded this as an if inside of a for loop with default values set before the loop to handle the case where no address matches. I would like to use unique0 to clarify that the ranges cannot overlap so this will not be implemented a a priority mux:
always_comb begin
valid_addr = 1'b0;
active_target = '0;
target_addr = '1;
for(int i = 0; i<NUM_TARGETS; i++) begin
unique0 if((addr >= START_ADDR[i]) && (paddr < (START_ADDR[i] + ADDR_SPAN[i]))) begin
valid_addr = 1'b1;
active_target = i;
target_addr = addr - START_ADDR[i];
end
end
end
The question is: will this unique0 do what I want? I am hoping that this is equivalent to the unrolled loop implemented as something like:
unique0 if ((addr >= START_ADDR[0]) && (paddr < (START_ADDR[0] + ADDR_SPAN[0]))) begin
valid_addr = 1'b1;
active_target = 0;
target_addr = addr - START_ADDR[0];
end
else if ((addr >= START_ADDR[1]) && (paddr < (START_ADDR[1] + ADDR_SPAN[1]))) begin
valid_addr = 1'b1;
active_target = 1;
target_addr = addr - START_ADDR[1];
end
else begin
valid_addr = 1'b0;
active_target = '0;
target_addr = '1;
end
I already have a problem since this will not compile with unique0 but will compile with unique so that either answers my question or my simulator just doesn't like it for some reason:
unique0 if((addr >= START_ADDR[i]) && (addr < (START_ADDR[i] + ADDR_SPAN[i]))) begin
|
expecting an '=' or '<=' sign in an assignment [9.2(IEEE)].
in order to do what your unrolled statement implies and to make it synthesizable, you would need to use a match flag. Something like in the following:
logic match_flag; //<<<
always_comb begin
match_flag = 1'b0; //<<<
valid_addr = 1'b0;
active_target = '0;
target_addr = '1;
for(int i = 0; i<NUM_TARGETS; i++) begin
if(!match_flag && (addr >= START_ADDR[i]) && (paddr < (START_ADDR[i] + ADDR_SPAN[i]))) begin
valid_addr = 1'b1;
active_target = i;
target_addr = addr - START_ADDR[i];
match_flag = 1'b1; //<<<
end
end
end
some synthesizers might support the break statement which could be used instead of the flag. Check documentation.

SystemVerilog error: "already exists; must not be redefined as a named block"

I'm creating a state machine with implicit datapath and am getting three errors that I haven't been able to resolve.
For the endcase error, I've made sure that all the begins have a corresponding end in the always block.
For the Finish error, the state has only been defined once so I'm not sure about that.
For the ; error, I have no idea why it doesn't want me to include countx and county statements.
Any help would be appreciated!
module fillscreen(input logic clk, input logic rst_n, input logic [2:0] colour,
input logic start, output logic done,
output logic [7:0] vga_x, output logic [6:0] vga_y,
output logic [2:0] vga_colour, output logic vga_plot);
enum logic [1:0] {Load = 2'b00, Increment = 2'b01, Out = 2'b10, Finish = 2'b11} state, next_state;
logic [7:0] countx, county;
always # (posedge clk) begin
case(state)
Load:
if(rst_n == 0)
next_state <= Load;
else if (start == 1)
next_state <= Increment;
else begin
next_state <= Load; end
//initialize counter
countx <= 0;
county <= 0;
Increment:
if(rst_n == 0)
next_state <= Load;
else if (county < 119 && countx < 159) begin
county <= county+1;
next_state <= Increment; end
else if (countx < 159) begin
countx <= countx +1;
next_state <= Increment; end
else
next_state <= Finish;
//output
vga_y <= county;
vga_x <= countx;
vga_colour <= countx % 8;
vga_plot <= 1;
Finish:
done <= 1;
if(rst_n == 0)
next_state <= Load;
else begin
next_state = Finish; end
Default:
vga_y <= county;
vga_x <= countx;
done <= 0;
vga_plot <= 0;
endcase
end
endmodule
Here are the errors I'm getting:
** Error: fillscreen.sv(22): near ";": syntax error, unexpected ';', expecting ':'
** Error: fillscreen.sv(54): near "endcase": syntax error, unexpected endcase
** Error: fillscreen.sv(25): 'Increment' already exists; must not be redefined as a named block
** Error fillscreen.sv(43): 'Finish' already exists; must not be redefined as a named block
For any case, you need to include begin..end if the code block for that case has multiple lines, just like if-statements or always blocks (see comments inline, there more than just missing begin..end):
case(state) // <- Note, you never assign state, only next_state, might want to review your code for correctness
Load: begin // <- This case has multiple lines
if (rst_n == 0) begin // <- I do begin..end for EVERYTHING as I inevitably come back and add lines in the body which can lead to bugs if there is no begin..end, like {..} in C
next_state <= Load;
end
else if (start == 1) begin
next_state <= Increment;
end
else begin
next_state <= Load;
end
//initialize counter
countx <= 0;
county <= 0;
end
Increment: begin
if (rst_n == 0) begin
next_state <= Load;
end
else if (county < 119 && countx < 159) begin
county <= county+1;
next_state <= Increment;
end
else if (countx < 159) begin
countx <= countx +1;
next_state <= Increment;
end
else begin
next_state <= Finish;
end
//output
vga_y <= county;
vga_x <= countx;
vga_colour <= countx % 8;
vga_plot <= 1;
end
Finish: begin
done <= 1;
if (rst_n == 0) begin
next_state <= Load;
end
else begin
next_state <= Finish; // Should be non-blocking
end
end
default: begin // <- Should be lower-case "default"
vga_y <= county;
vga_x <= countx;
done <= 0;
vga_plot <= 0;
end
endcase

State machine transitions to impossible state on Signal Tap

I am trying to output one bit at a time via SPI from a know 2D array.
logic [7:0] fpga_status_queue [0:17],
My state machine is for some reason going to a weird state.
18'h
Here is my code:
module FPGA_STATUS_READ (
input clk,
input sclk,
input cs, // Clock Enable
input rst_n, // Asynchronous reset active low
input fpgastatus_command,
input logic [3:0] group_control,
input logic [7:0] loopback,
output logic [7:0] fpga_status_queue [0:17],
output logic dout
);
// `include "../../config_files/rtl_config.svh"
assign fpga_status_queue[ 0] = 8'h1;//{group_control};
assign fpga_status_queue[ 1] = 8'h1;//{loopback};
assign fpga_status_queue[ 2] = 8'h1;//{synth_version[0]};
assign fpga_status_queue[ 3] = 8'h1;//{synth_version[1]};
assign fpga_status_queue[ 4] = 8'h1;//{synth_version[2]};
assign fpga_status_queue[ 5] = 8'h1;//{grid_version[0]};
assign fpga_status_queue[ 6] = 8'h1;//{grid_version[1]};
assign fpga_status_queue[ 7] = 8'h1;//{grid_version[2]};
assign fpga_status_queue[ 8] = 8'h1;//{pa_version[0]};
assign fpga_status_queue[ 9] = 8'h1;//{pa_version[1]};
assign fpga_status_queue[10] = 8'h1;//{pa_version[2]};
assign fpga_status_queue[11] = 8'h1;//{hdl_version[0]};
assign fpga_status_queue[12] = 8'h1;//{hdl_version[1]};
assign fpga_status_queue[13] = 8'h1;//{hdl_version[2]};
assign fpga_status_queue[14] = '1;
assign fpga_status_queue[15] = '1;
assign fpga_status_queue[16] = '0;
assign fpga_status_queue[17] = '0;
logic bit_run_counter;
logic bit_load_counter;
logic [4:0] bit_current_value;
logic bit_count_reached;
logic word_run_counter;
logic word_load_counter;
logic [4:0] word_current_value;
logic word_count_reached;
typedef enum logic [2:0] {IDLE, CS_WAIT, MISO_OUT, BIT_CHANGE, WORD_CHANGE} status_states;
status_states current_state, next_state;
always_ff #(posedge clk or negedge rst_n) begin : step_forward
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end : step_forward
always_comb begin : set_next_state
next_state = IDLE;
case (current_state)
IDLE : next_state = fpgastatus_command ? CS_WAIT : IDLE;
CS_WAIT : next_state = ~cs ? MISO_OUT : CS_WAIT;
MISO_OUT : begin//next_state = sclk ? bit_count_reached ? word_count_reached ? IDLE: WORD_CHANGE : BIT_CHANGE: MISO_OUT;
if (sclk && bit_count_reached && word_count_reached)
next_state = IDLE;
else if (sclk && bit_count_reached)
next_state = WORD_CHANGE;
else if (sclk)
next_state = BIT_CHANGE;
else
next_state = MISO_OUT;
end
BIT_CHANGE : next_state = MISO_OUT;
WORD_CHANGE: next_state = MISO_OUT;
default : next_state = IDLE;
endcase
end
always_comb begin : cntr_logic
bit_run_counter = '0;
bit_load_counter = '0;
word_run_counter = '0;
word_load_counter = '0;
dout = '0;
unique case (current_state)
IDLE :begin
bit_load_counter = '1;
word_load_counter = '1;
end
CS_WAIT :begin
bit_load_counter = '1;
word_load_counter = '1;
end
MISO_OUT :begin
dout = fpga_status_queue[word_current_value][bit_current_value];
end
BIT_CHANGE :begin
bit_run_counter = '1;
end
WORD_CHANGE:begin
word_run_counter = '1;
bit_load_counter = '1;
end
default : dout = '0;
endcase
end
up_down_counter #(
.ABSOLUTE_DATA_WIDTH(4)
) inst_bit_counter (
.clk (clk),
.run_counter (bit_run_counter),
.rst_n (rst_n),
.count_value (5'h7),
.load_counter (bit_load_counter),
.up_counter ('0),
.current_value (bit_current_value),
.count_reached (bit_count_reached)
);
up_down_counter #(
.ABSOLUTE_DATA_WIDTH(5)
) inst_word_counter (
.clk (clk),
.run_counter (word_run_counter),
.rst_n (rst_n),
.count_value (5'h11),
.load_counter (word_load_counter),
.up_counter ('0),
.current_value (word_current_value),
.count_reached (word_count_reached)
);
endmodule
It should go to WORD_CHANGE but both WORD_CHANGE and MISO_OUT for the next state for current state.
This is almost certainly a timing issue. I'm guessing that sclk is not synchronous to clk - probably it's connected directly to a device input pin.
The problem is this piece of code:
(...)
else if (sclk)
next_state = BIT_CHANGE;
else
next_state = MISO_OUT;
Whenever sclk transitions from zero to one, logic will raise the next_state bit corresponding to BIT_CHANGE, and in parallel lower the next_state bit corresponding to MISO_OUT. As this happens, there can be a brief moment where both bits are set or no bits are set, depending on which logic is faster. If you are unlucky and have a raising clk at this exact moment, you will get into the situation you are observing, where the state machine appears to be in two states at the same time.
The solution is to synchronize sclk, cs, and any other signals that determine the next state to clk. Such synchronization is typically done by simply sending the signals through two flip-flops.

If condition with externally selected value

I'm new to Verilog and it is maybe a dumb question but what is the preferred codeflow in Verilog to solve this problem:
Simple counter, counting external clk (INP) up to a particular value. If the counter matches the value it rises an output wire (DRDY) for one clk period then lowers it to 0. There is an external input (SR) where I'd like to set the comparison value, so if SR = 0, then the counting is up to 500000, if SR = 1 then up to 1000000. I can do it with one value, but I'd like to expand the functionality of my module.
Thank you in advance.
My code so far with one value comparison:
module ec(INP, RST, SR, DRDY, DRDY2);
input INP, RST, SR;
output reg DRDY, DRDY2;
reg [23:0] Q;
always #(posedge INP or negedge RST)
begin
if(!RST)
begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if( Q == 24'd1000000)
begin
Q <= 24'd0;
DRDY <= 1'b1;
DRDY2 <=~DRDY2;
end
else
begin
Q <= Q + 1;
DRDY <= 1'b0;
end
end
endmodule
An easy way to handle 2 options would be an expand the if statement:
always #(posedge INP or negedge RST) begin
if(!RST) begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if(
( (SR ==1'b0) && (Q == 24'd1000000) ||
(SR ==1'b1) && (Q == 24'd500000)
) begin
//...
end
else begin
//..
end
This can look quite messy in the code so could be separated out into a count target logic, if more options are to be supported then switch to a case statement instead of if.
reg [23:0] cnt_target ;
always #* begin
if (SR == 1'b1) begin
cnt_target = 24'd1000000 ;
else begin
cnt_target = 24'd500000 ;
end
end
always #(posedge INP or negedge RST) begin
if(!RST) begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if( Q == cnt_target) begin
//...
end
else begin
//..
end
NB: You might want to consider using Q >= cnt_target that way if SR changed on the fly you do not have to wait for Q to overflow. Plus >= for me tends to synthesis smaller than ==.

How can I show a sequence of numbers using a counter in Verilog

For example a have to show 0 , 2 , 4 , 0 , 2 , 4 .. I use an output with 8 segments - less important .
output reg [7:0] data
always # (*) begin
case
1:data= 8'b00000011; //number 0
2:data= 8'b00100101; //number 2
3:data= 8'b10011001; //number 4
default:data=8'b00000011;
endcase
end
And the counter :
input clock,
input reset,
output [7:0] out
reg [31:0] counter;
always # (posedge clock) begin
if(reset==1) counter <= 0;
else counter <= counter + 1;
end
My question is can I increment the case value instead of counter ?
Like :
always # (posedge clock) begin
if(reset==1) case <= 1;
else case <= case + 1;
if(case==3) reset<=1;
end
If not then how can I do this ?
Your case statement is wrong. It should select based on the counter value:
always # (*) begin
case(counter)
1: data= 8'b00000011; //number 0
2: data= 8'b00100101; //number 2
3: data= 8'b10011001; //number 4
default:data=8'b00000011;
endcase
end
Your counter should be:
always # (posedge clock) begin
if(reset==1 || counter == 3) counter <= 1;
else counter <= counter + 1;
end
Note that case is a keyword. You can't use it in an expression.