I'm quite new to Verilog. I have some code working, but from time to time, I get some incomprehensible behavior, and I think I lack some knowledge in Verilog.
Here is a quick example of a more complex project. It works with the div2
module (/* go */
), and it doesn't with the div5
module (/* no go */
). Go / no go
means I got ssoc
signal on LED2 debug output or not.
module test_div_1(
/* iCEstick clk (12MHz) */
input clkin,
/* 10MHz ref_in */
input ref_in,
/* iCEstick leds */
output LED_GREEN,
output LED0, output LED1, output LED2, output LED3,
/* ADC (DIV) spi */
);
SB_PLL40_CORE #(
.FEEDBACK_PATH("SIMPLE"),
/* $ icepll -i 12 -o 30 */
/* clkin=12MHz */
.DIVR(0), /* DIVR = 0 (div 1) */
.DIVF(79), /* DIVF = 79 (x80) */
.DIVQ(5), /* DIVQ = 5 (div 6) */
/* main_clk=30MHz */
.FILTER_RANGE(3'b001) /* FILTER_RANGE = 1 */
) uut (
.LOCK(LED_GREEN),
.RESETB(1'b1),
.BYPASS(1'b0),
.REFERENCECLK(clkin),
.PLLOUTCORE(main_clk)
);
wire main_clk;
wire ref_in;
wire soc;
reg ssoc;
wire spi_m_clk;
/* soc generator (125kHz) */
div80 d80_1(ref_in, soc);
/* cs and clk generation */
/* -----\/----- EXCLUDED -----\/-----
div2 div_spi_clk(ref_in, spi_m_clk); /-* go *-/
-----/\----- EXCLUDED -----/\----- */
div5 div_spi_clk(ref_in, spi_m_clk); /* no go */
always @ (negedge spi_m_clk)
ssoc<=soc;
/* TODO: remove (debug) */
assign LED0=spi_m_clk;
assign LED1=soc;
assign LED2=ssoc;
assign LED3=1'b0;
endmodule /* # test_div_1 end # */
module div80(input in,
output out);
wire in;
reg out;
reg [6:0] c;
initial
begin
c=7'b0000000;
end
always@(posedge in)
begin
if(c>=79)
begin
c<=0;
out<=1'b1;
end
else
begin
out<=1'b0;
c<=c+1;
end
end
endmodule /* # div80 end # */
module div5(input in,
output out);
wire in;
reg out;
reg [2:0] c;
initial
begin
c=3'b000;
end
always@(posedge in)
begin
if(c>=4)
begin
c<=0;
out<=1'b1;
end
else
begin
out<=1'b0;
c<=c+1;
end
end
endmodule /* # div5 end # */
module div2(input in,
output out);
wire in, out;
reg c;
always@(posedge in)
begin
c<=!c;
end
assign out=c;
endmodule /* # div2 end # */
The div80
module output works fine.
Is my mistake related to something about wire
/reg
, or anything else?
I'm using ice40stick and icestorm toolchain (yosys, nextpnr and icepack).
Could you help me understand why my design does not behave properly?
1 Answer 1
When I try to compile your code with a couple simulators, I get multiple warning for your div5
and div2
modules. If you do not get warning messages with your simulator, try your code on the simulators on EDAPlayground.
Here is the code without any warnings:
module div5(input in,
output reg out);
reg [2:0] c;
initial
begin
c=3'b000;
end
always@(posedge in)
begin
if(c>=4)
begin
c<=0;
out<=1'b1;
end
else
begin
out<=1'b0;
c<=c+1;
end
end
endmodule /* # div5 end # */
module div2(input in,
output out);
reg c;
always@(posedge in)
begin
c<=!c;
end
assign out=c;
endmodule /* # div2 end # */
In div5
, you make assignments to out
from procedural code (always
block). This means you need to declare out
as reg
. In div2
, you use a procedural assign
statement, which means you should not declare it as a reg
.