We learn VHDL in academics. Engg. education is not just about learning from acads, its about applying the knowledge and leverage what you learnt.
Few years back, when I 1st learnt VHDL, i preferred C over it, any day. That is, till VHDL demonstrated its potential to me. Now when I make this transition from VHDL to Verilog, the story repeats itself. I prefer VHDL over Verilog :) At least I dont have to bother about syncing with things that are sensitive to an edge + a level.
My 1st Verilog.. a FIFO that goes between processor and the interface, to temporarily buffer the data till the interface send it across. Inspired from Net + my own learning from errors additions.
http://asic-world.com/examples/verilog/syn_fifo.html#Synchronous_FIFO
`timescale 1ns / 1ps
module fifo(
proc_input,
data_in,
ready,
clk, rst, done, wr_data,
empty,
full
);
output [15:0] data_in;
output ready, empty, full;
input [15:0] proc_input;
input clk, rst, done, wr_data;
// ram = 2 ^ addr_width * 16 bit wide
parameter ADDR_WIDTH = 4;
parameter RAM_DEPTH = (1 << ADDR_WIDTH); // 2 ^addr_width
parameter WORD_LENGTH = 16;
//-----------Internal variables-------------------
reg [ADDR_WIDTH-1:0] wr_ptr;
reg [ADDR_WIDTH-1:0] rd_ptr;
reg [ADDR_WIDTH :0] count;
reg [15:0] data_in; //if not initialized, it will be trimmed during optimization
reg ready; // otherwise while assigning you get error: Reference to scalar wire 'ready' is not a legal reg or variable lvalue
reg [WORD_LENGTH-1:0] mem [0:RAM_DEPTH-1];
assign full = (count == (RAM_DEPTH-1));
assign empty = (count == 0);
always @ (posedge clk or posedge rst) //cant have 1 posedge and non-edge triggered in sensi list
begin : WRITE
if (rst)
wr_ptr <= 0;
else if(wr_data && (count != RAM_DEPTH-1)) //not full
begin
wr_ptr <= wr_ptr + 1; //latch implied due to incomplete if
end
end
always @ (posedge done or posedge rst)
begin : READ_POINTER
if (rst) begin
rd_ptr <= 0;
end else if (done && (count!=0)) begin
rd_ptr <= rd_ptr + 1;
end
end
// check if no need of done in if condition
//Xst:2111 - Clock of counter <rd_ptr> seems to be also used in the data or control logic of that element.
// the compiler wants count, rd_ptr and mem in the sensitivity list..shouldnt be used
always @ (done, rst)
begin : READ_DATA
if (rst) begin
data_in <= 0; //data_in is a register. one cant write data directly to port
ready <= 0;
end else if (done && (count!=0)) begin //check trigger on done
data_in <= mem[rd_ptr];
ready <= 1;
end else begin
data_in <= 0; //to prevent latch on data_in. //should have been high z, but dunno how to represent that
ready <= 0;
end
end
always @ (posedge clk or posedge rst)
begin : COUNTER
if (rst)
count <= 0;
else if (done && (count != 0))
count <= count - 1;
else if (wr_data && (count != RAM_DEPTH))
count <= count + 1;
end
//logically read and write can occur in parallel
//but without "else if" we get error that logic doesnt match FF template
always @ (wr_ptr, proc_input, wr_data)
begin
if (wr_data)
mem[wr_ptr] <= proc_input; //again a data_width size latch on mem_0 to mem_ram depth
end
endmodule
Notes: working mostly, yet to check corner cases..empty and full stuff
Have to check post-synthesis simulation..because of warnings that some signals may be trimmed..I dont want that to happen!!
2) Top level module: the code that made the chip..
contains modifications from the code published on the blog..
https://docs.google.com/document/d/1dOrttZW5EQFiEWcgUszROuMYu9jLKAuesl3KUhRyPsE/edit
Few years back, when I 1st learnt VHDL, i preferred C over it, any day. That is, till VHDL demonstrated its potential to me. Now when I make this transition from VHDL to Verilog, the story repeats itself. I prefer VHDL over Verilog :) At least I dont have to bother about syncing with things that are sensitive to an edge + a level.
My 1st Verilog.. a FIFO that goes between processor and the interface, to temporarily buffer the data till the interface send it across. Inspired from Net + my own learning from errors additions.
http://asic-world.com/examples/verilog/syn_fifo.html#Synchronous_FIFO
`timescale 1ns / 1ps
module fifo(
proc_input,
data_in,
ready,
clk, rst, done, wr_data,
empty,
full
);
output [15:0] data_in;
output ready, empty, full;
input [15:0] proc_input;
input clk, rst, done, wr_data;
// ram = 2 ^ addr_width * 16 bit wide
parameter ADDR_WIDTH = 4;
parameter RAM_DEPTH = (1 << ADDR_WIDTH); // 2 ^addr_width
parameter WORD_LENGTH = 16;
//-----------Internal variables-------------------
reg [ADDR_WIDTH-1:0] wr_ptr;
reg [ADDR_WIDTH-1:0] rd_ptr;
reg [ADDR_WIDTH :0] count;
reg [15:0] data_in; //if not initialized, it will be trimmed during optimization
reg ready; // otherwise while assigning you get error: Reference to scalar wire 'ready' is not a legal reg or variable lvalue
reg [WORD_LENGTH-1:0] mem [0:RAM_DEPTH-1];
assign full = (count == (RAM_DEPTH-1));
assign empty = (count == 0);
always @ (posedge clk or posedge rst) //cant have 1 posedge and non-edge triggered in sensi list
begin : WRITE
if (rst)
wr_ptr <= 0;
else if(wr_data && (count != RAM_DEPTH-1)) //not full
begin
wr_ptr <= wr_ptr + 1; //latch implied due to incomplete if
end
end
always @ (posedge done or posedge rst)
begin : READ_POINTER
if (rst) begin
rd_ptr <= 0;
end else if (done && (count!=0)) begin
rd_ptr <= rd_ptr + 1;
end
end
// check if no need of done in if condition
//Xst:2111 - Clock of counter <rd_ptr> seems to be also used in the data or control logic of that element.
// the compiler wants count, rd_ptr and mem in the sensitivity list..shouldnt be used
always @ (done, rst)
begin : READ_DATA
if (rst) begin
data_in <= 0; //data_in is a register. one cant write data directly to port
ready <= 0;
end else if (done && (count!=0)) begin //check trigger on done
data_in <= mem[rd_ptr];
ready <= 1;
end else begin
data_in <= 0; //to prevent latch on data_in. //should have been high z, but dunno how to represent that
ready <= 0;
end
end
always @ (posedge clk or posedge rst)
begin : COUNTER
if (rst)
count <= 0;
else if (done && (count != 0))
count <= count - 1;
else if (wr_data && (count != RAM_DEPTH))
count <= count + 1;
end
//logically read and write can occur in parallel
//but without "else if" we get error that logic doesnt match FF template
always @ (wr_ptr, proc_input, wr_data)
begin
if (wr_data)
mem[wr_ptr] <= proc_input; //again a data_width size latch on mem_0 to mem_ram depth
end
endmodule
Notes: working mostly, yet to check corner cases..empty and full stuff
Have to check post-synthesis simulation..because of warnings that some signals may be trimmed..I dont want that to happen!!
2) Top level module: the code that made the chip..
contains modifications from the code published on the blog..
https://docs.google.com/document/d/1dOrttZW5EQFiEWcgUszROuMYu9jLKAuesl3KUhRyPsE/edit
Structural module:
ReplyDeletefsm_veri_try1 FSM(
.clk (clk),
.rst (rst),
.ready (connect_ready),
.rs_in (rs_in),
.asu (asu),
.dsu (dsu),
.ahold (ahold),
.dhold (dhold),
.en_active (en_active),
.en_deactive (en_deactive),
.data_in (connect_data_in),
.dbus (dbus),
.rs (rs),
.CSb (CSb),
.en (en),
.done (connect_done)
);
fifo FIFO(
.proc_input (proc_input),
.data_in (connect_data_in),
.ready (connect_ready),
.clk (clk),
.rst (clk),
.done (connect_done),
.wr_data (wr_data),
.empty (empty),
.full (full)
);
Hi, my name is Michail, and I am from Moscow, doing electronics as a hobby. Probably I am stupid, but wasn't able to find any contacts of you :-) Just wanted to chat a bit. Drop me a message to 3@14.by if you wish.
ReplyDelete