How to run this code in series using verilog - verilog

The following code is compiled and is working in parallel, Please help me to make these code work sequentially, i.e after stage1 counter should reset itself and starts from 0 for the stage2. The following codes has Module1- stage1 and module2-stage2. This is the process flow in which one stage occur after completion of another. For example when stage 1 is done then counter reset itself and then stage 2 starts with count zero.Here stage 1 module has counter that counts till 18 and stage 2 counter counts 8.
module stage1(
input Clk, //50 Hz clock
input x0,
input reset,
output reg y0,y1,y2,y3,y5,y7,y10,y15,
output reg stage1_done
);
reg [15:0] counter = 0;
parameter F = 50;
always# (posedge Clk or posedge reset)
if(reset) begin
counter <= 0;
{y0,y1,y2,y3,y5,y7,y10,y15} <= 8'b00000000;
stage1_done <= 0;
end else begin
if(x0 == 1) begin
if(counter == 18*F)
stage1_done <= 1;
else begin
counter <= counter + 1;
stage1_done <= 0;
end
if(counter >= 1*F && counter < 10*F)
y0 <= 1;
else
y0 <= 0;
if(counter >= 1*F && counter < 17*F)
y1 <= 1;
else
y1 <= 0;
if(counter >= 1*F && counter < 9*F)
y2 <= 1;
else
y2 <= 0;
if(counter >= 11*F && counter < 16*F)
y3 <= 1;
else
y3 <= 0;
if(counter >= 1*F && counter < 18*F)
y5 <= 1;
else
y5 <= 0;
if(counter >= 1*F && counter < 5*F)
y7 <= 1;
else
y7 <= 0;
if(counter >= 1*F && counter < 5*F)
y10 <= 1;
else
y10 <= 0;
if((counter >= 2*F && counter < 9*F) || (counter >= 13*F && counter < 17*F))
y15 <= 1;
else
y15 <= 0;
end
end
endmodule
//Module for stage 2;
module stage2(
input x0,
input Clk, //50 Hz clock
input reset,
output reg y1,y3,y5,
output reg stage2_done
);
reg [15:0] counter = 0;
parameter F = 50;
always# (posedge Clk or posedge reset)
if(reset) begin
counter <= 0;
{y1,y3,y5} <= 3'b000;
stage2_done <= 0;
end
else begin if(x0 == 1) begin
if(counter == 8*F)
stage2_done <= 1;
else begin
counter <= counter + 1;
stage2_done <= 0;
end
if(counter >= 1*F && counter < 8*F)
y1 <= 1;
else
y1 <= 0;
if(counter >= 1*F && counter < 8*F)
y3 <= 1;
else
y3 <= 0;
if(counter >= 1*F && counter < 8*F)
y5 <= 1;
else
y5 <= 0;
end
end
endmodule

If you want a counter from stage2 module to start counting after counter from stage1 finishes, then you have to "inform" it that the other one finished counting. In your case you can use stage1_done signal and feed it to stage2 module. Use this signal as a condition for counter to start counting initially. Also, shouldn't you reset the counter from stage1 back to 0 when you assert stage1_done?

Think of it as a state machine. with 2 or 3 states, i.e. reset, stage1, stage2. You need to think over the conditions which would move from one stage to another. You provided one condition: stage1 counter overflow has to go from stage1 to stage2. There are definitely few question: what happens to stage1 while stage2 is running, what what happens when stage 2 is finished. What happens during reset?
So, I suggest that you create yest another module to implement the state machine logic:
module control(clk, ...);
enum { reset, stage1, stage2} state, next_state;
always_ff #( posedge clk)
case (state)
reset:
if (!resetSig) next_state <= stage1;
else if (resetSig) next_state <= reset;
stage1:
if (stage1Done) next)state <= stage2;
...
endcase
assign state = next_state;
Now in every stage you just use state as an enable condition.
module stage1(clk, state, stageDone, ...)
always_ff
if (state == reset)
do reset
else if (state == stage1)
do stage1
assign stageDone = counter == max_value;
and so on. Yes, you will need to pass extra ports for the state machine controls, but you will make your code much more manageable and readable and confirm to industry practices.

Related

Verilog synthesis is giving me an error that I don't understand

I am getting this error when synthesizing my code, but I don't know what it means. It reads:
Error- net "Count[0] or a directly connected net is driven by more
than one source and not all drivers are three state.
It says the same errors for vectors count[0] - count[4] as well as for my load and k values. The code is my representation of an SPI Master. The SPI master has an instantiation of a shift register that is used to push out information.
module SPIMaster(output reg SCLK, CS, MOSI,
input EN, CLK, MISO,
input [7:0] m_data);
wire master_out;
reg [4:0] count;
wire [7:0] data_buff;
wire SCLK1;
reg master_in, c_sw, k, state, load;
shiftReg register_out (master_out, data_buff, load, (~SCLK), master_in, m_data);
assign SCLK1 = (~c_sw) | CLK;
always#(posedge CLK) begin
if(state) begin
if (k == 1) begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
else begin
state <= 1;
c_sw <= 1;
CS <= 0;
end
end
else begin
if (EN == 1) begin
state <= 1;
c_sw <= 1;
CS <= 0;
count <= 0;
k <= 0;
load <= 1;
end
else begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
end
end
always#(posedge SCLK1) begin
if (CS == 0) master_in <= MISO;
if (count == 7) begin
load <= 0;
end
else if (count == 15)begin
load <= 0;
end
else begin
load <= 1;
end
end
always#(negedge SCLK1) begin
if (count == 23) k <= 1;
else k <= 0;
if (CS == 0) begin
MOSI <= master_out;
count <= count + 1;
end
end
endmodule
Your code does not adhere to good synthesis coding practices because you assign to count from 2 different always blocks and those 2 blocks are triggered by different clock signals. You should make all assignments to count from the same always block.
The same is true of load and k.

Failed to use "generate" for memory

I'm using Verilog-2001 with Vivado 2015.4. There is my code:
parameter SHIFT = 16;
wire integrators_reset;
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem [SHIFT - 1 : 0];
reg [SHIFT - 1 : 0] full_mem;
wire [SHIFT - 1 : 0] equal;
genvar i;
generate
for(i = 0; i < SHIFT; i = i + 1) begin
always #(negedge equal[i]) begin
if(integrators_reset) begin
sum_mem[i] <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem[i] <= sum_mem[i] + 1;
end
end
end
endgenerate
There is the error:
ERROR: [DRC 23-20] Rule violation (MDRV-1) Multiple Driver Nets- Net sum_mem[0][0] has multiple drivers
If i'm not using "generate" all is fine. For example:
always #(negedge equal[0]) begin
if(integrators_reset) begin
sum_mem[0] <= 0;
full_mem[0] <= 0;
end
else begin
if(sum_mem[0] == INTEGRATOR_MAX)
full_mem[0] <= 1;
else
sum_mem[0] <= sum_mem[0] + 1;
end
end
And there is not errors during implementation.
This seems like a tool limitation. You should be able to assign different fixed elements of an unpacked array from different always blocks. One workaround would be to move the declaration of sum_mem into the generate block.
for(I = 0; I < SHIFT; i = i + 1) begin : block_name
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem;
always #(negedge equal[I]) begin
if(integrators_reset) begin
sum_mem <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem <= sum_mem + 1;
end
end
end
Now you have block_name[0].sum_mem, block_name[1].sum_mem, but you can not access block_name with a variable index.

Value in register keeps resetting to 0 every clock cycle

I do not understand why the timer counter in this code does not work. At the end of every clock cycle the value resets to 0, so the output would look like this:
clock: 0 timer: 0
clock: 1 timer: 1
clock: 0 timer: 0
clock: 1 timer: 1
Code:
module controller(clock, reset, enable, lightN, lightS, lightE, lightW, NScolor, EWcolor);
input clock, reset, enable, lightN, lightS, lightE, lightW;
output NScolor, EWcolor;
wire clock, reset, enable, lightN, lightS, lightE, lightW;
reg NScolor, EWcolor;
reg timer;
always # (posedge clock)
begin: COUNT
$display("TIMER = %d", timer);
if (reset == 1) begin
$display("Resetting!");
NScolor<= 1;
EWcolor<= 0;
timer <= 0;
end
else if (enable == 1) begin
timer <= timer + 1;
if (timer == 7) begin
switchLights;
end
else if (timer >= 10) begin
timer <= 0;
switchLights;
end
end
end
task switchLights;
begin
if (NScolor == 0 && EWcolor == 2) begin
NScolor<= 1;
EWcolor<= 0;
end
else if (NScolor == 1) begin
NScolor<= 2;
EWcolor<= 0;
end
else if (NScolor == 2) begin
NScolor<= 0;
EWcolor<= 1;
end
if (EWcolor == 0 && NScolor == 2) begin
EWcolor<= 1;
NScolor<= 0;
end
else if (EWcolor == 1) begin
EWcolor<= 2;
NScolor<= 0;
end
else if (EWcolor == 2) begin
EWcolor<= 0;
NScolor<= 1;
end
end
endtask
endmodule
You have declared timer as:
reg timer;
which is a single-bit register. Hence, it only assumes values 0 an 1 in your simulation.
You may declare it as a multi-bit register, or declare it as an integer variable (assuming this code is anyway for simulation-purposes only, not for synthesis).
Note that you also have other issues in your code. For instance you declare EWColor as a single bit, but still attempt to assign it to 2, and compare it against 2.

