博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

总线读写---verilog代码

Posted on 2017-12-20 16:48  沉默改良者  阅读(2460)  评论(1编辑  收藏  举报

总线读写---verilog代码

  1 `timescale 1ns / 1ps
  2 //////////////////////////////////////////////////////////////////////////////////
  3 // Company: 
  4 // Engineer: chensimin
  5 // 
  6 // Create Date: 2017/11/16 17:32:35
  7 // Design Name: 
  8 // Module Name: read_and_write
  9 // Project Name: 
 10 // Target Devices: 
 11 // Tool Versions: 
 12 // Description: 
 13 // 
 14 // Dependencies: 
 15 // 
 16 // Revision:
 17 // Revision 0.01 - File Created
 18 // Additional Comments:
 19 // 
 20 //////////////////////////////////////////////////////////////////////////////////
 21 
 22 
 23 module read_and_write(
 24 
 25 //-----------------------clock and reset--------------------------
 26     input  wire       clk,
 27     input  wire       reset,
 28 //-----------------------up_interface---------------------------
 29     input  wire [11:0]up_address_channel,
 30     input  wire [31:0]up_wdata,
 31     output wire [31:0]up_rdata,
 32     input  wire       up_read_en,
 33     input  wire       up_write_en,
 34     output wire       up_ack,      
 35 //--------------------device IPC interface------------------------
 36     input  wire       ipc_ack,
 37     input  wire [31:0]ipc_rdata,
 38     output wire [31:0]ipc_wdata,
 39     output wire       ipc_rd,
 40     output wire       ipc_wr,
 41     output wire [11:0]ipc_addr,
 42 //--------------------------channel-------------------------------
 43     input  wire       channel_sel,
 44 //--------------------read flag-----------------------------------
 45     output wire       read_start_w
 46     );
 47 
 48 
 49 //------------------------read------------------------------------
 50 reg ipc_rd_r;
 51 reg [11:0]ipc_addr_r;
 52 reg ipc_wr_r;
 53 reg [31:0]ipc_wdata_r;
 54 reg [31:0]ipc_rdata_r;
 55 reg read_start;
 56 reg read_done;
 57 reg write_done;
 58 reg [2:0]i;
 59 reg [2:0]j;
 60 reg get_read_address;
 61 reg get_write_address;
 62 reg up_read_en_delay;
 63 reg up_write_en_delay;
 64 
 65 always @ (posedge clk or posedge reset)
 66     if(reset)
 67     begin
 68         up_read_en_delay <= 1'b0;
 69         up_write_en_delay <= 1'b0;
 70     end
 71     else
 72     begin
 73         up_read_en_delay <= up_read_en;
 74         up_write_en_delay <= up_write_en;
 75     end
 76 
 77 always @ (posedge clk or posedge reset)
 78     if(reset)
 79     begin
 80         ipc_rd_r <= 1'b0;
 81         ipc_rdata_r <= 32'h00000000;
 82         read_start <= 1'b0;
 83         read_done <= 1'b0;
 84         i <= 3'd0;
 85         get_read_address <= 1'b0;
 86     end
 87     else 
 88     begin
 89         read_start <= 1'b0;
 90         read_done <= 1'b0;
 91         ipc_rd_r <= 1'b0;
 92         get_read_address <= 1'b0;
 93         case(i)
 94         3'd0:
 95         begin
 96             if(channel_sel && up_read_en_delay)
 97             begin
 98                 get_read_address <= 1'b1;
 99                 i <= i + 1'b1;
100             end
101             else 
102                 i <= 3'd0;
103         end
104         3'd1:
105         begin
106             if(!ipc_ack)
107                 ipc_rd_r <= 1'b1;
108             else
109             begin
110                 ipc_rdata_r <= ipc_rdata;
111                 read_start <= 1'b1;
112                 read_done <= 1'b1;
113                 i <= i + 1'b1;    
114             end
115         end
116         3'd2:
117         begin
118             if(channel_sel && !up_read_en_delay)
119                 i <= 3'd0;
120             else 
121                 i <= 3'd2;
122         end
123         default: 
124         begin
125             i <= 3'd0;
126             read_start <= 1'b0;
127             read_done <= 1'b0;
128             ipc_rd_r <= 1'b0;
129             get_read_address <= 1'b0;
130         end
131         endcase
132     end
133 //------------------------write--------------------------------
134 always @ (posedge clk or posedge reset)
135     if(reset)
136     begin
137         ipc_wr_r <= 1'b0;
138         ipc_wdata_r <= 32'h00000000;
139         write_done <= 1'b0;
140         j <= 3'd0;
141         get_write_address <= 1'b0;
142     end
143     else 
144     begin
145         write_done <= 1'b0;
146         ipc_wr_r <= 1'b0;
147         get_write_address <= 1'b0;
148         case(j)
149         3'd0:
150         begin
151             if(channel_sel && up_write_en_delay)
152             begin
153                 get_write_address <= 1'b1;
154                 ipc_wdata_r <= up_wdata;
155                 j <= j + 1'b1;
156             end
157             else 
158                 j <= 3'd0;
159         end
160         3'd1:
161         begin
162             if(!ipc_ack)
163                 ipc_wr_r <= 1'b1;
164             else 
165             begin    
166                 write_done <= 1'b1;
167                 j <= j + 1'b1;
168             end
169         end
170         3'd2:
171         begin
172             if(channel_sel && !up_write_en_delay)
173                 j <= 3'd0;
174             else
175                 j <= 3'd2;
176         end
177         default:
178         begin
179             j <= 3'd0;
180             write_done <= 1'b0;
181             ipc_wr_r <= 1'b0;
182             get_write_address <= 1'b0;
183         end
184         endcase
185     end
186 //-------------------up_ack signal--------------------------
187 reg up_ack_r;
188 always @ (posedge clk or posedge reset)
189     if(reset)
190         up_ack_r <= 1'b0;
191     else if(read_done || write_done)
192         up_ack_r <= 1'b1;
193     else 
194         up_ack_r <= 1'b0;
195 
196 assign up_ack = up_ack_r;
197 
198 //------------------drive addr output-------------------------
199 always @ (posedge clk or posedge reset)
200     if(reset)
201         ipc_addr_r <= 12'h000;
202     else if(get_read_address || get_write_address) 
203     begin
204         ipc_addr_r <= up_address_channel;
205     end
206 
207 assign ipc_rd = ipc_rd_r;
208 assign ipc_addr = ipc_addr_r;
209 assign ipc_wdata = ipc_wdata_r;
210 assign ipc_wr = ipc_wr_r;
211 assign up_rdata = ipc_rdata_r;
212 assign read_start_w = read_start;
213 
214 endmodule

备注:在进行总线写操作的时候,写地址和数据信号要先准备好,等待写使能信号的到来。

非常重要的两点需要注意:

1.外部输入的控制信号,(如使能信号)往往和clk不同步,这就需要在使用前做延时处理,使其同步,这需要根据调试情况来定。

2.使能信号的使用,使能信号往往是一种脉冲信号,即:一个高点平期间,只进行一次相应的操作(读或写),这就需要在状态机中对使能信号进行合理的运用。如状态机中最后的一个状态:

 1 3'd2:
 2 begin
 3 if(channel_sel && !up_read_en_delay)
 4      i <= 3'd0;
 5 else 
 6      i <= 3'd2;
 7 end
 8 
 9 3'd2:
10 begin
11  if(channel_sel && !up_write_en_delay)
12      j <= 3'd0;
13  else
14      j <= 3'd2;
15 end

当使能信号执行完一个状态机后拉低时,状态机回到初始状态;

当使能信号执行完一个状态机后依旧保持高电平,状态机依旧保持当前状态。

这就是一个使能脉冲,执行一次操作的控制方法。