📄 ctrl_ram.v
字号:
// ctrl_RAM.v
/************** ctrl_RAM.v***************************
**模块名称:ctrl_RAM
**功能描述:RAM的读写控制,及发数据到上位机校验
****************************************************/
module ctrl_RAM(key,RI,clk,TI,sendwr,rst,Waddress,Raddress);
//--input------------------------------
input key; //按键输入控制复位信号rst
input RI; //串口接收数据,中断标志位 = 0 表示串口正在接受数据
//------------- 中断标志位 = 1 表示输入数据已经准备好
input clk; //系统同步时钟
input TI; //串口发送数据,TI = 0,表示正在发送数据;
//------------ TI = 1,表示等待发送数据或发送数据完毕;
//--output--------------------------------
output sendwr; //(从RAM读数据后)写数据到发送缓存区的使能标志
output rst; //复位信号,控制RAM的读写使能端WEN,REN
//WEN = 0 写有效; REN = 1 读有效;
output [7:0] Waddress; //写RAM的地址
output [7:0] Raddress; //读RAM的地址
//---参数定义赋值----------------------------
parameter wrcntbit = 8;
parameter rdcntbit = 8;
//--中间变量声明-----------------------------
reg [wrcntbit-1:0] wrcnt; //写数据的位数
reg [rdcntbit-1:0] rdcnt; //读数据的位数
reg [7:0] Waddress;
reg [7:0] Raddress;
reg rst_reg; //复位信号寄存器--
reg rst1,rst2,rst3,rst4,rst5; //
wire key_negedge; //按键的下降沿
reg key_buff; //键值缓存
wire rst_posedge,rst_negedge; //复位信号的两个沿
reg rst_buff; //复位电平缓存--
wire RI_negedge; //接收标志下降沿
reg RI_buff; //接收标志缓存
wire sendclk; //发送时钟
reg [15:0] sendclkdiv; //发送时钟分频计数器
wire TI_posedge; //发送标志上升沿
reg TI_buff; //发送标志缓存
//------------------------------------------
//================================================================
/*下面产生写地址复位信号rst,同时该信号也是
单片机复位信号,存贮器的读写周期指示信号*/
//================================================================
//--锁存键值----------------
always@( posedge clk)
begin
key_buff <= key;
end
assign key_negedge = key_buff & (~key); //取键值的下降沿,该电平的宽度在一个clk周期以内
//--产生复位信号,将琴键开关转换为乒乓开关
//--即保持一个电平输出,直到下一次按键按下
always@(posedge clk)
begin
if(key_negedge)
rst_reg <=~rst_reg;
end
assign rst = rst_reg; //将复位信号赋给输出端口
//=================================================
//下面是写地址处理程序
//=================================================
//--取复位信号下降沿作为电平信号
always@(posedge clk)
begin
rst_buff <= rst_reg;
end
assign rst_negedge = (~rst_reg)&rst_buff; //该电平的宽度在一个clk周期以内
//--取串口接收标志下降沿作为电平信号
always@(posedge clk) //对串口接收标志锁存
begin
RI_buff <= RI;
end
assign RI_negedge = (~RI)&RI_buff; //该电平的宽度在一个clk周期以内
//--控制地址计数逻辑
always@(posedge clk)
begin
if(rst_negedge) //给地址复位
begin
Waddress <= 8'b11111111; //写地址复位,在开始接收第一个数据的时候,
//后面的程序将地址加1,即实现从地址0开始写数据
wrcnt <= 0; //写计数器清零
end
else
if(RI_negedge) //表示串口又开始接收新的数据
begin
Waddress <= Waddress + 8'd1; //RAM地址加1
wrcnt <= wrcnt + 1'b1; //写计数器加1
end
end
//--------------------------------------
//========================================================
//下面是读地址控制程序
//========================================================
always@(posedge clk)
begin
TI_buff <= TI;
end
assign TI_posedge = (TI) & (~TI_buff); //取发送标志的上升沿
assign rst_posedge = rst_reg & (~rst_buff); //取复位信号的上升沿
always@(posedge clk)
begin
if(rst_posedge) //复位信号上升沿
begin
Raddress <= 0; //读读地址清0
rdcnt <= 0; //读计数器清0
end
else
if(TI_posedge) //发送表示上升沿,将读指针指向下一个地址
begin
Raddress <= Raddress+1;
rdcnt <= rdcnt+1'b1; //读计数器加1
end
end
//================================================
//产生发送数据使能信号sendwr,该信号高电平有效
//================================================
assign sendclk = (sendclkdiv == 16'd65535);
always@(posedge clk) //对clk分频
begin
if(sendclk)
sendclkdiv = 0;
else
sendclkdiv = sendclkdiv + 16'd1;
end
//--产生rst延迟5个时钟rst5信号
always@(posedge clk)
begin
rst1 <= rst;
rst2 <= rst1;
rst3 <= rst2;
rst4 <= rst3;
rst5 <= rst4;
end
//--产生sendwr信号,要求读写计数值不相等,
//--若(rdcnt = wrcnt),则表示存储于RAM中的数据已发送完毕
assign sendwr = rst5 & sendclk & ((rdcnt != wrcnt));
//=======================================================
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -