题目如下:
Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don't-care otherwise.
Note that the serial protocol sends the least significant bit first.
Error-free:
一, 最初的思路代码如下:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Use FSM from Fsm_serial
parameter start=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,fin=9,wai=10,idle=11;
reg[3:0] state,next;
wire [7:0] temp;
always @(*)
begin
case(state)
start:next = s1;
s1:next = s2;
s2:next = s3;
s3:next = s4;
s4:next = s5;
s5:next = s6;
s6:next = s7;
s7:next = s8;
s8:next = in?fin:wai;
fin:next = in?idle:start;
wai:next = in?idle:wai;
idle:next = in?idle:start;
default:next = 'x;
endcase
end
always@(posedge clk)
begin
if(reset)
state <= idle;
else
state <= next;
end
assign done = (state == fin);
// New: Datapath to latch input bits.
always @(posedge clk)
begin
case(next)
s1:temp[0] <= in;
s2:temp[1] <= in;
s3:temp[2] <= in;
s4:temp[3] <= in;
s5:temp[4] <= in;
s6:temp[5] <= in;
s7:temp[6] <= in;
s8:temp[7] <= in;
default:temp <= temp;
endcase
end
assign out_byte = done?temp:0;
endmodule
二,关于 Datapath to latch input bits.网站上给出了提示:The serial bitstream needs to be shifted in one bit at a time, then read out in parallel.
所以考虑采用移位寄存器替代数据输出的case语句,改动后代码如下:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Use FSM from Fsm_serial
parameter start=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,fin=9,wai=10,idle=11;
reg[3:0] state,next;
wire [8:0] temp;
wire [7:0] finally;
always @(*)
begin
case(state)
start:next = s1;
s1:next = s2;
s2:next = s3;
s3:next = s4;
s4:next = s5;
s5:next = s6;
s6:next = s7;
s7:next = s8;
s8:next = in?fin:wai;
fin:next = in?idle:start;
wai:next = in?idle:wai;
idle:next = in?idle:start;
default:next = 'x;
endcase
end
always@(posedge clk)
begin
if(reset)
state <= idle;
else
state <= next;
end
assign done = (state == fin);
// New: Datapath to latch input bits.
dflipflop dff0[8:0](.clk(clk),.d({temp[7:0],in}),.q(temp[8:0]));
assign finally = {temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8]};
assign out_byte = done?finally:0;
endmodule
module dflipflop(input clk,d,output q);
always@(posedge clk)
q <= d;
endmodule
注意两点:
a.串行协议先发送最低有效位,故并行输出的结果temp[8:1]要进行反转;
b.关于为什么8位数据但是使用了9位寄存器?
因为满足done为1时输出数据,此时状态并不是s8,最低一位寄存器输出的并不是最后一位数据。
三,在前两者基础上增加了计数器用来计数已接收的数据位数,简化了状态数目。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Use FSM from Fsm_serial
parameter stop=0,data=1,wai=2,idle=3;
reg[1:0] state,next;
wire [8:0] temp;
wire [7:0] finally;
reg[3:0] count;
always @(*)
begin
case(state)
data:next = (count >= 4'd8)? (in?stop:wai):data;
stop:next = in?idle:data;
wai:next = in?idle:wai;
idle:next = in?idle:data;
default:next = 'x;
endcase
end
always@(posedge clk)
begin
if(reset)
state <= idle;
else
begin
state <= next;
if(state == data)
count <= count + 1;
else count <= 0;
end
end
assign done = (state == stop);
// New: Datapath to latch input bits.
dflipflop dff0[8:0](.clk(clk),.d({temp[7:0],in}),.q(temp[8:0]));
assign finally = {temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8]};
assign out_byte = done?finally:0;
endmodule
module dflipflop(input clk,d,output q);
always@(posedge clk)
q <= d;
endmodule