1.原理图,这次的协议是7*55/d5/aa(擦出flash)55(在flash中写入数据)。因此frame的控制模块至关重要。
2.仿真结果
这是仿真的frame控制模过滤协议之后产生的擦除地址与标志位,图中可以看出能够产生。
这是flash的擦除模块,这是flash模块中的扇区自动加一,这次擦除了8个扇区。
这是擦除完成的标志位,回传55表示擦除完成。
这是仿真在协议模块中过滤协议之后,产生写的地址、写地址标志位、写数据以及写数据的标志位。
通过观察flash的写控制模块可以发现flash可以写入相应的数据。
通过观察uart的tx模块端,结束标志位产生后,可以回传aa(16进制)
3.这次大综合需要用到的模块uart的rx模块和tx模块、flash的擦除模块和写入模块、按键消抖和icapIP核模块以及利用top模块将所有模块综合。
module rx_crtl(
input wire sclk,
input wire rst_n,
input wire rx_in,
output reg stop_flag, //新增数据监测停止位
output reg flag_o,
output reg [7:0] data_o
);
reg [12:0] cnt;
reg [3:0] bit_cnt;
reg rx_in_1,rx_in_2;
reg rx_en; //使能信号值有问题
reg bit_flag;
reg [7:0]tmp_data;
reg tmp_flag;
reg [16:0] cnt_clean;
parameter CNT_CLEAN=100000;//28888; 仿真多写1个4
parameter CNT=5207;
parameter BIT_CNT=8;
parameter bit_flag_cnt=2603; // 产生bit采集标志位
//parameter clean_flag=2610;
always@(posedge sclk or negedge rst_n) //ram输入信号清零计数器
if(!rst_n)
cnt_clean<=16'd0;
else if(flag_o==1'b1) // 少写了清零条件,导致写地址一直处于清零状态
cnt_clean<=16'd0;
else if(cnt_clean==CNT_CLEAN)
cnt_clean<=cnt_clean; // 优先级,当时产生清零标志位没有保持,而是清零导致产生无数个终端位
else if(flag_o==1'b0) //flag_o==1'b1,当时想的就是拉高开始计数,结果发现根本不计数
cnt_clean<=cnt_clean+1'b1; //因为标志位拉高只有一个时钟周期,应该记拉低的时钟周期。
always@(posedge sclk or negedge rst_n) //数据清零位传递给帧协议
if(!rst_n)
stop_flag<=1'b0;
else if (cnt_clean==CNT_CLEAN-1)
stop_flag<=1'b1;
else stop_flag<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
rx_in_1<=1'b1;
else rx_in_1<=rx_in;
always@(posedge sclk or negedge rst_n) //输入信号延时
if(!rst_n)
rx_in_2<=1'b1;
else rx_in_2<=rx_in_1;
always@(posedge sclk or negedge rst_n) //产生计数使能信号
if(!rst_n)
rx_en<=1'b0;
else if(rx_in_1==1'b0&&rx_in_2==1'b1)
rx_en<=1'b1;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
rx_en<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=13'd0;
else if(rx_en==1'b0)
cnt<=13'd0;
else if(cnt==CNT)
cnt<=13'd0;
else if(rx_en==1'b1)
cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n) //位宽计数
if(!rst_n)
bit_cnt<=4'd0;
else if(rx_en==1'b0)
bit_cnt<=4'd0;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
bit_cnt<=4'd0;
else if(cnt==CNT)
bit_cnt<=bit_cnt+1'b1;
always@(posedge sclk or negedge rst_n) //产生bit标志位
if(!rst_n)
bit_flag<=1'b0;
else if(cnt==bit_flag_cnt)
bit_flag<=1'b1;
else bit_flag<=1'b0;
always@(posedge sclk or negedge rst_n) //数据拼接
if(!rst_n)
tmp_data<=8'd0;
else if(bit_flag==1'b1&&bit_cnt>=4'd1&&bit_cnt<=4'd8)
tmp_data<={rx_in_2,tmp_data[7:1]}; //少写分号
//else if(bit_cnt==BIT_CNT&&cnt==clean_flag) 数据不清零条件
// tmp_data<=8'd0;
always@(posedge sclk or negedge rst_n) //数据拼接完成标志
if(!rst_n)
tmp_flag<=1'b0;
else if(bit_flag==1'b1&&bit_cnt==BIT_CNT)
tmp_flag<=1'b1;
else tmp_flag<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
data_o<=8'd0;
else if(tmp_flag==1'b1)
data_o<=tmp_data;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
flag_o<=1'b0;
else flag_o<=tmp_flag;
endmodule
module w_farme(
input wire sclk,
input wire rst_n,
input wire flag_uart,
input wire [7:0] data_uart,
input wire stop_flag, //数据发送完成标志
input wire sen_stop_flag, //擦除完成标识
output reg wr_flag,
output reg [23:0] wr_addr,
output reg [7:0] wr_data,
output reg wr_flag_dizhi,
output reg [23:0] se_addr,
output reg se_flag,
output reg tx_flag,
output reg [7:0] tx_data //擦除结束用55标志,发生完成用aa标识
);
reg [10:0] state;
parameter IDLE =11'b00000_0000_01;
parameter H_1_55 =11'b00000_0000_10;
parameter H_2_55 =11'b00000_0001_00;
parameter H_3_55 =11'b00000_0010_00;
parameter H_4_55 =11'b00000_0100_00;
parameter H_5_55 =11'b00000_1000_00;
parameter H_6_55 =11'b00001_0000_00;
parameter H_7_55 =11'b00010_0000_00;
parameter H_d5 =11'b00100_0000_00;
parameter H_se =11'b01000_0000_00;
parameter H_wr =11'b10000_0000_00;
reg [2:0] cnt_flag;
reg [23:0] tmp_addr;
reg [2:0] cnt_flag_wr;
reg [23:0] tmp_addr_wr;
reg flag_uart_dely;
reg flag_uart_dely1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
state<=IDLE;
//else if(stop_flag==1'b1)
// state<=idle;
else if(flag_uart==1'b1)
case(state)
IDLE : if(data_uart==8'h55)
state<=H_1_55;
else state<=IDLE;
H_1_55: if(data_uart==8'h55)
state<=H_2_55;
else state<=IDLE;
H_2_55: if(data_uart==8'h55)
state<=H_3_55;
else state<=IDLE;
H_3_55: if(data_uart==8'h55)
state<=H_4_55;
else state<=IDLE;
H_4_55: if(data_uart==8'h55)
state<=H_5_55;
else state<=IDLE;
H_5_55: if(data_uart==8'h55)
state<=H_6_55;
else state<=IDLE;
H_6_55: if(data_uart==8'h55)
state<=H_7_55;
else state<=IDLE;
H_7_55: if(data_uart==8'hd5)
state<=H_d5;
else state<=IDLE;
H_d5: if(data_uart==8'haa)
state<=H_se;
else if(data_uart==8'h55)
state<=H_wr;
else state<=IDLE;
H_se: if(sen_stop_flag==1)
state<=IDLE;
else state<=state;
H_wr: if(stop_flag==1)
state<=IDLE;
else state<=state;
default:;
endcase
always@(posedge sclk or negedge rst_n)
if(!rst_n)
flag_uart_dely<=0;
else flag_uart_dely<=flag_uart;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
flag_uart_dely1<=0;
else flag_uart_dely1<=flag_uart_dely;
always@(posedge sclk or negedge rst_n) //产生读计数器,对输入的标志位计数
if(!rst_n)
cnt_flag<=2'd0;
else if(sen_stop_flag==1)
cnt_flag<=2'd0;
else if(cnt_flag==5)
cnt_flag<=cnt_flag;
else if(state==H_se&&flag_uart_dely==1)
cnt_flag<=cnt_flag+1;
always@(posedge sclk or negedge rst_n) //读地址拼接——目前不确定要不要清零
if(!rst_n)
tmp_addr<=24'd0;
else if(state==H_se&&flag_uart==1&&cnt_flag<=3)
tmp_addr<={tmp_addr[15:0],data_uart};
always@(posedge sclk or negedge rst_n) //地址发送
if(!rst_n)
se_addr<=24'd0;
else se_addr<=tmp_addr;
always@(posedge sclk or negedge rst_n) //清除标志位产生
if(!rst_n)
se_flag<=0;
else if(cnt_flag==4)
se_flag<=flag_uart_dely1;
else se_flag<=0;
always@(posedge sclk or negedge rst_n) //产生写计数器,对输入的标志位计数
if(!rst_n)
cnt_flag_wr<=2'd0;
else if(stop_flag==1)
cnt_flag_wr<=2'd0;
else if(cnt_flag_wr==5)
cnt_flag_wr<=cnt_flag_wr;
else if(state==H_wr&&flag_uart_dely==1)
cnt_flag_wr<=cnt_flag_wr+1;
always@(posedge sclk or negedge rst_n) //写地址拼接——目前不确定要不要清零wr_flag_dizhi
if(!rst_n)
tmp_addr_wr<=24'd0;
else if(state==H_wr&&flag_uart==1&&cnt_flag_wr<=3)
tmp_addr_wr<={tmp_addr_wr[15:0],data_uart};
always@(posedge sclk or negedge rst_n) //写地址拼接——目前不确定要不要清零wr_flag_dizhi
if(!rst_n)
wr_flag_dizhi<=0;
else if(cnt_flag_wr==4)
wr_flag_dizhi<=flag_uart_dely;
else wr_flag_dizhi<=0;
always@(posedge sclk or negedge rst_n) //地址发送
if(!rst_n)
wr_addr<=24'd0;
else wr_addr<=tmp_addr_wr;
always@(posedge sclk or negedge rst_n) //数据发送标志位产生
if(!rst_n)
wr_flag<=0;
else if(cnt_flag_wr>=5)
wr_flag<=flag_uart_dely1;
else wr_flag<=0;
always@(posedge sclk or negedge rst_n) //写的数据打拍
if(!rst_n)
wr_data<=8'd0;
else if(cnt_flag_wr==5)
wr_data<=data_uart;
else if(stop_flag==1)
wr_data<=8'd0;
always@(posedge sclk or negedge rst_n) //回传数据标志位
if(!rst_n)
tx_flag<=0;
else if(sen_stop_flag==1)
tx_flag<=1;
else if(stop_flag==1&&state==H_wr)
tx_flag<=1;
else tx_flag<=0;
always@(posedge sclk or negedge rst_n) //回传数据
if(!rst_n)
tx_data<=8'd0;
else if(sen_stop_flag==1)
tx_data<=8'h55;
else if(stop_flag==1)
tx_data<=8'haa;
else tx_data<=8'd0;
endmodule
/***************************
spi协议控制flash扇区擦除
****************************/
module flash_ctrl_se(
input wire sclk,
input wire rst_n,
input wire pi_se_flag,
input wire [23:0] se_addr_in,
output reg led,
output reg cs_n,
output reg sck,
output reg sdi,
output reg sent_flag_out //地址清零结束位
);
reg [9:0] state;
parameter idle =10'b0000_0000_01;
parameter WAIT1 =10'b0000_0000_10;
parameter WRITE =10'b0000_0001_00;
parameter WAIT2 =10'b0000_0010_00;
parameter WAIT3 =10'b0000_0100_00;
parameter WAIT4 =10'b0000_1000_00;
parameter SE =10'b0001_0000_00;
parameter INIT_ADDR =10'b0010_0000_00;
parameter WAIT5 =10'b0100_0000_00;
parameter WAIT_3S =10'b1000_0000_00;
reg [4:0] sclk_cnt;
parameter SCLK_CNT=31;
reg [1:0] cnt_init_addr;
reg [25:0] cnt_1s;
parameter ONE_S=49_9999_99;
reg [1:0] cnt_3s;
reg [1:0] cnt4;
reg [2:0] bit_cnt;
reg [3:0] cnt_wait_3s;
reg [23:0] init_addr;
parameter wr_en=8'h06; //信号差了一个时钟周期
parameter se_en=8'hd8;
parameter CNT_wait_3s=7;
reg cnt_3s_en;
always@(posedge sclk or negedge rst_n) //循环擦除
if(!rst_n)
cnt_wait_3s<=3'd0;
else if(cnt_wait_3s==CNT_wait_3s&&cnt_1s==ONE_S&&cnt_3s==2)
cnt_wait_3s<=3'd0;
else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2)
cnt_wait_3s<=cnt_wait_3s+1'b1;
always@(posedge sclk or negedge rst_n) //扇区地址变换
if(!rst_n)
init_addr<=24'd0;
else if(pi_se_flag==1)
init_addr<=se_addr_in;
else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2) /////
init_addr<=init_addr+24'h01_0000;
else if(state==idle)
init_addr<=24'd0;
always@(posedge sclk or negedge rst_n) //为输出时钟计数
if(!rst_n)
cnt4<=2'd0;
else if(cnt4==3)
cnt4<=2'd0;
else if(state==WRITE||state==SE||state==INIT_ADDR)
cnt4<=cnt4+1;
always@(posedge sclk or negedge rst_n) // bit位计数
if(!rst_n)
bit_cnt<=3'd0;
else if(bit_cnt==7&&cnt4==3)
bit_cnt<=3'd0;
else if(cnt4==3)
bit_cnt<=bit_cnt+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt_1s<=26'd0;
else if(cnt_1s==ONE_S)
cnt_1s<=26'd0;
else if(cnt_3s_en==1)
cnt_1s<=cnt_1s+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt_3s<=2'd0;
else if(cnt_1s==ONE_S&&cnt_3s==2)
cnt_3s<=2'd0;
else if(cnt_1s==ONE_S)
cnt_3s<=cnt_3s+1;
always@(posedge sclk or negedge rst_n) //3秒使能信号
if(!rst_n)
cnt_3s_en<=0;
else if(cnt_1s==ONE_S&&cnt_3s==2)
cnt_3s_en<=0;
else if(state==WAIT_3S)
cnt_3s_en<=1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cs_n<=1;
else if(pi_se_flag==1)
cs_n<=0;
else if(state==idle)
cs_n<=1;
else if(state==WAIT2&&sclk_cnt==SCLK_CNT) //片选信号没有描述对
cs_n<=1;
else if(state==WAIT3&&sclk_cnt==SCLK_CNT)
cs_n<=0;
else if(state==WAIT5&&sclk_cnt==SCLK_CNT)
cs_n<=1;
else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2)
cs_n<=0;
//else if(cnt_wait_3s==CNT_wait_3s)
//cs_n<=1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
sclk_cnt<=5'd0;
else if (sclk_cnt==SCLK_CNT&&cnt_wait_3s==CNT_wait_3s)
sclk_cnt<=5'd0;
else if(sclk_cnt==SCLK_CNT)
sclk_cnt<=5'd0;
else if(cs_n==0)
sclk_cnt<=sclk_cnt+1;
else if(state==WAIT3)
sclk_cnt<=sclk_cnt+1;
always@(posedge sclk or negedge rst_n) //3位状态计数
if(!rst_n)
cnt_init_addr<=2'd0;
else if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT)
cnt_init_addr<=2'd0;
else if(sclk_cnt==SCLK_CNT&&state==INIT_ADDR)
cnt_init_addr<=cnt_init_addr+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
state<=idle;
else case(state)
idle: if(pi_se_flag==1)
state<=WAIT1;
else state<=idle;
WAIT1: if(sclk_cnt==SCLK_CNT)
state<=WRITE;
else state<=WAIT1;
WRITE: if(sclk_cnt==SCLK_CNT)
state<=WAIT2;
else state<=WRITE;
WAIT2: if(sclk_cnt==SCLK_CNT)
state<=WAIT3;
else state<=WAIT2;
WAIT3: if(sclk_cnt==SCLK_CNT)
state<=WAIT4;
else state<=WAIT3;
WAIT4: if(sclk_cnt==SCLK_CNT)
state<=SE;
SE: if(sclk_cnt==SCLK_CNT)
state<=INIT_ADDR;
else state<=SE;
INIT_ADDR: if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT)
state<=WAIT5;
else state<=INIT_ADDR;
WAIT5: if(sclk_cnt==SCLK_CNT)
state<=WAIT_3S;
else state<=WAIT5;
WAIT_3S: if(cnt_1s==ONE_S&&cnt_3s==2)
state<=WAIT1;
else if(cnt_wait_3s==CNT_wait_3s)
state<=idle;
default: state<=idle;
endcase
always@(posedge sclk or negedge rst_n) //时钟传递
if(!rst_n)
sck<=0;
else if(state==WRITE &&cnt4==1)
sck<=1;
else if(state==WRITE&&cnt4==3)
sck<=0;
else if (state==SE&&cnt4==1)
sck<=1;
else if(state==SE&&cnt4==3)
sck<=0;
else if (state==INIT_ADDR&&cnt4==1)
sck<=1;
else if(state==INIT_ADDR&&cnt4==3)
sck<=0;
always@(posedge sclk or negedge rst_n) //低电平传输数据 上升沿采集数据
if(!rst_n)
sdi<=1'b1;
else if(state==WRITE)
sdi<=wr_en[7-bit_cnt];
else if(state==SE)
sdi<=se_en[7-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==0)
sdi<=init_addr[23-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==1)
sdi<=init_addr[15-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==2)
sdi<=init_addr[7-bit_cnt];
else sdi<=1'b1; //检查发现有问题
always@(posedge sclk or negedge rst_n)
if(!rst_n)
led<=0;
else if(cnt_3s_en==1)
led<=1;
else led<=0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
sent_flag_out<=0;
else if(cnt_wait_3s==CNT_wait_3s&&cnt_1s==ONE_S&&cnt_3s==2)
sent_flag_out<=1;
else sent_flag_out<=0;
endmodule
/***************************
spi协议控制flash扇区数据输入
****************************/
module flash_ctrl_wr(
input wire sclk,
input wire rst_n,
input wire pi_flag,
input wire pi_flag_dizhi,
input wire [7:0] data_in,
input wire stop_flag_rx, //发送端输入的停止位
input wire [23:0] frame_wr_addr,
output reg cs_n,
output reg sck,
output reg sdi
);
reg [9:0] state;
parameter idle =10'b0000_0000_01;
parameter WAIT1 =10'b0000_0000_10;
parameter WRITE =10'b0000_0001_00;
parameter WAIT2 =10'b0000_0010_00;
parameter WAIT3 =10'b0000_0100_00;
parameter WAIT4 =10'b0000_1000_00;
parameter PP =10'b0001_0000_00;
parameter INIT_ADDR =10'b0010_0000_00;
parameter DATA_IN =10'b0100_0000_00;
parameter WAIT5 =10'b1000_0000_00;
reg [4:0] sclk_cnt;
parameter SCLK_CNT=31;
reg [1:0] cnt_init_addr;
reg [1:0] cnt4;
reg [2:0] bit_cnt;
reg add_addr_flag;
reg [23:0] init_addr;
parameter INIT_ADDR_Location=6'h00_00_00;
parameter wr_en=8'h06;
parameter PP_en=8'h02;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
add_addr_flag<=0;
else if(state==WAIT5&&sclk_cnt==SCLK_CNT)
add_addr_flag<=1;
else add_addr_flag<=0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
init_addr<=INIT_ADDR_Location;
else if(pi_flag_dizhi==1)
init_addr<=frame_wr_addr;
else if(add_addr_flag==1)
init_addr<=init_addr+24'h0000_01; //字节自动加一,加到255后页自动加一
//else init_addr<=24'd0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt4<=2'd0;
else if(cnt4==3)
cnt4<=2'd0;
else if(state==WRITE||state==PP||state==INIT_ADDR||state==DATA_IN)
cnt4<=cnt4+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
bit_cnt<=3'd0;
else if(bit_cnt==7&&cnt4==3)
bit_cnt<=3'd0;
else if(cnt4==3)
bit_cnt<=bit_cnt+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cs_n<=1;
else if(pi_flag==1)
cs_n<=0;
else if(state==WAIT2&&sclk_cnt==SCLK_CNT)
cs_n<=1;
else if(state==WAIT3&&sclk_cnt==SCLK_CNT)
cs_n<=0;
else if(sclk_cnt==SCLK_CNT&&state==WAIT5)
cs_n<=1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
sclk_cnt<=5'd0;
else if (sclk_cnt==SCLK_CNT&&state==WAIT5)
sclk_cnt<=5'd0;
else if(sclk_cnt==SCLK_CNT)
sclk_cnt<=5'd0;
else if(cs_n==0)
sclk_cnt<=sclk_cnt+1;
else if(state==WAIT3)
sclk_cnt<=sclk_cnt+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt_init_addr<=2'd0;
else if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT)
cnt_init_addr<=2'd0;
else if(sclk_cnt==SCLK_CNT&&state==INIT_ADDR)
cnt_init_addr<=cnt_init_addr+1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
state<=idle;
else case(state)
idle: if(pi_flag==1)
state<=WAIT1;
else state<=idle;
WAIT1: if(sclk_cnt==SCLK_CNT)
state<=WRITE;
else state<=WAIT1;
WRITE: if(sclk_cnt==SCLK_CNT)
state<=WAIT2;
else state<=WRITE;
WAIT2: if(sclk_cnt==SCLK_CNT)
state<=WAIT3;
else state<=WAIT2;
WAIT3: if(sclk_cnt==SCLK_CNT)
state<=WAIT4;
else state<=WAIT3;
WAIT4: if(sclk_cnt==SCLK_CNT)
state<=PP;
PP: if(sclk_cnt==SCLK_CNT)
state<=INIT_ADDR;
else state<=PP;
INIT_ADDR: if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT)
state<=DATA_IN;
else state<=INIT_ADDR;
DATA_IN: if(sclk_cnt==SCLK_CNT)
state<=WAIT5;
else state<=DATA_IN;
WAIT5: if(stop_flag_rx)
state<=idle;
else if(sclk_cnt==SCLK_CNT)
state<=idle;
else state<=WAIT5;
default: state<=idle;
endcase
always@(posedge sclk or negedge rst_n) //时钟传递
if(!rst_n)
sck<=0;
else if(state==WRITE &&cnt4==1)
sck<=1;
else if(state==WRITE&&cnt4==3)
sck<=0;
else if (state==PP&&cnt4==1)
sck<=1;
else if(state==PP&&cnt4==3)
sck<=0;
else if (state==INIT_ADDR&&cnt4==1)
sck<=1;
else if(state==INIT_ADDR&&cnt4==3)
sck<=0;
else if (state==DATA_IN&&cnt4==1)
sck<=1;
else if(state==DATA_IN&&cnt4==3)
sck<=0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
sdi<=1'b1;
else if(state==WRITE)
sdi<=wr_en[7-bit_cnt];
else if(state==PP)
sdi<=PP_en[7-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==0)
sdi<=init_addr[23-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==1)
sdi<=init_addr[15-bit_cnt];
else if(state==INIT_ADDR&&cnt_init_addr==2)
sdi<=init_addr[7-bit_cnt];
else if(state==DATA_IN)
sdi<=data_in[7-bit_cnt];
else sdi<=1'b1;
endmodule
module key_rock(
input wire sclk,
input wire rst_n,
input wire key_in,
output reg key_o
);
reg [18:0] cnt;
parameter CNT_MAX=500000-1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=1'b0;
else if(key_in==1)
cnt<=0;
else if(cnt==CNT_MAX)
cnt<=cnt;
else
cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
key_o<=1'b0;
else if (cnt==CNT_MAX-1)
key_o<=1'b1;
else
key_o<=1'b0;
endmodule
module icap_ctrl(
input wire sclk,
input wire rst_n,
input wire key_in,
input wire [23:0] wr_addr_frame
);
reg [3:0] cnt;
reg ce;
reg [15:0] tmp_i;
wire [15:0] i_data;
always@(posedge sclk or negedge rst_n) //cnt14
if(!rst_n)
cnt<=4'd0;
else if(cnt==14)
cnt<=4'd0;
else if (ce==0)
cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n) //ce
if(!rst_n)
ce<=1'b1;
else if(cnt==14)
ce<=1'b1;
else if (key_in==1) //不是很理解
ce<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
tmp_i<=16'hffff;
else case(cnt)
0: tmp_i<=16'hffff;
1: tmp_i<=16'haa99;
2: tmp_i<=16'h5566;
3: tmp_i<=16'h3261;
4: tmp_i<=wr_addr_frame[15:0]; //{data_uart,tmp_addr[7:0]};
5: tmp_i<=16'h3281;
6: tmp_i<={8'h03,wr_addr_frame[23:16]};//
7: tmp_i<=16'h32a1;
8: tmp_i<=16'h0000; //
9: tmp_i<=16'h32c1;
10: tmp_i<=16'h0300; //
11: tmp_i<=16'h30a1;
12: tmp_i<=16'h000e;
13: tmp_i<=16'h2000;
14: tmp_i<=16'hffff;
default: tmp_i<=16'hffff;
endcase
assign i_data={tmp_i[8],tmp_i[9],tmp_i[10],tmp_i[11],tmp_i[12],tmp_i[13],tmp_i[14],tmp_i[15],
tmp_i[0],tmp_i[1],tmp_i[2],tmp_i[3],tmp_i[4],tmp_i[5],tmp_i[6],tmp_i[7]};
ICAP_SPARTAN6 #(
.DEVICE_ID(28'h4000093), // Specifies the pre-programmed Device ID value
.SIM_CFG_FILE_NAME("NONE") // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
// model
)
ICAP_SPARTAN6_inst (
.BUSY(), // 1-bit output: Busy/Ready output
.O(), // 16-bit output: Configuartion data output bus
.CE(ce), // 1-bit input: Active-Low ICAP Enable input
.CLK(sclk), // 1-bit input: Clock input
.I(i_data), // 16-bit input: Configuration data input bus
.WRITE(1'b0) // 1-bit input: Read/Write control input
);
endmodule
module tx_crtl(
input wire sclk,
input wire rst_n,
input wire [7:0] data_in,
input wire flag_in,
output reg data_o
);
reg [12:0] cnt;
reg [3:0] bit_cnt;
reg tx_en;
parameter CNT=5207;
parameter BIT_CNT=8;
reg [7:0] data_in_dely;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
data_in_dely<=8'd0;
else if(flag_in==1)
data_in_dely<=data_in;
else if(tx_en==0)
data_in_dely<=8'd0;
//tx_en
always@(posedge sclk or negedge rst_n)
if(!rst_n)
tx_en<=1'b0;
else if(flag_in==1'b1)
tx_en<=1'b1;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
tx_en<=1'b0;
//cnt 波特率计数
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=13'd0;
else if(cnt==CNT)
cnt<=13'd0;
else if(tx_en==1'b1) //条件没写对
cnt<=cnt+1'b1;
//bit_cnt 字节统计
always@(posedge sclk or negedge rst_n)
if(!rst_n)
bit_cnt<=4'd0;
else if(tx_en==1'b0)
bit_cnt<=4'd0;
else if(bit_cnt==BIT_CNT&cnt==CNT)
bit_cnt<=4'd0;
else if(cnt==CNT)
bit_cnt<=bit_cnt+1'b1;
//输出数据控制
always@(posedge sclk or negedge rst_n)
if(!rst_n)
data_o<=1'b1;
else if(tx_en==1'b0) //flag_in==1'b1
data_o<=1'b1;
else if(bit_cnt==10'd0) //flag_in==1'b1
data_o<=1'b0;
else if(bit_cnt==10'd1)
data_o<=data_in_dely[0];
else if (bit_cnt==10'd2)
data_o<=data_in_dely[1];
else if(bit_cnt==10'd3)
data_o<=data_in_dely[2];
else if(bit_cnt==10'd4)
data_o<=data_in_dely[3];
else if(bit_cnt==10'd5)
data_o<=data_in_dely[4];
else if(bit_cnt==10'd6)
data_o<=data_in_dely[5];
else if(bit_cnt==10'd7)
data_o<=data_in_dely[6];
else if(bit_cnt==10'd8)
data_o<=data_in_dely[7];
//else if(bit_cnt==BIT_CNT)
// data_o<=1'b1;
else data_o<=1'b1;
endmodule
module top_updata(
input wire sclk,
input wire rst_n,
input wire rx_uart_data,
input wire key_in,
output wire tx_data,
output wire led,
output wire cs_n,
output wire sck,
output wire sdi
);
wire key_inst_o;
wire stop_flag_rx;
wire flag_o_rx;
wire [7:0] data_o_rx;
wire wr_flag_frame_inst;
wire [23:0] wr_addr_frame_inst;
wire [7:0] wr_data_inst;
wire se_flag_frame;
wire [23:0] se_addr_frame;
wire sent_flag_out_se_inst;
wire tx_flag_frame;
wire [7:0] tx_data_farme;
wire wr_inst_cs_n;
wire wr_inst_sck;
wire wr_inst_sdi;
wire se_inst_cs_n;
wire se_inst_sck;
wire se_inst_sdi;
wire wr_flag_dizhi;
assign cs_n=(wr_inst_cs_n&&se_inst_cs_n);
assign sck=(wr_inst_sck||se_inst_sck);
assign sdi=(wr_inst_sdi&&se_inst_sdi);
key_rock key_rock_inst(
.sclk (sclk),
.rst_n (rst_n),
.key_in (key_in),
.key_o (key_inst_o)
);
icap_ctrl icap_ctrl_inst(
.sclk (sclk),
.rst_n (rst_n),
.key_in (key_inst_o),
.wr_addr_frame (wr_addr_frame_inst)
);
rx_crtl rx_crtl_inst(
.sclk (sclk),
.rst_n (rst_n),
.rx_in (rx_uart_data),
.stop_flag (stop_flag_rx),
.flag_o (flag_o_rx),
.data_o (data_o_rx)
);
w_farme w_farme_inst(
.sclk (sclk),
.rst_n (rst_n),
.flag_uart (flag_o_rx),
.data_uart (data_o_rx),
.stop_flag (stop_flag_rx), //数据发送完成标志
.sen_stop_flag (sent_flag_out_se_inst), //擦除完成标识
.wr_flag_dizhi (wr_flag_dizhi),
.wr_flag (wr_flag_frame_inst),
.wr_addr (wr_addr_frame_inst),
.wr_data (wr_data_inst),
.se_addr (se_addr_frame),
.se_flag (se_flag_frame),
.tx_flag (tx_flag_frame),
.tx_data (tx_data_farme) //擦除结束用55标志,发生完成用aa标识
);
flash_ctrl_wr flash_ctrl_wr_inst(
.sclk (sclk),
.rst_n (rst_n),
.pi_flag (wr_flag_frame_inst),
.data_in (wr_data_inst),
.stop_flag_rx (stop_flag_rx), //发送端输入的停止位
.frame_wr_addr (wr_addr_frame_inst),
.pi_flag_dizhi (wr_flag_dizhi),
.cs_n (wr_inst_cs_n),
.sck (wr_inst_sck),
.sdi (wr_inst_sdi)
);
flash_ctrl_se flash_ctrl_se_inst(
.sclk (sclk),
.rst_n (rst_n),
.pi_se_flag (se_flag_frame),
.se_addr_in (se_addr_frame),
.led (led),
.cs_n (se_inst_cs_n),
.sck (se_inst_sck),
.sdi (se_inst_sdi),
.sent_flag_out (sent_flag_out_se_inst) //地址清零结束位
);
tx_crtl tx_crtl_inst(
.sclk (sclk),
.rst_n (rst_n),
.data_in (tx_data_farme),
.flag_in (tx_flag_frame),
.data_o (tx_data)
);
endmodule
`timescale 1ns/1ns
module tb_update;
reg sclk;
reg rst_n;
reg rx;
reg[7:0] a_mem[18:0]; //当前为测试flash写模块 擦出数据为55 55 55 55 55 55 55 d5 aa 10 00 00
initial $readmemh("./data.txt", a_mem); //测试flash写入数据为55 55 55 55 55 55 55 d5 55 10 00 00 01 02 03 04 05 aa 55
initial
begin
sclk = 1'b1;
rst_n <= 1'b0;
#300
rst_n <= 1'b1;
end
always #10 sclk = ~sclk;
initial
begin
rx <= 1'b1;
#2000
rx_byte();
end
task rx_byte();
integer j;//定义一个整型变量
for(j=0;j<19;j=j+1)//for循环 测试的时候,数据加到原来的256应该是86
rx_bit(a_mem[j]);//a_mem[j]是data.txt文件里面第j个8比特数据
//j每次取一个值,就调用一次rx_bit();
//一共调用256次
endtask
task rx_bit(input [7:0] data);//data是a_mem[j]的值。
integer i;
for(i=0;i<10;i=i+1)
begin
case(i)
0: rx <= 1'b0;//起始位
1: rx <= data[0];
2: rx <= data[1];
3: rx <= data[2];
4: rx <= data[3];
5: rx <= data[4];
6: rx <= data[5];
7: rx <= data[6];
8: rx <= data[7];
//上面8个发送的是数据位
9: rx <= 1'b1;//停止位
endcase
#104140;//一个波特时间=sclk周期*波特计数器
end
endtask
defparam top_updata_inst.flash_ctrl_se_inst.ONE_S=500;
//defparam top_updata_inst.rx_crtl_inst.CNT=9;
//defparam top_updata_inst.rx_crtl_inst.bit_flag_cnt=4;
//defparam top_updata_inst.tx_crtl_inst.CNT=10;
top_updata top_updata_inst(
.sclk (sclk),
.rst_n (rst_n),
.rx_uart_data (rx),
.key_in ()
);
endmodule
4.这次比较难调试的frame_ctrl模块,多次仿真最终达到目的
5.如果仿真通过,下载只办卡却没有达到应有效果,就需要利用ise的chipscope对内部信号进行抓取。
6.擦除调试如图: