一、线性序列机和有限状态机和(状态机**-编程思想**)的原理
序列机是什么:用计数器对时钟个数计数,根据相应时钟周期下的单个周期时间和计数个数可以确定某个时刻的时间,确定时间后再需要时间点转换电平!
采用的是线性序列机其原理就是设计者必须清楚每一个时钟节拍,都有哪些东西发生变化;举个例子:这个东西就好比我们的课表一样,我们第一节上语文课,第二节上数学课,第三节上英语课,它是按照时钟节拍一拍一拍的按照事先已经知道要发生的步骤做着每件事情。
而状态机则不同它的灵活性比较高可以随意的从一个状态跳到另一个状态。状态机里面case(state),而序列机里面则是case(count),count表示的是时钟节拍数。
线性序列机:是时间顺序的事件,根据时间先后顺序进行工作。每次执行一个工作,都只能按照时间顺序从头到尾。
状态机:根据程序内的状态,进行工作。例
如:a=1时,做A事情然后a=3;a=3时做B事情然后a=1。
示例
1TLC5620驱动模块(DAC):
module TLC5620_ctrl(
clk50M,
rst_n,
ctrlword,
updatareq,
updatadone,
TLC5620_CLK,
TLC5620_DATA,
TLC5620_LOAD,
TLC5620_LDAC
);
input clk50M;
input rst_n;
input [10:0] ctrlword;
input updatareq;
output reg updatadone;
output reg TLC5620_CLK;
output reg TLC5620_DATA;
output reg TLC5620_LOAD;
output reg TLC5620_LDAC;
reg [9:0] counter;
/*************************产生计数器************************/
always @ (posedge clk50M or negedge rst_n) begin
if(!rst_n)
counter<=10'd0;
else if(updatareq==1|(counter!=10'd0)) begin
if(counter==10'd820)
counter<=10'd0;
else
counter<=counter+1'b1;
end
else
counter<=10'd0;
end
/**********************************************************/
/*********************线性序列机写接口时序*******************/
always @ (posedge clk50M or negedge rst_n) begin
if(!rst_n) begin
updatadone<=1'b0;
TLC5620_CLK<=1'b0;
TLC5620_DATA<=1'b0;
TLC5620_LOAD<=1'b0;
TLC5620_LDAC<=1'b0;
updatadone<=1'b0;
end
else begin
case(counter)
0:begin
TLC5620_CLK<=1'b0;
TLC5620_DATA<=1'b0;
TLC5620_LOAD<=1'b1;
TLC5620_LDAC<=1'b0;
updatadone<=1'b0;
end
10:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[10];
end
40:TLC5620_CLK<=1'b0;
70:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[9];
end
100:TLC5620_CLK<=1'b0;
130:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[8];
end
160:TLC5620_CLK<=1'b0;
190:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[7];
end
220:TLC5620_CLK<=1'b0;
250:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[6];
end
280:TLC5620_CLK<=1'b0;
310:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[5];
end
340:TLC5620_CLK<=1'b0;
370:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[4];
end
400:TLC5620_CLK<=1'b0;
430:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[3];
end
460:TLC5620_CLK<=1'b0;
490:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[2];
end
520:TLC5620_CLK<=1'b0;
550:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[1];
end
580:TLC5620_CLK<=1'b0;
610:
begin
TLC5620_CLK<=1'b1;
TLC5620_DATA<=ctrlword[0];
end
640:TLC5620_CLK<=1'b0;
670:TLC5620_LOAD<=1'b0;
800:TLC5620_LOAD<=1'b1;
820:updatadone<=1'b1;
default:;
endcase
end
end
endmodule
2串口发送设计
module uart_tx (
input uart_clk,
input rst_n,
input tf_empty,//判断才做是否完成
input [7:0] tf_data,
output reg tf_rdreq,
output reg txd
);
reg [7:0] cnt;//节拍计数
reg [7:0] temp_data;//FIFO读数据后进行寄存
//LSM_1
always @(posedge uart_clk or negedge rst_n) begin
if(rst_n == 1'b0)
cnt <= 8'd192;
else if (cnt >= 8'd192 && tf_empty == 1'b0)
cnt <= 8'd0;
eles if(cnt < 8'd192)
cnt <= cnt + 1'd1;
end
//LSM_2
always @(posedge uart_clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
txd <= 1'b1;
tf_rdreq <= 1'b0;
temp_data <= 8'd0;
end else
case (cnt)
0 : begin
tf_rdreq <= 1'b0;
txd <= 1'b0;
end
1 : temp_data <= tf_data;
1*16 : txd <= temp_data[0];
2*16 : txd <= temp_data[1];
3*16 : txd <= temp_data[2];
4*16 : txd <= temp_data[3];
5*16 : txd <= temp_data[4];
6*16 : txd <= temp_data[5];
7*16 : txd <= temp_data[6];
8*16 : txd <= temp_data[7];
9*16 : txd <= 1'b1;
endcase
end
endmodule
状态机