VL21 根据状态转移表实现时序电路
d触发器是不可能d触发器的,这辈子不可能d触发器的。电路图又不会看,就是状态机这种东西,才能维持的了代码这样子,用状态机感觉像回家一样,写状态机里的感觉比家里感觉好多了!里面个个都是人才,代码又简洁,我超喜欢状态机的!
状态机三段式:
//第一段,基本就是死格式了,时序逻辑,非阻塞赋值,传递寄存器的状态
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cs <= ?'b00 ;
end
else begin
cs <= ns ;
end
end
//第二段,组合逻辑,阻塞赋值,根据当前状态和当前输入,确定下个状态机状态。
always@(*) begin
case(cs)
xx : xxx = (xxx) ? xx : xx;
xx : xxx = (xxx) ? xx : xx;
xx : xxx = (xxx) ? xx : xx;
default:xx = xx;
endcase
end
//第三段,时序逻辑,非阻塞赋值,根据当前状态和当前输入,确定输出信号。
先reg个工具人,if,else赋值后再assign输出
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
reg [1:0] cs,ns;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cs <= 2'b00;
ns <= 2'b00;
end
else begin
cs <= ns;
end
end
always@(*) begin
case(cs)
2'b00 : ns = (A == 1'b1) ? 2'b11 : 2'b01;
2'b01 : ns = (A == 1'b1) ? 2'b00 : 2'b10;
2'b10 : ns = (A == 1'b1) ? 2'b01 : 2'b11;
2'b11 : ns = (A == 1'b1) ? 2'b10 : 2'b00;
endcase
end
assign Y = (cs == 2'b11) ? 1 : 0;
endmodule
VL22 根据状态转移图实现时序电路
`timescale 1ns/1ns
module seq_circuit(
input C ,
input clk ,
input rst_n,
output wire Y
);
reg [1:0] cs,ns;
reg Y_1;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cs <= 2'b00;
ns <= 2'b00;
end
else begin
cs <= ns;
end
end
always@(*) begin
case(cs)
2'b00 : ns = (C == 1'b0) ? 2'b00 : 2'b01;
2'b01 : ns = (C == 1'b0) ? 2'b11 : 2'b01;
2'b10 : ns = (C == 1'b0) ? 2'b00 : 2'b10;
2'b11 : ns = (C == 1'b0) ? 2'b11 : 2'b10;
endcase
end
always@(*) begin
case(cs)
2'b00 : Y_1 = 1'b0;
2'b01 : Y_1 = 1'b0;
2'b10 : Y_1 = (C == 1'b0) ? 1'b0 : 1'b1;
2'b11 : Y_1 = 1'b1;
endcase
end
assign Y = Y_1;
endmodule
VL23 ROM的简单实现
[width:0] rom_name [depth:0];
位宽每个数据具有多少位;深度表示需要多少个数据。
注意本题在时钟的非上升沿,addr变换时data也要跟着变化,所以assign data = rom[addr];
要写在组合逻辑部分。
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
reg [3:0] rom [7:0];
assign data = rom[addr];
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
rom[0] <= 4'd0;
rom[1] <= 4'd2;
rom[2] <= 4'd4;
rom[3] <= 4'd6;
rom[4] <= 4'd8;
rom[5] <= 4'd10;
rom[6] <= 4'd12;
rom[7] <= 4'd14;
end else begin
rom[0] <= rom[0];
rom[1] <= rom[1];
rom[2] <= rom[2];
rom[3] <= rom[3];
rom[4] <= rom[4];
rom[5] <= rom[5];
rom[6] <= rom[6];
rom[7] <= rom[7];
end
end
endmodule
VL24 边沿检测
将a信号延迟一拍得到a_1信号,即可判断rise/down。
`timescale 1ns/1ns
module edge_detect(
input clk,
input rst_n,
input a,
output reg rise,
output reg down
);
reg a_1;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
a_1 <= 0;
rise <= 0;
down <= 0;
end else begin
if(a & !a_1) begin
rise <= 1;
down <= 0;
end else if(!a & a_1) begin
rise <= 0;
down <= 1;
end else begin
rise <= 0;
down <= 0;
end
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
a_1 <= 0;
else
a_1 <= a;
end
endmodule