题目链接:Exams/ece241 2014 q5a - HDLBits (01xz.net)
Exams/ece241 2014 q5b - HDLBits (01xz.net)
根据题目意思是需要对连续的输入bit进行2's Complement的操作,实际上就是对输入进行取反再+1(直接翻译成补码似乎不太合理,因为正整数的补码是原码,这里也没有说是否有符号),2's Complement的解释参考下面链接
1's Complement和2's Complement的区别_biology24的博客-CSDN博客_2's complement
题目主要的难点主要有两个
- 如何将串行的数据转换为补码再输出
- 使用两种不同的状态机书写代码
首先是如何将串行的数据转换为补码再输出,在这里我一开始也没有想出来,后面参考了下面的文章搞清楚了原理,大家可以自行理解一下
HDLBits:在线学习 Verilog (二十九 · Problem 140-144) - 知乎 (zhihu.com)
主要的原理就是,由于补码是取反再加一,所以在串行数据第一个1到来之前的数据都是0,取反之后都为1,在后面+1的过程中会被进位,所以还是0;而第一个1之后的数据(包括第一个1),因为1取反之后为0,所以进位到这就停止了,不会再向上进位,所以之后的数都是取反的。因此,保持和取反的bit会被第一个1隔开,只就是为什么输入数据要先输入LSB的原因。
另外,需要明白两种状态机的区别,这里也就不在赘述,主要就是Moore输出只和当前状态有关,Mealy输出和当前状态和输入有关,还有就是Moore相比Mealy推迟一个时钟周期输出,还有异步同步的区别等。
下面是Q140 Serial two's complementer (Moore FSM)的代码,因为Moore型状态机输出只和当前状态有关,因此需要将输入的数据存储到状态中再输出,只需要三个状态即可(IDLE,0,1),通过reverse寄存器判断是否需要将输入翻转。
module top_module (
input clk,
input areset,
input x,
output z
);
parameter IDLE = 3'b001;
parameter ZERO = 3'b010;
parameter ONE = 3'b100;
reg [2:0] curr_state;
reg [2:0] next_state;
reg reverse;
always@(posedge clk or posedge areset) begin
if(areset) begin
curr_state <= ZERO;
end
else begin
curr_state <= next_state;
end
end
always @(posedge clk or posedge areset) begin
if(areset) begin
reverse <= 1'b0;
end
else begin
if(x) begin
reverse <= 1'b1;
end
else begin
reverse <= reverse;
end
end
end
always @(*) begin
case(curr_state)
IDLE:begin
next_state = x ? ONE : ZERO;
end
ONE:begin
next_state = (reverse ^ x) ? ONE : ZERO;
end
ZERO:begin
next_state = (reverse ^ x) ? ONE : ZERO;
end
default: next_state = IDLE;
endcase
end
assign z = (curr_state == ONE) ? 1'b1 : 1'b0;
endmodule
下面是Q141 Serial two's complementer (Mealy FSM)的代码,因为Mealy型状态机输出和当前状态以及输入有关,因此直接使用两个状态判断输入是否需要翻转即可,看起来在本题中Mealy型状态机使用会比较简单。
module top_module (
input clk,
input areset,
input x,
output z
);
parameter IDLE = 2'b01;
parameter REVERSE = 2'b10;
reg [1:0] curr_state;
reg [1:0] next_state;
always@(posedge clk or posedge areset) begin
if(areset) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
always @(*) begin
case(curr_state)
IDLE:begin
next_state = x ? REVERSE : IDLE;
end
REVERSE:begin
next_state = REVERSE;
end
default: next_state = IDLE;
endcase
end
assign z = ((curr_state == REVERSE)^x) ? 1'b1 : 1'b0;
endmodule
从两个状态机的输出波形也可以看出Moore相比Mealy推迟一个时钟周期输出
Moore
Mealy