Learning Verilog or VHDL from some good books/sources?

Topics relating to PALs, CPLDs, FPGAs, and other PLDs used for the support or creation of 65-family processors, both hardware and HDL.
User avatar
MichaelM
Posts: 761
Joined: 23 Apr 2012
Location: Huntsville, AL

Re: Learning Verilog or VHDL from some good books/sources?

Post by MichaelM »

I moved/renamed the wiki page that BigEd linked to. The page is found here.
Michael A.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Learning Verilog or VHDL from some good books/sources?

Post by BigEd »

Great to see all your wiki updates go by in my RSS reader Michael! I've updated the link in my post.
User avatar
MichaelM
Posts: 761
Joined: 23 Apr 2012
Location: Huntsville, AL

Re: Learning Verilog or VHDL from some good books/sources?

Post by MichaelM »

How does that work? I'm definitely behind the times.
Michael A.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Learning Verilog or VHDL from some good books/sources?

Post by BigEd »

Another seam of resources:
http://eesun.free.fr/DOC/VERILOG/synvlg.html
via
http://people.ece.cornell.edu/land/courses/ece5760/
(includes video lectures)

Cheers
Ed
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: Learning Verilog or VHDL from some good books/sources?

Post by ElEctric_EyE »

In Verilog:
Is it safe to make the assumption that 'always @ *', 'assign', 'output', and 'wire' all belong to the class of asynchronous signals?
While 'always @(posedge clk)', 'output reg', and 'reg' are meant to be synchronous only signals?
User avatar
MichaelM
Posts: 761
Joined: 23 Apr 2012
Location: Huntsville, AL

Re: Learning Verilog or VHDL from some good books/sources?

Post by MichaelM »

reg does not mean FF.

Try the following code fragment in a module:

Code: Select all


module Reg_Test(
    input  Rst,
    input  Clk,

    input  WE,
    input  OE,
    input  [7:0] DI,
    output reg [7:0] DO
);

reg   [7:0] Q;

always @(posedge Clk)
begin
    if(Rst)
         Q <= #1 0;
    else if(WE)
         Q <= #1 DI;
end

always @* DO <= (OE ? Q : 0);

endmodule

Notice DO is declared as a reg. Change the definition from reg to wire, and try to synthesize the module.

The lesson is that only a reg implemented within an always @(posedge Clk) block will synthesize to a synchronous element.
Michael A.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: Learning Verilog or VHDL from some good books/sources?

Post by ElEctric_EyE »

What is the difference between the following 2 statements?

Code: Select all

Assign SRD = SRDO;
and

Code: Select all

always @*
     SRD <= SRDO;
Are they not both combinatorial circuits?
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Learning Verilog or VHDL from some good books/sources?

Post by Arlet »

In synthesis, these are the same.

In simulation, there will be a difference. In the 'assign' case, SRD is always the same as SRDO. In the second case, SRD only follows SRDO when the latter changes value. So, if SRD is initialized as '0', and SRDO is initialized as '1', and SRDO never changes, SRD will remain '0'.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Learning Verilog or VHDL from some good books/sources?

Post by BigEd »

I might expect a simulation performance difference too, although I haven't checked.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Address Decoding

Post by ElEctric_EyE »

I have another question regarding address decoding. I currently use comparators for a ROM decoder which works:

Code: Select all

if ( (cpuAB >= 32'hffff_f000) && (cpuAB <= 32'hffff_ffff) )        //4Kx16 'initialized RAM' ROM address decode
		rom1CS <= 0;
		else rom1CS <= 1;
When I try to do it a different way, it doesn't work and I'm wondering why.

Code: Select all

