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;elsecnt_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;elsekey2_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;elseaddr<=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 beginsys_clk=1'b1;sys_rst_n<=1'b0;key1<=1'b0;key2<=1'b0#20sys_rst_n<=1'b1;#7000 //让数码管完整显示0-255地址,因为一个地址200ns,250*200=500_000//key1key1<=1'b1;#20key1<=1'b0;#20000key1<=1'b1;#20key1<=1'b0;//key2key2<=1'b1;#20key2<=1'b0;#20000key2<=1'b1;#20key2<=1'b0;#600000endalways #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 beginsys_clk=1'b1;sys_rst_n<=1'b0;key1<=1'b1;key2<=1'b1;#20sys_rst_n<=1'b1;#7000 //让数码管完整显示0-255地址,因为一个地址200ns,250*200=500_000
//key1key1<=1'b0;#20key1<=1'b1;#20key1<=1'b0;#20key1<=1'b1;#20key1<=1'b0;#200key1<=1'b1;#20key1<=1'b0;#20key1<=1'b1;#20key1<=1'b0;#20key1<=1'b1;
//key2#2000key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#200key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;
//key2#2000key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#200key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;#20key2<=1'b0;#20key2<=1'b1;endalways #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