1.原题复现
代码
思考过程
首先,可以根据上一题比较而言,这一题不过是多了一个校验位(这里要注意的是:这个校验位在停止位之前,校验位和停止位是分开的两个不同的bit,刚开始没写出来,就是因为这里没弄清楚)
上一题的题目见蓝色部分点击进入https://hdlbits.01xz.net/wiki/Fsm_serialdata
然后贴上该题的串行数据代码:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
parameter IDLE=0,START=1,bit0=2,bit1=3,bit2=4,bit3=5,bit4=6,bit5=7,bit6=8,bit7=9,STOP=11,DONE0=12,DONE1=13;
reg[3:0]state,next_state;
reg [7:0] mid_byte;
always@(*)begin
case(state)
IDLE:next_state = in?IDLE:START;
START:next_state = bit0;
bit0:next_state = bit1;
bit1:next_state = bit2;
bit2:next_state = bit3;
bit3:next_state = bit4;
bit4:next_state = bit5;
bit5:next_state = bit6;
bit6:next_state = bit7;
bit7:next_state = in?STOP:DONE0;
STOP:next_state = in?IDLE:START;
DONE0:next_state = in?IDLE:DONE0;
endcase
end
always@(posedge clk)begin
if(reset)begin
state<= IDLE;
end
else begin
state <=next_state;
case(state)
START:mid_byte[0] <= in;
bit0:mid_byte[1] <= in;
bit1:mid_byte[2] <= in;
bit2:mid_byte[3] <= in;
bit3:mid_byte[4] <= in;
bit4:mid_byte[5] <= in;
bit5:mid_byte[6] <= in;
bit6:mid_byte[7] <= in;
default:mid_byte = mid_byte;
endcase
end
end
assign done = (state ==STOP);
// Use FSM from Fsm_serial
assign out_byte = done?mid_byte:0;
// New: Datapath to latch input bits.
// Use FSM from Fsm_serial
// New: Datapath to latch input bits.
endmodule
本题是思路就是在该代码上进行改进:
本题思路捋顺之后会发现:
1.这里面多了一个状态bit8:该状态在停止位之前,用来输入校验位。
2.在接受校验位之后,进入停止状态的判断:
判断情况又分为三种:
1.当停止位有效时候,分为校验过后,1的个数为奇数
2.以及1的个数为偶数。
3.以及当停止位无效(in=0)。
一共三种情况。因此,停止状态后根据不同的条件应该列写出三种情况。
3.计数情况分析:
1.分析是奇数还是偶数,应当在进入相应的读取数据时候才开始分析,也就是说在IDLE,以及STOP状态下(当判断为有效数据时候,此时奇数的结果为1,不应该在对odd的取值进行分析,也就是此时应该复位为0.
2.通过上述1,我们可以了解,需要分析odd的变化情况应当处于:
START bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 (bit8状态时候,已经接受了校验位了,此时的状态是根据in来判断是否为停止位,不应当计入校验判断当中。)同时odd只有在满足: 处于这些状态下,而且需要输入的数据为1的时候才会发生变化。
据此,给出的代码为:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
parameter IDLE=0,START=1,bit0=2,bit1=3,bit2=4,bit3=5,bit4=6,bit5=7,bit6=8,bit7=9,bit8=10,STOP=11,DONE0=12,DONE1=13;
reg[3:0]state,next_state;
reg [8:0] d_s;
wire p_s ,odd;
always@(*)begin
case(state)
IDLE:next_state = in?IDLE:START;
START:next_state = bit0;
bit0:next_state = bit1;
bit1:next_state = bit2;
bit2:next_state = bit3;
bit3:next_state = bit4;
bit4:next_state = bit5;
bit5:next_state = bit6;
bit6:next_state = bit7;
bit7:next_state = bit8;//进入第七位后,表明有效数据都传入了,接下来,接受奇偶校验位
bit8: begin//进入bit8后,也就是接受校验位了,然后接下来根据结束位和校验位共同判断是否数据有效。
if(in & odd)
next_state = STOP;
else if (in & ~odd )
next_state = DONE1;
else
next_state = DONE0;
end
STOP:next_state = in?IDLE:START;
DONE0:next_state = in?IDLE:DONE0;
DONE1: next_state = in?IDLE:START;
endcase
end
always@(posedge clk)begin
if(reset)begin
state<= IDLE;
end
else begin
state <=next_state;
end
end
always@(posedge clk) begin
if(reset)
d_s <= 9'b0;
else begin
case(state)//将输入的数据传递给中间存储的寄存器
START:d_s[0] <= in; //在START状态时候,此时的in就是第一个数据
bit0: d_s[1] <= in;
bit1: d_s[2] <= in;
bit2: d_s[3] <= in;
bit3: d_s[4] <= in;
bit4: d_s[5] <= in;
bit5: d_s[6] <= in;
bit6: d_s[7] <= in;
bit7: d_s[8] <= in;
endcase
end
end
assign p_s = (state == START )|(state == bit0 )|(state == bit1 )|(state == bit2 )|(state == bit3 )|(state == bit4 )|(state == bit5 )|(state == bit6 )|(state == bit7);
wire in2 ;
assign in2 = p_s ∈
wire p_rst;
assign p_rst = (reset |(state ==IDLE)|(state == STOP));
parity instance1(clk,p_rst,in2,odd);
assign done = (state == STOP );
// Use FSM from Fsm_serial
assign out_byte = done?d_s[7:0]:0;
// Modify FSM and datapath from Fsm_serialdata
// New: Add parity checking.
endmodule