1.原理
通过添加数据文件,使ROM看起来不是易失性存储器,
产生256个数据,每个数据的位宽是8
如果前面为x,后面就是x+256-1
2.单端口ROM配置
FPGA内部没有非易失性存储器。调用的ROM和RAM都是用RAM来生成的
3.双端口ROM配置
使用第一种单时钟
默认不选择使能信号
添加了寄存器,输入时钟可以选择更高的频率
对时钟的使能信号,默认不勾选
是否给寄存器添加清0信号。默认不勾选
4.实验代码
K1按下,给ROM写入一个随机的地址,读取这个地址的数据。K2同理。将读取数据和mif文件对比。
4.1 rom_ctrl.v
module rom_ctrl#(
parameter CNT_MAX=24'd9_999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key1 ,
input wire key2 ,
output reg[7:0] addr
);
reg [23:0]cnt_200ms; //10,000,000个时钟周期,0-9_999_999
reg key1_en ;
reg key2_en ;
always@(sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_200ms<=24'd0;
else if((cnt_200ms==CNT_MAX)||(key1_en==1'b1)||(key2_en==1'b1))
cnt_200ms<=24'd0;
else
cnt_200ms<=cnt_200ms+1'b1;
always@(sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
key1_en<=1'b0;
else if(key2==1'b1)
key1_en<=1'b0;
else if(key1==1'b1)
key1_en<=~key1_en;
else
key1_en<=key1_en;
always@(sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
key2_en<=1'b0;
else if(key2==1'b1)
key2_en<=~key2_en;
else
key2_en<=key2_en;
always@(sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
addr<=8'd0;
else if((cnt_200ms==CNT_MAX)&&(addr==8'd255))
addr<=8'd0;
else if(key1_en==1'b1)
addr<=8'd99;
else if(key2_en==1'b1)
addr<=8'd199;
else if(cnt_200ms==CNT_MAX)
addr<=addr+1'b1;
else
addr<=addr;
endmodule
4.2 tb_rom_ctrl.v
`timescale 1ns/1ns
module tb_rom_ctrl();
reg sys_clk;
reg sys_rst_n;
reg key1;
reg key2;
wire[7:0] addr;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
key1<=1'b0;
key2<=1'b0
#20
sys_rst_n<=1'b1;
#7000 //让数码管完整显示0-255地址,因为一个地址200ns,250*200=500_000
//key1
key1<=1'b1;
#20
key1<=1'b0;
#20000
key1<=1'b1;
#20
key1<=1'b0;
//key2
key2<=1'b1;
#20
key2<=1'b0;
#20000
key2<=1'b1;
#20
key2<=1'b0;
#600000
end
always #10 sys_clk=~sys_clk;
rom_ctrl#(
CNT_MAX=24'd99
)
rom_ctrl_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ),
.key1 (key1 ),
.key2 (key2 ),
.addr (addr )
);
endmodule
4.3
4.3 rom.v
module rom(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key1 ,
input wire key2 ,
output reg ds ,
output reg oe ,
output reg shcp ,
output reg stcp
);
wire key1_flag;
wire key2_flag;
wire [7:0] addr;
wire [7:0] data;
wire [5:0]point ;
wire sign ;
wire seg_en ;
key_filter
#(
.CNT_MAX(20'd999_999)
)
key_filter_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.key_in (key1 ) ,
.key_flag (key1_flag )
);
key_filter
#(
.CNT_MAX(20'd999_999)
)
key_filter_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.key_in (key2 ) ,
.key_flag (key2_flag )
);
rom_ctrl#(
.CNT_MAX(24'd9_999_999)
)
rom_ctrl_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ),
.key1 (key1_flag ),
.key2 (key2_flag ),
.addr (addr )
);
rom_8x256 rom_8x256_inst
(
.address (addr),
.clock (sys_clk),
.q (data)
);
seg_595_dynamic seg_595_dynamic_inst(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.data ({12'b0,data} ,
.point (6'b000_000 ) ,
.sign (1'b0 ) ,
.seg_en (1'b1 ) ,
.ds (ds ) ,
.oe (oe ) ,
.shcp (shcp ) ,
.stcp (stcp )
);
endmodule
4.4 tb_rom.v
`timescale 1ns/1ns
module tb_rom();
reg sys_clk ;
reg sys_rst_n ;
reg key1 ;
reg key2 ;
wire ds ;
wire oe ;
wire shcp ;
wire stcp ;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
key1<=1'b1;
key2<=1'b1;
#20
sys_rst_n<=1'b1;
#7000 //让数码管完整显示0-255地址,因为一个地址200ns,250*200=500_000
//key1
key1<=1'b0;
#20
key1<=1'b1;
#20
key1<=1'b0;
#20
key1<=1'b1;
#20
key1<=1'b0;
#200
key1<=1'b1;
#20
key1<=1'b0;
#20
key1<=1'b1;
#20
key1<=1'b0;
#20
key1<=1'b1;
//key2
#2000
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#200
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
//key2
#2000
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#200
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
#20
key2<=1'b0;
#20
key2<=1'b1;
end
always #10 sys_clk=~sys_clk;
rom rom_inst(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.key1 (key1 ),
.key2 (key2 ),
.ds (ds ),
.oe (oe ),
.shcp (shcp ),
.stcp (stcp )
);
endmodule