Verilog只能实现双口RAM的仿真模型,真的双口RAM是hard macro不能用verilog实现的
下面是一个例子,a口写,b口读。记住这只是仿真模型。真正实现是要调用hard macro的
xx是地址位宽
yy是数据位宽
module dual_port_ram(clka, clkb, addra, wr_data, wr_en, addrb, rd_data)
input clka, clkb;
input [(xx-1):0] addra,addrb;
input [(yy-1):0] wr_data;
input wr_en;
output [yy:0] rd_data;
reg [yy:0] ram_data[(xx^2)];
always @ (posedge clka)
if(wr_en)
ram_data[addra] <=wr_data;
always @ (posedge clkb)
rd_data <= ram_data[addrb];
endmodule
我把原理讲诉一下:
1按键1是 按键2和按键3 的启动控制信号
2按键2 与按键3 是互相矛盾的,只有一个会亮
分析,通过状态机实现,
当light2_ctrl ==1时进入light2状态
当light3_ctrl ==1时进入light3状态
然后请看我下面编写的程序
module delay_1s(
clock,
reset_n,
light1_ena,
light1_on
);
paramter MAX_VALUE = 6'd1000;
input clock;
input reset_n;
input light1_ena;//输入light1的启动信号
output light1_on;//经过1s后,给出light1亮灯信号
reg [5:0] counter;
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
counter <= 6'b0;
else if(counter<MAX_VALUE&&counter>6'd1)
counter <= counter + 1'b1;
else if(light1_ena)
counter <= 6'b1;
else
counter <=6'd0;
end
reg light1_on;
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
light1_on <= 1'b0;
else if(counter<=MAX_VALUE)
light1_on<= 1'b1;
end
endmodule
//------------------------------------
module light_ctrl(
clock,
reset_n,
light1_ctrl,
light2_ctrl,
light3_ctrl,
light2_ena,
light3_ena,
time_counter
);
input clock;
input reset_n;//low active
input light1_ctrl;//人按的按键
output light1_ena;//控制灯1亮灭的信号
input light2_ctrl;//人按的按键
output light2_ena;//控制灯1亮灭的信号
input light3_ctrl;//人按的
output light3_ena;//控制灯1亮灭的信号
output [3:0]time_counter; //接 4位的数码管的时间累计值,以clock为基
准的次数
//-----------------------
reg light2_ena;
reg light3_ena;
reg[2:0]curr_state;
reg[2:0]next_state;
reg [3:0]time_counter;
parameter IDLE = 3'b0;
parameter LIGHT1 = 3'b100;
parameter LIGHT2 = 3'b101;
parameter LIGHT3 = 3'b110;
parameter LIGHT_ALL = 3'b111;
//
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
curr_state <= IDLE;
else
curr_state <= next_state;
end
always@()
begin
next_state = curr_state;
case(curr_state)
IDLE:
if(light1_ctrl)
next_state = LIGHT1;
else
next_state = IDLE;
LIGHT1:
begin
case({light3_ctrl,light2_ctrl})
2'b00: next_state= LIGHT1;
2'b10: next_state= LIGHT3;
2'b01: next_state= LIGHT2;
default: next_state= LIGHT_ALL;//LIGHT_ALL
state
endcase
end//LIGHT1
LIGHT2:
begin
next_state= LIGHT2;
end
LIGHT3:
begin
next_state= LIGHT3;
end
LIGHT_ALL:
begin
next_state= LIGHT_ALL;
end
default: next_state = IDLE;
endcase
end
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
light2_ena <= 1'b0;
else
light2_ena <= (curr_state==LIGHT2)|(curr_state==LIGHT_ALL);
end
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
light3_ena <= 1'b0;
else
light3_ena <= (curr_state==LIGHT3)|(curr_state==LIGHT_ALL);
end
always@(posedge clock or negedge reset_n)
begin
if(!reset_n)
time_counter <= 4'b0;
else if(curr_state==LIGHT1)
time_counter <= time_counter + 1'b1;
end
endmodule
//------------------------------------
module light_ctrl_top(
clock,
reset_n,
light1_ctrl,
light2_ctrl,
light3_ctrl,
light1_on,
light2_on,
light3_on,
time_counter
);
input clock;
input reset_n;
input light1_ctrl;
input light2_ctrl;
input light3_ctrl;
output light1_on;
output light2_on;
output light3_on;
output[3:0] time_counter;
//---------------------------
delay_1s u_delay_1s(
clock(clock),
reset_n(reset_n),
light1_ena(light1_ctrl),
light1_on(light1_on)
);
//-----------------------------
light_ctrl u_light_ctrl(
clock(clock),
reset_n(reset_n),
light1_ctrl( light1_on ),
light2_ctrl( light2_ctrl ),
light3_ctrl( light3_ctrl ),
light2_ena(light2_on ),
light3_ena(light2_on ),
time_counter( time_counter)
);
endmodule
每个Verilog程序包括四个主要部分:端口定义、I/O说明、内部信号声明、功能定义。Verilog HDL是一种用于数字逻辑电路设计的语言。用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型。
Verilog HDL既是一种行为描述的语言也是一种结构描述的语言。这也就是说,既可以用电路的功能描述也可以用元器件和它们之间的连接来建立所设计电路的Verilog HDL模型。Verilog模型可以是实际电路的不同级别的抽象。这些抽象的级别和它们对应的模型类型共有以下五种:
1、系统级(system):用高级语言结构实现设计模块的外部性能的模型。
2、算法级(algorithm):用高级语言结构实现设计算法的模型。
3、RTL级(Register Transfer Level):描述数据在寄存器之间流动和如何处理这些数据的模型。
4、门级(gate-level):描述逻辑门以及逻辑门之间的连接的模型。
5、开关级(switch-level):描述器件中三极管和储存节点以及它们之间连接的模型。
扩展资料
一个复杂电路系统的完整Verilog HDL模型是由若干个Verilog HDL模块构成的,每一个模块又可以由若干个子模块构成。其中有些模块需要综合成具体电路,而有些模块只是与用户所设计的模块交互的现存电路或激励信号源。
利用Verilog HDL语言结构所提供的这种功能就可以构造一个模块间的清晰层次结构来描述极其复杂的大型设计,并对所作设计的逻辑电路进行严格的验证。Verilog HDL行为描述语言作为一种结构化和过程性的语言,其语法结构非常适合于算法级和RTL级的模型设计。
Verilog的设计初衷是成为一种基本语法与C语言相近的硬件描述语言。这是因为C语言在Verilog设计之初,已经在许多领域得到广泛应用,C语言的许多语言要素已经被许多人习惯。一种与C语言相似的硬件描述语言,可以让电路设计人员更容易学习和接受。
不过,Verilog与C语言还是存在许多差别。另外,作为一种与普通计算机编程语言不同的硬件描述语言,它还具有一些独特的语言要素,例如向量形式的线网和寄存器、过程中的非阻塞赋值等。总的来说,具备C语言的设计人员将能够很快掌握Verilog硬件描述语言。
参考资料来源:
百度百科——Verilog HDL
下面的代码我已经用modelsim仿真过了,没有问题。
module count(out,clk,rst); //源程序
input clk,rst;
output[3:0] out;
reg[3:0] out;
initial out=4'd0;
always @(posedge clk or negedge rst)
begin
if(!rst) out=4'd0;
else
begin
out=out+4'd1;
if(out==4'd1||out==4'd6||out==4'd8) out=out+4'd1;
if(out==4'd5) out=out+4'd2;
end
end
endmodule
`timescale 1ns/1ns //测试程序
`include "countv"
module count_tp;
reg clk,rst;
wire[3:0] out;
parameter DELY=100;
count mycount(out,clk,rst);
always #(DELY/2) clk=~clk;
initial
begin
clk=0;rst=1;
#(DELY5) rst=0;
#DELY rst=1;
#(DELY20) $finish;
end
initial $monitor($time,,,"clk=%d rst=%d out=%d",clk,rst,out);
endmodule
首先纠正下千年同志的回答:
你的第一点,请看清楚楼主两个always块第一个是grade,第二个是grade1,grade2分别表示个位十位;
第二点:脉冲信号不能做判断条件这句,我拍这胸脯告诉你,绝对可以。。只有你用时序逻辑,在时钟沿检测脉冲信号就可以,只有保证脉冲宽度大于一个时钟周期就绝对能检测到。
第三点:楼主确实有这么点不完善,不过有些时候可以预先确知某些信号同时发生也可以不考虑的。
最后的你建议,先学C再改verilog,个人意见非常不赞同。。很多软件工程师特别喜欢把写软件哦思维带到硬件描述语言中来。。调用个函数啦。。写个for,写个while什么,最后还问为啥综合报错。。。除非你是专门做测试的用systemC或者systemverilog。that's all。
有点偏题了,说楼主的问题:
你的错误:第一点,最明显的地方是 第二个always块里面,你同时用了阻塞赋值和非阻塞赋值语句,这是典型错误。时序逻辑的always块里面都用<=,组合逻辑的always块都用=。
第二,第二个语句中X,Y两个变量的赋值的表达式根本没办法正确综合,一般%这个运算符号只能出现在仿真里(也很少用)除法/只能对2的整数幂进行相除,根本不能除以10,因为这里除法的本质就是除以2^n就等同于讲寄存器的值左移n位;请问这里10等于2的几次幂啊?!
第三个错误,第一个always块,作为组合逻辑,要把所有的敏感变量加进敏感变量列表里,而且组合逻辑你就不用边缘检测posedge 了,直接always@(add or sub or grade)就可以了。
第四个错误。。你的这个组合逻辑的always块,else 语句写在else if 语句前面,这是一种很诡异的写法,能综合个什么东西出来完全想不出来。
所有,我给你的建议是,你这段程序直接推翻重新来写,全部使用标准的时序逻辑的写法,
就是你第二段“always@(posedge clk or negedge RSTn)beign……end”这种写法,它可以保证你的所有电路行为都是发生在时钟上升沿或异步复位下降沿。
其次,每个信号第一if的分支语句一定是要if (!RSTn),即RSTn为低电平时整个加法器复位。这样做的好处在于:由于所有FPGA器件自动上电的瞬间,内部各个信号的初始态都是低电平,可以保证系统有一个自动复位的过程,所有按照这样写的寄存器都会有一个初始态。而避免了不定态X。
最后,建议你四个bit位宽的个位寄存器做成一个模为10的计数器(可以加可以减,具体靠判断sub,add哪一个信号为高)。。每次计数器满时就将十位的那个寄存器加一,而当个位寄存器为零且又检测到sub减信号时,则把个位寄存器置为4‘b1001(9);将十位寄存器也减一;这样就可以实现总累加值从0~99的加减法器了 。
假设din是单bit信号
reg din_ff1;
reg din_ff2;
reg qout;
always @(posedge clk) begin
din_ff1 <= din;
din_ff2 <= din_ff1;
end
always @(posedge clk or negedge clr) begin
if (clr==1'b0)
qout <= 1'b0;
else
qout <= ((din | din_ff1) ^ din_ff2);
end
给你写一个例子,下面是一个设计文件和一个对应的测试程序,希望能起到抛砖引玉的和用:
/
File Name : testv
Author : >
以上就是关于哪位大神有verilog实现的双口RAM例程,就教全部的内容,包括:哪位大神有verilog实现的双口RAM例程,就教、高分求高人相助~一个Verilog程序编写的问题~、每个Verilog HDL程序包括哪4个主要部分等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)