FPGA学习笔记-------计数器结构05

//sccb接口
//计数器
//明德扬定义计数器
//计数器规则1:计数器逐一考虑3要素:初值、加一条件、结束值
//计数器规则2:计数器初值必须为零
//计数器规则3:使用某一计数器值,必须同时满足加一条件
//计数器规则4:结束条件必须同时满足加一条件
//计数器规则5:当取某个数时,assign的形式必须为:(加一条件)&&(cnt==计数值-1);
//计数器规则6:结束后必须回到0;
//计数器规则7:若要限定范围,则推荐使用">=“和”<"两种符号;
//计数器规则8:设计步骤是,先写计数器的always段,条件用名字代替,然后用assign写出加1条件;最后用assign写出结束条件;
//计数器规则9:加1条件必须与计数器严格对齐,其他信号一律向计数器对齐;
//计数器规则10:命名规则必须符合规范,比如:add_cnt表示加1条件;end_cnt表示结束条件;
//计数器规则11:减1计数器暂时不用。

//计数器八步法
// 第一步:功能明确
// 第二步:功能波形
// 第三步:计数结构 ------根据波形找出实现时序需要的计数器数量和结构
// 第四步:加1和结束条件
// 第五步:定义特殊点
// 第六步:完整性检查
// 第七步:计数器代码
// 第八步:功能代码
用硬件思想去描绘电路 ,找出每个信号变高变低的条件(条件要对齐计数器)

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				cnt_sclk <= 0;
			end
		else if(add_cnt_sclk)       //加一条件
			begin
				if(end_cnt_sclk)    //结束条件
					cnt_sclk <= 0;
				else
					cnt_sclk <= cnt_sclk + 1'b1;
			end
	end

assign add_cnt_sclk = work_flag;
assign end_cnt_sclk = add_cnt_sclk && cnt_sclk == SCLK_TIME - 1;

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				cnt_byte <= 0;
			end
		else if(add_cnt_byte)       //加一条件
			begin
				if(end_cnt_byte)    //结束条件
					cnt_byte <= 0;
				else
					cnt_byte <= cnt_byte + 1'b1;
			end
	end

assign add_cnt_byte = end_cnt_sclk;
assign end_cnt_byte = add_cnt_byte && cnt_byte == byte_num - 1;

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				cnt_step <= 0;
			end
		else if(add_cnt_step)       //加一条件
			begin
				if(end_cnt_step)    //结束条件
					cnt_step <= 0;
				else
					cnt_step <= cnt_step + 1'b1;
			end
	end

assign add_cnt_step = end_cnt_byte;
assign end_cnt_step = add_cnt_step && cnt_byte == step_num - 1;

//功能代码
parameter 	IDWADD = 8'h42;
parameter	IDRADD = 8'h43;
parameter	SCLK_TIME = 400;
parameter	SCLK_HALF_TIME = SCLK_TIME/2;
parameter	SCLK_W_TIME = SlCK_TIME/4;
parameter	SCLK_R_TIME = (SCLK_TIME/4)*3;

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				work_flag =1'b0;
			end
		else if(en)
			begin
				work_flag <= 1;
			end
		else if(end_cnt_step)
			begin
				work_flag <= 0;
			end
	end
	
assign en = work_flag == 1'b0 && (wr_en || rd_en);

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				rd_flag  =1'b0;
			end
		else if(rd_en)
			begin
				rd_flag <= 1;
			end
		else if(wr_en)
			begin
				rd_flag <= 0;
			end
	end

assign  wr_state = work_flag && rd_flag == 1'b0;
assign 	rd_state = work_flag && rd_flag == 1'b1;
assign  rd_0_state = rd_state && cnt_step == 1'b0;
assign  rd_1_state = rd_state && cnt_step == 1'b1;
assign  rd_get_state = rd_1_state && cnt_byte >= 10 && cnt_byte < 18;

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				subaad <= 0;
				wdata_ff0 <= 0;
			end
		else if(en)
			begin
				subaad <= addr;
				wdata_ff0 <= wdata;
			end
	end
	
always @(*)
	begin
		if(wr_state)
			begin
				wdata_temp = {1'b0,IDWADD,1'b1,subaad,1'b1,wdata_ff0,1'b1,1'b0,1'b1};
				byte_num = 30;
				step_num = 1;
			end
		else if(rd_0_state)
			begin
				wdata_temp = {1'b0,IDWADD,1'b1,subaad,1'b1,1'b0,1'b1,9'b0};
				byte_num = 21;
				step_num = 2;
			end
		else if(rd_1_state)
			begin
				wdata_temp = {1'b0,IDRADD,1'b1,8'b0,1'b1,1'b0,1'b1,9'b0};
				byte_num = 21;
				step_num = 2;
			end
	end

assign start_area = add_cnt_sclk && cnt_byte == 0;
assign stop_area = add_cnt_sclk && cnt_byte == byte_num - 1;

assign sclk_h2l = add_cnt_sclk && cnt_sclk == 0 && ((!start_area) && (!stop_area));
assign sclk_l2h = add_cnt_sclk && cnt_sclk == SCLK_HALF_TIME - 1;

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				sclk  =1'b1;
			end
		else if(sclk_l2h)
			begin
				sclk <= 1;
			end
		else if(sclk_l2h)
			begin
				sclk <= 0;
			end
	end
	
assign sio_send = add_cnt_sclk && cnt_sclk == SCLK_W_TIME - 1 && rd_get_state == 1'b0;
assign sio_get = add_cnt_sclk && cnt_sclk == SCLK_R_TIME - 1 && rd_get_state; 

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				sio_out <=1'b1;
			end
		else if(sio_send)
			begin
				sio_out <= wdata_temp[29 - cnt_byte];
			end
	end
	
always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				sio_out_en  =1'b0;
			end
		else if(work_flag && rd_get_state == 1'b0)
			begin
				sio_out_en <= 1;
			end
		else 
			begin
				sio_out_en <= 0;
			end
	end
	
always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				rdata  =1'b0;
			end
		else if(rd_get_state && sio_get)
			begin
				rdata <= {rdata[6:0],sio_in};
			end
	end

always @(posedge clk or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			begin
				rdata_vld  =1'b0;
			end
		else if(end_cnt_step && rd_1_state)
			begin
				rdata_vld <= 1;
			end
		else 
			begin
				rdata_vld <= 0;
			end
	end

always @(*)
	begin
		if(work_flag || rd_en || wr_en)
			rdy = 1'b0;
		else 
			rdy = 1'b1;
	end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值