2016年5月8日 罗鹏春 Lesson18
内容提要:
1 Flash Memory
2 .sof文件 和 烧写到Flash的操作的区别
3 flash文件的擦除
4 spi的指令时序
//-----------------------------------------正文-------------------------------------------
1 flash memeory:SPI(Serial Peripheral Interface:串行外设接口);
闪存:
1 长寿命非易失性(断电情况下仍能保持所存储的数据信息)的存储器,
2 数据删除不是以单个字节为单位而是以固定的区块为单位
3 闪存是EEPROM的变种,不同的是,
EEPROM能在字节水平上进行删除重写而不是整个芯片擦写,
而闪存的大部分芯片需要块擦除。
4 NOR型和NAND型
NOR型闪存更像内存,有独立的地址线和数据线,但是价格比较贵,容量比较小;
NAND型更像硬盘,地址线和数据线是共用的IO,类似硬盘的所有信息都是通过一条硬盘线传送。
MAND比NOR成本低,容量大。
NOR闪存适合频繁随机读写的场合,通常用于存储程序代码并直接在闪存内运行。
2 SOF是JTAG模式的下载,速度比较快,但是是掉电失效的。
POF是ASP模式,是固化在芯片里的,速度比较慢,但是是不会失效的。
一般在设计调试程序的时候用SOF烧写,应用的时候用POF烧写。
3 flash擦除 【参见相关指令手册】
4 SPI:
(1)SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
(2)SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,地位在后,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps。
(3)SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号:
(1)sdi – 主器件(fpag)数据输出,从器件(flash)数据输入
(2)sdo – 主器件数据输入,从器件数据输出
(3)sck – 时钟信号,由主器件产生
(4)cs_n – 从器件使能信号,由主器件控制
//=====================================
【西西学FPGA】Lesson19
2016年5月8日 罗鹏春
发送指令 完成flasg 的PP操作
//----------------------------------------------------正文
module flash_pp(
input wire sclk,
input wire s_rst_n,
input wire key_in,
input wire sdo,
output reg cs_n,
output reg sdi,
output reg sck,
output reg [7:0] data_out,
output reg data_flag
);
parameter//for state
IDLE = 4'd0,
SE_WREN = 4'd1,//擦除操作的写使能信号
SE_DELAY = 4'd2,//1024个时钟
SE_OP = 4'd3,//擦除操作
PP_WAIT = 4'd4,//等待pp操作的key输入
PP_WREN = 4'd5,//pp操作的写使能信号
PP_DELAY = 4'd6,//1024个时钟
PP_OP = 4'd7,//pp操作
RD_WAIT = 4'd8,//等待读信号
RD_OP = 4'd9;//read操作
parameter//for introduction
WREN = 8'b0000_0110,
READ = 8'b0000_0011,
PP = 8'b0000_0010,
SE = 8'b1101_1000,
ADDR = 24'h00_0000,
DATA_INIT = 8'b0000_0000;//发送的初始数据
reg pp_flag;
reg [4:0] cnt_32;//CS有效的时候,进行满32清零的计数操作
reg [9:0] cnt_pp;//记录cnt_32满的个数,pp的最大计数为260-1;
reg [3:0] state;
reg [1:0] cnt_4;
reg [7:0] send_data;//发送的数据给spi
reg [7:0] data;//数值的计算问题
reg [7:0] data_out_tmp;
reg data_flag_delay;
//------------------------------------输出端口---------------------
//cs_n,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cs_n <= 1'b1;
else
begin
case(state)
IDLE :
if(key_in == 1'b1)
cs_n <= 1'b0;
SE_WREN :
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
cs_n <= 1'b1;
SE_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
cs_n <= 1'b0;
SE_OP :
if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
cs_n <= 1'b1;
PP_WAIT:
if(key_in == 1'b1)
cs_n <= 1'b0;
PP_WREN:
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
cs_n <= 1'b1;
PP_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
cs_n <= 1'b0;
PP_OP:
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
cs_n <= 1'b1;
RD_WAIT :
if(key_in == 1'b1)
cs_n <= 1'b0;
RD_OP :
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
cs_n <= 1'b1;
default:
cs_n <= 1'b1;
endcase
end
//sdi,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
sdi <= 1'b0;
else if ((cnt_4 == 2'd0)&&(cs_n == 1'b0))
sdi <= send_data[7];
//sck
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
sck <= 1'b0;
else if (pp_flag != 1'b1)
sck <= 1'b0;
else if (pp_flag == 1'b1)
begin
if(cnt_4 == 2'd0)
sck <= 1'b0;
else if(cnt_4 == 2'd2)
sck <= 1'b1;
end
else
sck <= 1'b0;
//data_out,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_out <= 8'b0;
else if(data_flag_delay == 1'b1)
data_out <= data_out_tmp;
//data_flag
////reg data_flag_delay;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_flag_delay <= 1'b0;
else if((state == RD_OP)&&(cnt_pp >= 10'd5)&&(cnt_pp <= 260)&&(cnt_32 == 5'd30))
data_flag_delay <= 1'b1;
else
data_flag_delay <= 1'b0;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_flag <= 1'b0;
else if (data_flag_delay == 1'b1)
data_flag <= 1'b1;
else
data_flag <= 1'b0;
//reg [7:0] data_out_tmp;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_out_tmp <= 8'b0;
else if((state == RD_OP)&&(cnt_pp >= 10'd4)&&(cnt_pp <= 260))
begin
case(cnt_32)
5'd2: data_out_tmp[7] <= sdo;
5'd6: data_out_tmp[6] <= sdo;
5'd10: data_out_tmp[5]<= sdo;
5'd14: data_out_tmp[4] <= sdo;
5'd18: data_out_tmp[3] <= sdo;
5'd22: data_out_tmp[2] <= sdo;
5'd26: data_out_tmp[1] <= sdo;
5'd30: data_out_tmp[0] <= sdo;
default:
data_out_tmp <= data_out_tmp;
endcase
end
//----------------------------发送数据-------------------------------
//reg [7:0] send_data;//发送的数据给sdi
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
send_data <= DATA_INIT;
else if (cnt_4 == 2'd2)
send_data <= {send_data[6:0],send_data[7]};
else
begin
case(state)
SE_WREN :
if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
send_data <= WREN;
SE_OP :
if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
send_data <= SE;
else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
send_data <= ADDR[23:16];
else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
send_data <= ADDR[15:8];
else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
send_data <= ADDR[7:0];
PP_WREN:
if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
send_data <= WREN;
PP_OP:
if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
send_data <= PP;
else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
send_data <= ADDR[23:16];
else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
send_data <= ADDR[15:8];
else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
send_data <= ADDR[7:0];
else if(cnt_32 == 5'd31)
send_data <= data;
RD_OP :
if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
send_data <= READ;
else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
send_data <= ADDR[23:16];
else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
send_data <= ADDR[15:8];
else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
send_data <= ADDR[7:0];
default:
send_data <= DATA_INIT;
endcase
end
//reg [7:0] data;//数值的计算问题
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data <= DATA_INIT;
else if ((state == PP_OP)&&(cnt_pp >= 10'd4)&&(cnt_pp <= 259)&&(cnt_32 == 5'd31)&&(cnt_4 == 2'd3))
data <= data + 1'b1;
// ---------------------------------中间变量-------------------------
//pp_flag;//在操作中的标志
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
pp_flag <= 1'b0;
else if (key_in == 1)
pp_flag <= 1'b1;
else if(((state ==RD_OP)&&(cnt_pp == 10'd261)&&(cnt_32 == 5'd31))||(state ==PP_WAIT)||(state ==RD_WAIT))
pp_flag <= 1'b0;
//cnt_32;/
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cnt_32 <= 5'd0;
else if(cnt_32 == 5'd31)
cnt_32 <= 5'd0;
else if(pp_flag == 1'b1)
cnt_32 <= cnt_32 + 1'b1;
else
cnt_32 <= 5'd0;
//cnt_pp;/
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cnt_pp <= 10'd0;
else
begin
case(state)
IDLE :
if(key_in == 1'b1)
cnt_pp <= 10'd0;
SE_WREN :
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
SE_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
SE_OP :
if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
PP_WAIT:
if(key_in == 1'b1)
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
PP_WREN:
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
PP_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
PP_OP:
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
RD_WAIT :
if(key_in == 1'b1)
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
RD_OP :
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
cnt_pp <= 10'd0;
else if (cnt_32 == 5'd31)
cnt_pp <= cnt_pp + 1'b1;
default:
cnt_pp <= 10'd0;
endcase
end
//state;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
state <= IDLE;
else
begin
case(state)
IDLE :
if(key_in == 1'b1)
state <= SE_WREN;
SE_WREN :
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
state <= SE_DELAY;
SE_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
state <=SE_OP;
SE_OP :
if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
state <= PP_WAIT ;
PP_WAIT:
if(key_in == 1'b1)
state <= PP_WREN;
PP_WREN:
if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
state <= PP_DELAY;
PP_DELAY:
if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
state <= PP_OP;
PP_OP:
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
state <= RD_WAIT;
RD_WAIT :
if(key_in == 1'b1)
state <= RD_OP ;
RD_OP :
if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
state <= IDLE;
default:
state <= IDLE;
endcase
end
//
//cnt_4;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cnt_4 <= 2'd0;
else
begin
case(state)
SE_WREN :
if(cnt_pp == 10'd1)
begin
if(cnt_4 == 2'd3)
cnt_4 <= 2'd0;
else
cnt_4 <= cnt_4 + 1'b1;
end
else
cnt_4 <= 2'd0;
SE_OP :
if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd4))
begin
if(cnt_4 == 2'd3)
cnt_4 <= 2'd0;
else
cnt_4 <= cnt_4 + 1'b1;
end
else
cnt_4 <= 2'd0;
PP_WREN:
if(cnt_pp == 10'd1)
begin
if(cnt_4 == 2'd3)
cnt_4 <= 2'd0;
else
cnt_4 <= cnt_4 + 1'b1;
end
else
cnt_4 <= 2'd0;
PP_OP:
if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd260))
begin
if(cnt_4 == 2'd3)
cnt_4 <= 2'd0;
else
cnt_4 <= cnt_4 + 1'b1;
end
else
cnt_4 <= 2'd0;
RD_OP :
if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd260))
begin
if(cnt_4 == 2'd3)
cnt_4 <= 2'd0;
else
cnt_4 <= cnt_4 + 1'b1;
end
else
cnt_4 <= 2'd0;
default:
cnt_4 <= 2'd0;
endcase
end
endmodule
//----------------------------------------------RAM_CONTROLLER
module ram_controller(
input wire sclk,
input wire s_rst_n,
input wire [7:0] data_in,
input wire data_flag,
input wire key_in,
output wire [7:0] data_to_ram,//to 双口ram
output reg [7:0] write_addr_to_ram,
output reg [7:0] read_addr_to_ram,
output reg wren_to_ram,
output reg read_data_flag
);
reg [25:0] clk_cnt;//1s 寄存器
reg [1:0] key_in_cnt;
parameter
CLK_CNT = 26'd2500_0000;
//key_in_cnt
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
key_in_cnt <= 2'd0;
else if(key_in_cnt == 2'd3)
key_in_cnt <= key_in_cnt;
else if (key_in == 1'b1)
key_in_cnt <= key_in_cnt + 1'b1;
//clk_cnt
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
clk_cnt <= 26'd0;
else if(clk_cnt == CLK_CNT)
clk_cnt <= 26'd0;
else if(write_addr_to_ram == 8'h00)
clk_cnt <= clk_cnt + 1'b1;
// data_to_ram,
assign data_to_ram = data_in;
//wren_to_ram
always@(posedge sclk )
wren_to_ram <= data_flag;
//assign wren_to_ram = data_flag;
// write_addr_to_ram,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
write_addr_to_ram <= 8'd0;
else if (wren_to_ram == 1'b1)
write_addr_to_ram <= write_addr_to_ram + 1'b1;
//read_data_flag
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
read_data_flag <= 1'b0;
else if((read_addr_to_ram >= 8'd0)&&(read_addr_to_ram <= 8'd255)&&(clk_cnt == 26'd0))
read_data_flag <= 1'b1;
else
read_data_flag <= 1'b0;
//read_addr_to_ram,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
read_addr_to_ram <= 8'b0;
else if ((clk_cnt == CLK_CNT)&&(read_addr_to_ram == 8'd255)&&(key_in_cnt == 2'd3))
read_addr_to_ram <= 8'b0;
else if ((clk_cnt == CLK_CNT)&&(key_in_cnt == 2'd3))
read_addr_to_ram <= read_addr_to_ram + 1'b1;
endmodule
//----------------------------------------------top
module flash_controller(
input wire sclk,
input wire s_rst_n,
input wire key_in,
// input wire sdo,//from flash
output wire [2:0] sel,//to seg
output wire [7:0] seg
);
wire sdo;
wire key_out;
wire sck;
wire sdi;
wire cs_n;
wire [7:0] data_out;
wire data_flag;
wire [7:0] data_to_ram;//to 双口ram
wire [7:0] write_addr_to_ram;
wire [7:0] read_addr_to_ram;
wire wren_to_ram;
wire [7:0] q_sig;
wire read_data_flag;
wire [23:0] bcd_out;
wire out_flag;
key_in key_in_inst(
.sclk (sclk ),
.s_rst_n (s_rst_n ),
.key_in (key_in ),
.flag (key_out )
);
flash_pp flash_pp_inst(
.sclk (sclk ),
.s_rst_n (s_rst_n ),
.key_in (key_out ),
.sdo (sdo ),
.cs_n (cs_n ),
.sdi (sdi ),
.sck (sck ),
.data_out (data_out),
.data_flag (data_flag)
);
flash flash_inst (
.asdo_in ( sdi ),
.asmi_access_granted ( 1'b1 ),
.dclk_in ( sck ),
.ncso_in ( cs_n ),
.noe_in ( 1'b0 ),
.asmi_access_request ( ),
.data0_out ( sdo )
);
//data_out /data_flag -> ram
ram_controller ram_controller_inst(
.sclk (sclk ),
.s_rst_n (s_rst_n ),
.data_in (data_out),
.data_flag (data_flag) ,
.key_in (key_out ),
.data_to_ram (data_to_ram ),//to 双口ram
.write_addr_to_ram (write_addr_to_ram ),
.read_addr_to_ram (read_addr_to_ram ),
.wren_to_ram (wren_to_ram ),
.read_data_flag (read_data_flag)
);
ram8x256 ram8x256_inst (
.clock (sclk ),
.data ( data_to_ram ),
.rdaddress ( read_addr_to_ram ),
.wraddress ( write_addr_to_ram ),
.wren ( wren_to_ram ),
.q ( q_sig )
);
//bin_bcd bin_bcd_inst(
// .sclk (sclk ),
// .s_rst_n (s_rst_n ),
// .bin_in ({16'b0,q_sig} ),
// .in_flag (read_data_flag ),
//
// .bcd_out(bcd_out),
// .out_flag(out_flag)
// );
seg seg_inst(
.sclk (sclk ),
.s_rst_n (s_rst_n ),
.num (q_sig),
.enable (read_data_flag),
.sel(sel),
.seg(seg)
);
endmodule
//================================
【西西学FPGA】Lesson20uart+controller+spi
/*------------------------------------------------------------
模块名:command
功能描述:
时间:2016.5.18
作者:xizi cheng
联系方式:[email protected]
------------------------------------------------------------*/
module command(
input wire sclk,
input wire s_rst_n,
input wire [7:0] Rx_data,//form uart .rx_module
input wire Rx_flag,//一个系统周期,标志rx_data有效
input wire Tx_end,//from uart.tx_module
input wire ending_flag,
input wire [7:0] R_flash_data,//from flash_ctrl
input wire R_flash_flag,//读flash指令,读出的数据以及有效信号
input wire [7:0] W_flash_addr,//写flash指令,将存入输入ram的数据写入flash //fromflash_ctrl
output wire [7:0] W_flash_data,//比W_flash_addr晚一个周期
output reg [7:0] Tx_data,//to uart.tx_module
output reg Tx_flag,
output reg W_request,//to flash_ctrl
output reg R_request,//
output reg E_request,//
output reg [23:0] Flash_start_addr//
);
parameter
IDLE = 4'd0,
WAIT_FOR_55 = 4'd1,
WAIT_FOR_D5 = 4'd2,
WAIT_FOR_FA = 4'd3,
WAIT_FOR_ADDR = 4'd4,
WAIT_FOR_OP = 4'd5,
READ_00_00 = 4'd6,
READ_00_01 = 4'd7,
WRITE_00_00 = 4'd8,
WRITE_00_01 = 4'd9,
ERASE_00_00 = 4'd10,
ERASE_00_01 = 4'd11,
READ_OP = 4'd12,
WRITE_OP = 4'd13,
ERASE_OP = 4'd14,
WRITE_END = 4'd15,
WRITE_NUM_CNT = 8'd255;
reg [7:0] data_to_inram ;
// reg [7:0] read_addr_to_inram ;
reg [7:0] write_addr_to_inram ;
reg wren_to_inram ;
wire [7:0] q_from_inram ;
reg [7:0] data_to_outram ;
reg [7:0] read_addr_to_outram ;
reg [7:0] write_addr_to_outram ;
reg wren_to_outram ;
wire [7:0] q_from_outram ;
reg send_end;
reg [3:0] state;
reg [2:0] cnt_for_55;
reg [1:0] cnt_for_addr;
// reg [7:0] write_cnt;
reg [7:0] send_cnt;
reg send_flag;
reg tx_flag_delay2;
reg write_flag;
//------------------------------------------------------输出端口
//W_request,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
W_request <= 1'b0;
else if (write_addr_to_inram == 8'd255 &&(wren_to_inram == 1'b1) &&(state == WRITE_OP))
W_request <= 1'b1;
else
W_request <= 1'b0;
//R_request,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
R_request <= 1'b0;
else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00)&&(state == READ_00_01))
R_request <= 1'b1;
else
R_request <= 1'b0;
//E_request,
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
E_request <= 1'b0;
else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00)&&(state == ERASE_00_01))
E_request <= 1'b1;
else
E_request <= 1'b0;
//------------------------------------------------------中间变量
//cnt_for_addr
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cnt_for_addr <= 2'd0;
else if((cnt_for_addr == 2'd2)&&(Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
cnt_for_addr <= 2'd0;
else if ((Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
cnt_for_addr <= cnt_for_addr + 1'b1;
//cnt_for_55;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
cnt_for_55 <= 3'd0;
else if((state != WAIT_FOR_55))
cnt_for_55 <= 3'd0;
else if (cnt_for_55 == 3'd7)
cnt_for_55 <= 3'd0;
else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h55)&&(state == WAIT_FOR_55))
cnt_for_55 <= cnt_for_55 + 1'b1;
//Flash_start_addr
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
Flash_start_addr <= 24'd0;
else if ((Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
begin
case(cnt_for_addr)
2'd0:
Flash_start_addr[7:0] <= Rx_data;
2'd1:
Flash_start_addr[15:8] <= Rx_data;
2'd2:
Flash_start_addr[23:16] <= Rx_data;
default:
Flash_start_addr <= 24'd0;
endcase
end
//----------------------------------------state;
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
state <= IDLE;
else
begin
case(state)
IDLE :
if((Rx_data == 8'h55)&&(Rx_flag == 1'b1))
state <= WAIT_FOR_55;
WAIT_FOR_55 :
if((cnt_for_55 == 3'd5)&&(Rx_data == 8'h55)&&(Rx_flag == 1'b1))
state <= WAIT_FOR_D5;
else if((Rx_data != 8'h55)&&(Rx_flag == 1'b1))
state <= IDLE;
WAIT_FOR_D5 :
if((Rx_data == 8'hD5)&&(Rx_flag == 1'b1))
state <= WAIT_FOR_FA ;
else if((Rx_data != 8'hD5)&&(Rx_flag == 1'b1))
state <= IDLE;
WAIT_FOR_FA :
if((Rx_data == 8'hFA )&&(Rx_flag == 1'b1))
state <= WAIT_FOR_ADDR ;
else if((Rx_data != 8'hFA)&&(Rx_flag == 1'b1))
state <= IDLE;
WAIT_FOR_ADDR :
if((cnt_for_addr == 2'd2)&&(Rx_flag == 1'b1))
state <= WAIT_FOR_OP;
WAIT_FOR_OP :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h55))
state <= READ_00_00;
else if((Rx_flag == 1'b1)&&(Rx_data == 8'hAA))
state <= WRITE_00_00;
else if((Rx_flag == 1'b1)&&(Rx_data == 8'hF0))
state <= ERASE_00_00;//输入数据为擦除
else if(Rx_flag == 1'b1)
state <= IDLE;
READ_00_00 :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= READ_00_01 ;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
READ_00_01 : //保留位必须为00
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= READ_OP ;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
//------------------------------
WRITE_00_00 :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= WRITE_00_01 ;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
WRITE_00_01 :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= WRITE_OP ;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
ERASE_00_00 :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= ERASE_00_01;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
ERASE_00_01 :
if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
state <= ERASE_OP ;
else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
state <= IDLE;
READ_OP :
if ( send_end == 1'b1)
state <= IDLE;
WRITE_OP :
if(W_request == 1'b1)
state <= WRITE_END;
ERASE_OP :
if(send_cnt == 8'd15 && Tx_end == 1'b1)
state <= IDLE;
WRITE_END:
if(send_cnt == 8'd15 && Tx_end == 1'b1)
state <= IDLE;
default:
state <= IDLE;
endcase
end
//---------------------------------------------------------write to inram
//write_flag
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
write_flag <= 1'b0;
else if (write_addr_to_inram ==8'd255 && wren_to_inram == 1'b1)
write_flag <= 1'b0;
else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00) &&(state == WRITE_00_01))
write_flag <= 1'b1;
//data_to_inram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_to_inram <=8'd0;
else if (state != WRITE_OP)
data_to_inram <=8'd0;
else if ((state == WRITE_OP)&&(Rx_flag == 1'b1))
data_to_inram <= Rx_data;
//write_addr_to_inram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
write_addr_to_inram <= 8'd0;
else if (state != WRITE_OP)
write_addr_to_inram <= 8'd0;
else if (write_addr_to_inram == 8'd255 && wren_to_inram == 1'b1)
write_addr_to_inram <= 8'd0;
else if ((state == WRITE_OP)&&(wren_to_inram == 1'b1))
write_addr_to_inram <= write_addr_to_inram + 1'b1;
//wren_to_inram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
wren_to_inram <=1'b0;
else if ((state == WRITE_OP)&&(Rx_flag == 1'b1)&&(write_addr_to_inram <= 8'd255)&&(write_flag == 1'b1))
wren_to_inram <=1'b1;
else
wren_to_inram <=1'b0;
ram_8x256 in_ram_8x256 (
.clock ( sclk ),
.data ( data_to_inram ),//
.rdaddress ( W_flash_addr ),//
.wraddress ( write_addr_to_inram ),//
.wren ( wren_to_inram ),//
.q ( W_flash_data )//
);
//---------------------------------------------------------write to outram
//Tx_data q_from_outram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
Tx_data <= 8'hFF;
else if (ending_flag== 1&&(state == ERASE_OP ||state == READ_OP ||state == WRITE_END))
Tx_data <= 8'h55;
else if (send_flag == 1)
Tx_data <= q_from_outram;
else if(send_flag == 0 &&(state == ERASE_OP ||state == READ_OP ||state == WRITE_END))
begin
case(send_cnt)
8'd1:if(Tx_end == 1)
Tx_data <= 8'h55;
8'd2:if(Tx_end == 1)
Tx_data <= 8'h55;
8'd3:if(Tx_end == 1)
Tx_data <= 8'h55;
8'd4:if(Tx_end == 1)
Tx_data <= 8'h55;
8'd5:if(Tx_end == 1)
Tx_data <= 8'h55;
8'd6: if(Tx_end == 1)
Tx_data <= 8'h55;
8'd7: if(Tx_end == 1)
Tx_data <= 8'hd5;
8'd8: if(Tx_end == 1)
Tx_data <=8'hFC;
8'd9: if(Tx_end == 1)
Tx_data <=Flash_start_addr[7:0];
8'd10: if(Tx_end == 1)
Tx_data <=Flash_start_addr[15:8];
8'd11: if(Tx_end == 1)
Tx_data <=Flash_start_addr[23:16];
8'd12: if(Tx_end == 1)
Tx_data <= 8'h99;
8'd13: if(Tx_end == 1)
Tx_data <= 8'h00;
8'd14: if((Tx_end == 1)&&(state == ERASE_OP ))
Tx_data <= 8'hf0;
else if ((Tx_end == 1)&&(state == READ_OP))
Tx_data <= 8'h55;
else if ((Tx_end == 1)&&(state == WRITE_END))
Tx_data <= 8'hAA;
endcase
end
//send_flag
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
send_flag <= 1'b0;
else if (send_end == 1'b1)
send_flag <= 1'b0;
else if ( state == READ_OP &&send_cnt == 8'd15&& Tx_end == 1'b1)
send_flag <= 1'b1;
//tx_flag_delay2
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
tx_flag_delay2<= 1'b0;
else
tx_flag_delay2<= Tx_end;
//Tx_flag
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
Tx_flag <= 1'b0;
else if(send_flag == 1)
Tx_flag <= tx_flag_delay2;
else if(send_flag == 0)
begin
if(((state == ERASE_OP||state == WRITE_END)&&(send_cnt == 8'h0F))||(state == READ_OP)&&(send_cnt == 8'hFF))
Tx_flag <= 1'b0;
else if ((state == ERASE_OP||state == WRITE_END)||(state == READ_OP)&&(send_cnt != 8'h0f))
Tx_flag <= Tx_end||ending_flag;
else
Tx_flag <= 1'b0;
end
else
Tx_flag <= 1'b0;
//read_addr_to_outram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
read_addr_to_outram <= 8'd0;
else if (read_addr_to_outram == 8'd255 && tx_flag_delay2 == 1 && send_flag == 1'b0)
read_addr_to_outram <= 8'd0;
else if (send_flag == 1 && Tx_flag == 1 && state == READ_OP)
read_addr_to_outram <= read_addr_to_outram + 1'b1;
//reg [7:0] send_cnt
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
send_cnt <= 8'd0;
else if (state == IDLE)
send_cnt <= 8'd0;
else if (send_end == 1'b1)
send_cnt <= 8'd0;
else if (send_flag == 1'b0 &&(state == READ_OP||state ==WRITE_END||state == ERASE_OP) &&send_cnt == 8'd15 && Tx_end == 1)
send_cnt <= 8'd0;
else if ((state == READ_OP||state == WRITE_END||state == ERASE_OP)&&(send_cnt < 255) &&(ending_flag == 1 || Tx_end == 1))
send_cnt <= send_cnt + 1'b1;
//send_end
always @(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
send_end <= 1'b0;
else if ( state == READ_OP &&send_cnt == 8'd255 && send_flag == 1 && Tx_flag == 1)
send_end <= 1'b1;
else
send_end <= 1'b0;
//data_to_outram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
data_to_outram <=8'd0;
else if (state != READ_OP)
data_to_outram <=8'd0;
else if ((state == READ_OP)&&(R_flash_flag == 1'b1))
data_to_outram <=R_flash_data;
//write_addr_to_outram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
write_addr_to_outram <= 8'd0;
else if (write_addr_to_outram == WRITE_NUM_CNT && wren_to_outram == 1'b1 )
write_addr_to_outram <= 8'd0;
else if ((state == READ_OP)&&(wren_to_outram == 1'b1))
write_addr_to_outram <= write_addr_to_outram + 1'b1;
//wren_to_outram
always@(posedge sclk or negedge s_rst_n)
if(!s_rst_n)
wren_to_outram <=1'b0;
else if ((state == READ_OP)&&(R_flash_flag == 1'b1))
wren_to_outram <=1'b1;
else
wren_to_outram <=1'b0;
ram_8x256 out_ram_8x256 (
.clock ( sclk ),
.data ( data_to_outram ),//
.rdaddress ( read_addr_to_outram ),//
.wraddress ( write_addr_to_outram ),//
.wren ( wren_to_outram ),//
.q ( q_from_outram )//
);
endmodule
//=============Lesson21
时间 2016.5.21
1 .do文件
2 写端口
3 写跳转状态
4 写文档(2,3,4,是一件事情)
5 信号波形图(visio)
6 总体架构图
//修改过后的Tx_module,Tx_end 产生的条件和方法
//-----------------------------尤老师的tx模块
module rs232_phy_tx(
input wire sclk,
input wire rst_n,
//interface for rs232 rx
output reg tx_d,
//interface for internal logic
input wire [7:0] tx_data,
input wire tx_data_sync,
output wire busy
);
reg [9:0] tx_data_t;
reg cnt_en;
reg end_flag;
reg div_end_flag;
reg [13:0] div_cnt;
reg [3:0] baud_cnt;
reg shift_flag;
parameter BAUD_RATE =1085-1; //125M/baud_rate(115200bps)=1085;
//9600bps=13021;14400bps=8680;19200bps=6510;38400bps=3255;
//57600bps=2170;115200bps=1085;230400bps=542;460800bps=271;
parameter INVERT =0; //如果invert=0下降沿"0"为起始位,第10位停止位为高。invert=1则相反。
parameter FREQ_ERROR =400; //收发端的频率误差
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)begin
tx_data_t<=10'h3ff;
end
else if(tx_data_sync=='d1)
tx_data_t<={1'b1,tx_data,1'b0};
else if(shift_flag=='d1)
tx_data_t<={1'b1,tx_data_t[9:1]};
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
div_end_flag<='d0;
else if(div_cnt==(BAUD_RATE - 1))
div_end_flag<='d1;
else
div_end_flag<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
end_flag<='d0;
else if(div_cnt==(BAUD_RATE -FREQ_ERROR) && baud_cnt=='d9)
end_flag<='d1;
else
end_flag<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)
cnt_en<='d0;
else if(end_flag=='d1)
cnt_en<='d0;
else if(tx_data_sync)
cnt_en<='d1;
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)
div_cnt<='d0;
else if(cnt_en=='d1 && div_end_flag=='d1)
div_cnt<='d0;
else if(cnt_en=='d1)
div_cnt<=div_cnt+'d1;
else div_cnt<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)
baud_cnt<='d0;
else if(cnt_en=='d1 && end_flag=='d1)
baud_cnt<='d0;
else if(cnt_en=='d1 && div_end_flag=='d1)
baud_cnt<=baud_cnt+'d1;
else if(cnt_en=='d0)
baud_cnt<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)
shift_flag<='d0;
else if(cnt_en=='d1 && div_cnt=='d0 && baud_cnt!='d0)
shift_flag<='d1;
else shift_flag<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n=='d0)begin
if(INVERT=='d0)
tx_d<=1'b1;
else tx_d<=1'b0;
end
else if(INVERT=='d0)
tx_d<=tx_data_t[0];
else
tx_d<=~tx_data_t[0];
assign busy=cnt_en;
endmodule
//------------------------------------------------------------tx_end 产生条件
module uart(
input wire sclk ,
input wire s_rst_n ,
input wire rx ,
input wire [7:0] tx_data ,
input wire tx_flag ,
output wire [7:0] rx_data ,
output wire rx_flag ,
output wire tx ,
output reg tx_end
);
//tx_module tx_module_inst(
// .sclk (sclk ),
// .s_rst_n (s_rst_n ),
// .pi_flag (tx_flag ),
// .pi_num (tx_data ),
//
// .po_tx (tx ),
// .tx_end (tx_end )
// );
defparam rs232_phy_tx.BAUD_RATE=50000000/9600;
rs232_phy_tx rs232_phy_tx(
.sclk(sclk),
.rst_n(s_rst_n),
.tx_d(tx),
.tx_data(tx_data),
.tx_data_sync(tx_flag),
.busy(busy)
);
reg busy_delay;
always@( posedge sclk )
busy_delay <= busy;
always@(posedge sclk )
if(busy == 1'b0 && busy_delay ==1'b1)
tx_end <= 1'b1;
else
tx_end <= 1'b0;
rx_module rx_module_inst(
.sclk (sclk ),
.s_rst_n (s_rst_n ),
.rx_data_in (rx ),
.po_rx_data (rx_data ),
.po_rx_flag (rx_flag )
);
endmodule
//课后总结:
1 最初觉得在最后一个clk产生tx_end信号也不会影响到自己发送的数据,所以tx_end产生的条件是在最后一个bit产生的时候,baut_cnt == 波特率/2
2 后来因为接收的数据一直不对,因此老师建议我修改tx_end信号的产生条件,于是用老师的模块来生成tx_end;在发送数据的时候有了flag恒为高,当数据完全发送完成的时候,flag拉低,就利用这个flag的下降沿产生一个tx_end信号,当前数据完全发送而之后的信号也能立刻发送。
在电路世界,虽然提高效率也重要,但是数据的准确性还是需要强调。