系统芯片设计课上笔记-verilog复习(2)+watchdog-爱代码爱编程
串并转换
串并转换一般用来各种低速通信协议中,比如UART, SPI, I2C等。
UART的传输速率有9600,38400,191200等,K级别,CPU频率是M级别,串并转换可以作为数据缓冲模块,提高数据传输效率
wire data_out;
reg [7:0] temp;
always @(posedge clk or negedge rstn) begin
if(!rstn)
temp <= 8'h0;
else if(load)
temp <= data_in;
else if(en)
temp <= {temp[6:0], 1'b0};
else
temp <= temp;
end
assign data_out = temp[7];
// 并转串,比如CPU给uart发送串行数据,1bit,1bit发送
input wire data_in;
temp <= {temp[6:0], data_in};
// 串转并
FIFO&FILO
FIFO通常用在通信双方数据传输速率不匹配的情况下,硬件实现。
FILO与软件中的堆栈类型,完成入栈和出栈操作,一般采用软件方式实现。
FIFO分为同步fifo和异步fifo,异步fifo指的是读写时钟域的速率不同,当读写时钟速率差越大,所需fifo的深度越小,反之,深度越大。同步fifo指的是读写时钟速率相同,仅仅完成的是数据搬移工作,比如DMA的工作,在DMA控制器内部有一个同步的fifo作为数据缓冲,可以提高数据传输的速率。
此外,为了设计方便,FIFO的输入和输出位宽一般是相同的,如果不相同,要通过上文提到的串并转换方法进行位宽的调整。
- 同步fifo_demo
module fifo_sync #(
parameter DATA_WIDTH = 32,
parameter RAM_DEPTH = 8,
parameter RAM_ADDR = 3
)(
input clk,
input rstn,
input wr_en,
input [DATA_WIDTH-1:0] wr_data,
input rd_en,
output reg [DATA_WIDTH-1:0] rd_data,
output reg fifo_full,
output reg fifo_empyt
);
reg [DATA_WIDTH-1:0] ram[RAM_DEPTH];
reg [RAM_ADDR-1:0] wr_ptr, rd_ptr;
reg [RAM_ADDR-1:0] counter;
integer i;
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
for(i=0;i<RAM_DEPTH)
ram[i] <= 0;
end
else if(!fifo_full & wr_en)
ram[wr_ptr] <= wr_data;
end
always @(*) begin // comb logic
if(!rstn) begin
rd_data = 0;
end
else if(rd_en & !fifo_empyt)
rd_data = ram[rd_ptr];
else
rd_data = 0;
end
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
wr_ptr <= 0;
end
else if(wr_en & ~fifo_full)
wr_ptr <= wr_ptr + 1'b1;
end
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
rd_ptr <= 0;
end
else if(rd_en & ~fifo_empyt)
rd_ptr <= rd_ptr + 1'b1;
end
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
counter <= 'h0;
end
else if(wr_ptr && !fifo_full)
counter <= counter + 1'b1;
else if(rd_ptr && !fifo_empyt)
counter <= counter - 1'b1;
end
always @(*)
if(counter == RAM_DEPTH-1)
fifo_full = 1;
else
fifo_full = 0;
always @(*)
if(counter == 0)
fifo_empyt = 1;
else
fifo_empyt = 0;
endmodule
- 异步fifo的demo
有时间再写~
watchdog(硬件实现)
满足第一个预置数,向CPU发起中断,请求对watchdog计数清零,如果等到预置数1+预置数2还没有等到清零信号,说明系统跑飞了,则发起全局复位信号,对系统进行复位。
module wtd(
input clk,
input rstn,
input clear,
input [7:0] preload1,
input [7:0] preload2,
output reg done,
output reg reset
);
reg [7:0] cnt;
always @(posedge clk or negedge rstn) begin
if(!rstn)
cnt <= 8'h0;
else if(clear)
cnt <= 8'h0;
else if(cnt <= preload1 + preload2)
cnt <= cnt + 8'h1;
else
cnt <= cnt;
end
always @(posedge clk or negedge rstn) begin
if(!rstn)
done <= 1'b0;
else if(clear)
done <= 1'b0;
else if(cnt == preload1)
done <= 1'b1;
end
always @(posedge clk or negedge rstn) begin
if(!rstn)
reset <= 1'b0;
else if(cnt == preload1 + preload2)
reset <= 1'b1;
end
endmodule
对于硬件寄存器的访问,有两种方式:
- 硬件直接访问
- 通过软件方式间接访问