if (cpuAB == 32'b1111_1111_1111_1111_1111_xxxx_xxxx_xxxx)		//4Kx16 'initialized RAM' ROM address decode
		rom1CS <= 0;
		else rom1CS <= 1;
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Learning Verilog or VHDL from some good books/sources?

Post by Arlet »

It's because 0 == x or 1 == x result in a false result. If you want to treat 'x' as don't care, you need to use casex/casez.

You could compare cpuAB[31:12] with 20'hFFFFF;
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: Learning Verilog or VHDL from some good books/sources?

Post by ElEctric_EyE »

Thanks, it was becoming cumbersome to use comparators, especially for decoding only for a few consecutive addresses for I/O ports. I'll work with the casex structure now.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: Learning Verilog or VHDL from some good books/sources?

Post by ElEctric_EyE »

I like it much better! Easier on the eyes too.

Code: Select all

always @*
	casex(cpuAB [31:0])
		32'b1111_1111_1111_1111_1111_xxxx_xxxx_xxxx:     //$FFFF_F000-$FFFF_FFFF
				rom1CS <= 0;
	default: rom1CS <= 1;
endcase
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

For us who follow Verilog

Post by ElEctric_EyE »

I just got home and tried it in the project and it doesn't fit.
Seems like it's best to have 2 comparators for linear memory addressing (beginning and end, code @ bottom) Chip Select signals vs. all the 'x's and the MUX's (maybe for a non-linear addressing, code @ below).

This is what I had for the MUX's (slow):

Code: Select all

module A_D ( input cpuWE,
					  input [31:0] cpuAB,
					  input [15:0] ZPP,				//from CPU, zeropage pointer
					  input [15:0] SPP,				//from CPU, stackpage pointer
					  output reg ram1CS = 0,
					  output reg ram1WE = 0,		//pre-init to '0', not selected
					  output reg ram2CS = 0,
					  output reg ram2WE = 0,		//pre-init to '0', not selected
					  output reg rom1CS = 0,		//pre-init to '0', selected
					  output reg vramCS = 0,
					  output reg rndgCS = 0,
					  output reg cntrCS = 0
					  );

// address decoding for internal blockRAMs

always @* begin
	ram1WE <= ( !ram1CS && cpuWE );
	ram2WE <= ( !ram2CS && cpuWE );
end

always @*
	casex(cpuAB [31:0])
		32'b1111_1111_1111_1111_1111_xxxx_xxxx_xxxx:
				rom1CS <= 0;
	default: rom1CS <= 1;
endcase

always @*
	casex(cpuAB [31:0])
		{SPP,16'b1111_1100_xxxx_xxxx}:
				ram2CS <= 0;
	default: ram2CS <= 1;
endcase

always @*
	casex(cpuAB [31:0])
		{ZPP,16'b0000_00xx_xxxx_xxxx}:
				ram1CS <= 0;
	default: ram1CS <= 1;
endcase

always @*
	casex(cpuAB [31:0])
		32'b0000_0010_xxxx_xxxx_0000_0010_xxxx_xxxx:
				vramCS <= 1;
	default: vramCS <= 0;
endcase

always @*
	casex(cpuAB [31:0])
		32'b1100_0000_0000_0000_0000_0000_0000_000x:
				cntrCS <= 1;
	default: cntrCS <= 0;
endcase

always @*
	casex(cpuAB [31:0])
		32'b1010_0000_0000_0000_0000_0000_0000_0000:
				rndgCS <= 1;
	default: rndgCS <= 0;
endcase
	
endmodule
This is what I have reverted back too:

Code: Select all

module A_D ( input cpuWE,
					  input [31:0] cpuAB,
					  input [15:0] ZPP,				//from CPU, zeropage pointer
					  input [15:0] SPP,				//from CPU, stackpage pointer
					  output reg ram1CS = 0,
					  output reg ram1WE = 0,		//pre-init to '0', not selected
					  output reg ram2CS = 0,
					  output reg ram2WE = 0,		//pre-init to '0', not selected
					  output reg rom1CS = 0,		//pre-init to '0', not selected
					  output reg vramCS = 0,
					  output reg rndgCS = 0,
					  output reg cntrCS = 0
					  );

// address decoding for internal blockRAMs

always @* begin
	ram1WE <= ( !ram1CS && cpuWE );
	ram2WE <= ( !ram2CS && cpuWE );
	if ( (cpuAB >= {ZPP,16'h0000}) && cpuAB <= ({ZPP,16'h03ff}) )		//1Kx16 zeropage RAM address decode w/ZPP reg as the MSB pointer
		ram1CS <= 0;
		else ram1CS <= 1;
	if ( (cpuAB >= {SPP,16'hfc00}) && cpuAB <= ({SPP,16'hffff}) )		//1Kx16 stackpage RAM address decode w/SPP reg as the MSB pointer
		ram2CS <= 0;
		else ram2CS <= 1;
	if ( (cpuAB >= 32'hffff_f000) && (cpuAB <= 32'hffff_ffff) )			//4Kx16 'initialized RAM' ROM address decode
		rom1CS <= 0;
		else rom1CS <= 1;
	if (cpuAB >= 32'h0000_0000 && cpuAB <= 32'h0280_01e0) 				//video space
		vramCS <= 1;
		else vramCS <= 0;
	if (cpuAB == 32'ha000_0000)													//random number generator, read only
		rndgCS <= 1;
		else rndgCS <= 0;
	if (cpuAB >= 32'hc000_0000 && cpuAB <= 32'hc0000_0001)				//cycle counter
		cntrCS <= 1;
		else cntrCS <= 0;
end

endmodule
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: Learning Verilog or VHDL from some good books/sources?

Post by ElEctric_EyE »

The bottom still failed, using smartxplorer, with a score of '14', very close to '0'. One usually sees values in the 'thousands' if there is no hope...
So I am accommodating the logic, especially the video space and cycle counter decoding. These would take formulas down to the last bit I would think. I can afford for those resources not to be eaten up!

This passes. My project is nearing max for the XC6SLX9-144:

Code: Select all

...if (cpuAB >= 32'h0000_0000 && cpuAB <= 32'h03ff_03ff) 				//video space, 1024x1024
		vramCS <= 1;
		else vramCS <= 0;
	if (cpuAB == 32'ha000_0000)													//random number generator, read only
		rndgCS <= 1;
		else rndgCS <= 0;
	if (cpuAB >= 32'hc000_0000 && cpuAB <= 32'hcfff_ffff)				//cycle counter
		cntrCS <= 1;
		else cntrCS <= 0;
end...
Post Reply