"); //-->
AT93C46的MIX功能
1 功能概述
AT93C46在DI接收到读指令时,地址被解码,数据在DO引脚上串行输出。写周期是完全自主调时的,在写入之前不需要单独的擦除周期。只有当器件处于擦除/写使能状态时,写周期才有效。当写入周期开始后,CS被置为高电平时,DO引脚输出处于就绪/忙状态。本项目要求AT93C46在前两个单独案例的基础上完成读和写功能的混合功能。
2 设计思路
读(READ)指令包含要读取的存储器位置的地址代码。在接收到指令后,地址被解码,来自存储器的所选数据在串行输出引脚DO处可用。输出数据的变化与SK时钟上升沿同步。需要注意的是,在8或16位数据输出的字符串之前会有1比特的虚拟位(逻辑“0”)。
写(WRITE)指令包含要写入指定存储器的8位或16位数据。自定义编程周期twp始于最后一位数据在输入引脚DI接收的完成。如果CS在保持低电平至少250 ns(tcs)后拉高,则DO引脚输出读/忙状态。DO处的逻辑“0”表示编程仍在进行中,而逻辑“1”表示存储位置指定的地址已经写入指令中包含的数据模式,并且准备好下一步的指令。如果CS在自定义编程周期twp结束后拉高,则无法获得就绪/忙状态。
本案例要求实现一个AT93C46的接口能够根据命令,实现EWEN、WRITE和READ功能,具体思路如下:
1. 上游模块在rdy=1时,给出start命令,开始进行EWEN、WRITE或者READ操作;在rdy=0期间,start命令无效。
2. 当start有效时,如果mode=0表示进行EWEN操作;mode=1表示进行WRITE操作;mode=2表示进行READ操作。
3. 当start有效时,addr和wdata有效。
4. 当进行EWEN操作时,将addr写入at93c46。
5. 当进行WRITE操作时,将addr和wdata写入at93c46。
6. 当进行READ操作时,将addr写入at93c46,并从at93c46读到数据,通过rdata和rdata_vld返回给上游模块。
信号列表如下:
信号名 | I/O | 位宽 | 说明 |
clk | I | 1 | 系统工作时钟100MHz。 |
rst_n | I | 1 | 系统复位信号,低电平有效。 |
addr | I | 7 | 地址信号,在start有效时,此值有效。 |
wdata | I | 8 | 写数据信号,在start有效时,此值有效。 |
start | I | 1 | 开始命令,仅在rdy=1时才有效。 |
mode | I | 2 | 操作模式,start有效时,此值有效。 0:EWEN操作 1:WRITE操作 2:READ操作 其他:无变化 |
rdy | O | 1 | 准备好信号。当rdy为1时,start才有效。在rdy为0时,不能使start有效。 |
rdata | O | 8 | 从AT93C46读取的数据 |
rdata_vld | O | 1 | 从AT93C46读到的数据有效指示信号 |
do | I | 1 | at93c46数据输出 |
di | O | 1 | at93c46数据输入 |
cs | O | 1 | at93c46片选 |
sk | O | 1 | at93c46时钟,1MHz |
3 程序设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | module at93c46_mix( clk , rst_n , start , mode , addr , wdata , rdata , rdata_vld , rdy , do , di , cs , sk );
parameter DATA_W = 8 ; parameter EWEN = 2'b00 ; parameter WRITE = 2'b01 ; parameter READ = 2'b10 ;
input clk ; input rst_n ; input [6:0] addr ; input [1:0] mode ; input start ; input do ;
input [DATA_W-1:0] wdata ; output rdy ; output di ; output cs ; output sk ; output[DATA_W-1:0] rdata ; output rdata_vld ;
reg [DATA_W-1:0] rdata ; reg rdata_vld ; reg rdy ; reg di ; reg cs ; reg sk ;
reg [17:0] data ; reg [1:0] flag ; reg [16:0] cnt0 ; reg [4:0] cnt1 ; reg cnt2 ; reg [16:0] x ; reg [4:0] y ; reg [1:0] m ; reg [1:0] work_flag ;
wire add_cnt0 ; wire end_cnt0 ; wire add_cnt1 ; wire end_cnt1 ; wire add_cnt2 ; wire end_cnt2 ; wire mid_cnt0 ; wire fir_cnt0 ;
always @(posedgeclk or negedgerst_n)begin if(!rst_n)begin cnt0 <= 0; end else if(add_cnt0)begin if(end_cnt0) cnt0 <= 0; else cnt0 <= cnt0 + 1; end end assign add_cnt0 = work_flag; assign end_cnt0 = add_cnt0 && cnt0==x-1 ;
always @(posedgeclk or negedgerst_n)begin if(!rst_n)begin cnt1 <= 0; end else if(add_cnt1)begin if(end_cnt1) cnt1 <= 0; else cnt1 <= cnt1 + 1; end end assign add_cnt1 = end_cnt0; assign end_cnt1 = add_cnt1 && cnt1==y-1 ;
always @(posedgeclk or negedgerst_n)begin if(!rst_n)begin cnt2 <= 0; end else if(add_cnt2)begin if(end_cnt2) cnt2 <= 0; else cnt2 <= cnt2 + 1; end end assign add_cnt2 = end_cnt1; assign end_cnt2 = add_cnt2 && cnt2==m-1 ;
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin flag <= 0; end else if(start && mode==EWEN)begin flag <= 0; end else if(start && mode==WRITE)begin flag <= 1; end else if(start && mode==READ)begin flag <= 2; end end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin data <= 0; end else if(start && mode==EWEN)begin data <= {3'b100,addr,wdata}; end else if(start && mode==WRITE)begin data <= {3'b101,addr,wdata}; end else if(start && mode==READ)begin data <= {3'b110,addr,wdata}; end end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin work_flag<= 0; end else if(start)begin work_flag<= 1; end else if(end_cnt2)begin work_flag<= 0; end end
assign mid_cnt0 = add_cnt0 && cnt0==50-1 && cnt2==1-1; assign fir_cnt0 = add_cnt0 && cnt0== 1-1 && cnt2==1-1;
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin sk<= 0; end else if(mid_cnt0) begin sk<= 1; end else if(end_cnt0) begin sk<= 0; end end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin di <= 1'b0; end else if(fir_cnt0)begin di <= data[17-cnt1]; end end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin cs<= 1'b0; end else if(mode==WRITE || (end_cnt1 && cnt2==2-1 && flag==1))begin cs<= 1'b1; end else if(end_cnt1 && (cnt2==1-1 || cnt2==3-1))begin cs<= 1'b0; end end
always @(*)begin if(mode==WRITE || work_flag) rdy = 1'b0; else rdy = 1'b1; end
always @(*)begin if(cnt2==1-1 && flag==0)begin x = 100; y = 10; end else if(cnt2==1-1 && (flag==2-1 || flag==3-1))begin x = 100; y = 18; end else if(cnt2==2-1)begin x = 100; y = 1; end else begin x = 100000; y = 1 ; end end
always @(*)begin if(flag==1)begin z = 3; else z = 2; end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin rdata<= 0; end else if(end_cnt0 && cnt1 >= 11 && flag==2) begin rdata<= {rdata[6:0],do}; end end
always @(posedgeclk or negedgerst_n)begin if(rst_n==1'b0)begin rdata_vld<= 1'b0; end else if(end_cnt2 && flag==2) begin rdata_vld<= 1'b1; end else begin rdata_vld<= 1'b0; end end endmodule |
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。