Verilog - multiple edges in one block like in VHDL?

I'm using Quartus II, version 11.0 and I'm trying to port my VHDL code to Verilog (just for practice).
I need to check - how long 'a' line is low. There are working VHDL code:
process (clock, a)
begin
-- on each rising edge of clock...
if (rising_edge(clock))
then -- count how long 'a' is low
if (a = '0' and a_low_time < 3)
then
a_low_time <= a_low_time + 1;
end if;
end if;
-- reset counter if 'a' is not low
if a = '1' then
a_low_time <= 0;
end if;
end process;
Very simple, it's working perfectly. But how can I do it using Verilog?
This code:
// on each rising edge of clock...
always # (posedge clock)
begin
// count how long 'a' is low
if (!a && a_low_time < 3)
a_low_time <= a_low_time + 1;
end
// reset counter if 'a' is high
always # (*)
begin
if (a)
a_low_time <= 0;
end
Throws "сan't resolve multiple constant drivers" error. And this:
always # (posedge clock, posedge a)
begin
if (!a && a_low_time < 3)
a_low_time <= a_low_time + 1;
else if (a)
a_low_time <= 0;
end
Throws "cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct" error.
This code is working:
always # (posedge clock)
begin
if (!a && a_low_time < 3)
a_low_time <= a_low_time + 1;
else if (a)
a_low_time <= 0;
end
But I need to reset a_low_time immediately after 'a' goes high but not on rising edge of clock.
How can I do it? Can't believe that I can't do so simple task.
Why do you need to reset a_low_time asynchronously? In any case, maybe you can use a as your reset line:
always #(posedge clock or posedge a)
begin
if (a)
a_low_time <= 0;
else if (!a && a_low_time < 3)
a_low_time <= a_low_time + 1;
Actually, since a is your reset, you shouldn't need to check it to increment:
always #(posedge clock or posedge a)
begin
if (a)
a_low_time <= 0;
else if (a_low_time < 3)
a_low_time <= a_low_time + 1;

How to test primality in Verilog?

I have the Verilog code shown below, and if I try to compile it I get an error message. The point is that I'm trying to manipulate an input, which as long as I know cannot be done in Verilog. The point is that I need check the following condition in Verilog:
static int prime(unsigned long long n)
{
unsigned long long val = 1;
unsigned long long divisor = 5;
if (n == 2 || n == 3)
return 1;
if (n < 2 || n%2 == 0 || n%3 == 0)
return 0;
for ( ; divisor<=n/divisor; val++, divisor=6*val-1)
{
if (n%divisor == 0 || n%(divisor+2) == 0)
return 0;
}
return 1;
}
At the moment I have the following code:
module prime(clk, rst, start, A, ready, P);
input clk, rst, start;
input [7:0] A;
output ready, P;
reg ready, P;
wire [7:0] divisor;
assign divisor = 5;
wire [7:0] val;
assign val = 1;
always # (posedge clk or posedge rst) begin
if (!rst) begin
P <= 0;
end
else if (start) begin
case (A)
0 : P <= 1;
1 : P <= 1;
2 : P <= 1;
3 : P <= 1;
endcase
if (A%2 == 0 && A != 2) begin
P <= 0;
end
else begin
for( ; divisor <= A/divisor; val=val+1, divisor=6*val-1) begin
if (A%divisor == 0 || A%(divisor+2) == 0) begin
P <= 0;
end
end
// need to set P to 1
end
end
end
endmodule
Please also note I need to test primes in the form of 6n+1 or 6n-1, and I also need to assume in my code that 0 and 1 are also primes.
If I try the above code I get an error message saying:
Enhanced FOR loop is not enabled for verilog
If anyone can help me solve the error and finish my logic in Verilog, I would be glad.
The Verilog BNF does not allow empty or compound statements in for(;;). Change the file to *.sv to compile it under SystemVerilog rules. Otherwise change your for loop statement to have simple statements
for( divisor =5; divisor <= A/divisor; divisor=6*val-1) begin
if (A%divisor == 0 || A%(divisor+2) == 0) begin
P <= 0;
end
val++;
end
Also, you can't make procedural assignments to wires. make them variables.

Resources