串口指令处理器:
电路图:
cmd_pro指令集格式:
每次连续接收三个字节,第一字节为指令CMD,第二字节为操作数A,第三字节为操作数B;
指令集:
CMD | 操作 |
8‘h0a | A+B |
8'h0b | A-B |
8'h0c | A&B |
8'h0d | A|B |
状态流程图:
Verilog代码:
cmd_pro模块
module cmd_pro(
clk,
res,
din_pro,
en_din_pro,
dout_pro,
en_dout_pro,
rdy
);
input clk;
input res;
input[7:0] din_pro;//指令和数据输入端口;
input en_din_pro;//输入使能;
output[7:0] dout_pro;//指令执行结果
output en_dout_pro;//指令输出使能
output rdy;//串口发送模块空闲标志,0表示空闲
parameter add_ab=8'h0a;
parameter sub_ab=8'h0b;
parameter and_ab=8'h0c;
parameter or_ab =8'h0d;
reg[2:0] state;//主状态机寄存器;不知道几个状态是,多设置几位
reg[7:0] cmd_reg,A_reg,B_reg;//存放指令、A和B;
reg[7:0] dout_pro;
reg en_dout_pro;
always@(posedge clk or negedge res)
if(~res)begin
state<=0;cmd_reg<=0;A_reg<=0;B_reg<=0;dout_pro<=0;
en_dout_pro<=0;
end
else begin
case(state)
0://等指令
begin
en_dout_pro<=0;
if(en_din_pro)begin
cmd_reg<=din_pro;
state<=1;
end
end
1://收A;
begin
if(en_din_pro)begin
A_reg<=din_pro;
state<=2;
end
end
2://收B;
begin
if(en_din_pro)begin
B_reg<=din_pro;
state<=3;
end
end
3://指令译码和执行
begin
state<=4;
case(cmd_reg)
add_ab:begin dout_pro<=A_reg+B_reg;end
sub_ab:begin dout_pro<=A_reg-B_reg;end
and_ab:begin dout_pro<=A_reg&B_reg;end
or_ab: begin dout_pro<=A_reg|B_reg;end//规整性
endcase
end
4://发送指令执行结果;
begin
if(~rdy)begin
en_dout_pro<=1;
state<=0;
end
end
default://
begin
state<=0;
en_dout_pro<=0;
end
endcase
end
endmodule
UART_top:
`timescale 1ns/10ps
module UART_top(
clk,
res,
RX,
TX
);
input clk;
input res;
input RX;
output TX;
//在这里例化三个模块
//需要定义RX,TX模块与cmd模块联系的5个中间信号,信号名以cmd为准
//因为这五个信号都是连接信号,定义为wire类型
wire[7:0] din_pro;
wire en_din_pro;
wire[7:0] dout_pro;
wire en_dout_pro;
wire rdy;
//封装顶层的时候,不管谁是输入,谁是输出,从顶层看都是连线,纯连接wire类型
//做testbench时,会改变模块的输入,所以要定义为reg类型
//异名例化
//串口数据接收
UART_RXer UART_RXer(
.clk(clk),
.res(res),
.RX(RX),
.data_out(din_pro),
.en_data_out(en_din_pro)
);
//串口数据发送
UART_TXer UART_TXer(
.clk(clk),
.res(res),
.data_in(dout_pro),
.en_data_in(en_dout_pro),
.TX(TX),
.rdy(rdy)
);
//指令处理
cmd_pro cmd_pro(
.clk(clk),
.res(res),
.din_pro(din_pro),
.en_din_pro(en_din_pro),
.dout_pro(dout_pro),
.en_dout_pro(en_dout_pro),
.rdy(rdy)
);
endmodule
测试代码:
//------testbench----
module UART_top_tb;
reg clk,res;
wire RX;
wire TX;
reg[45:0] RX_send;//里面装有串口字节发送数据
assign RX=RX_send[0];//连接RX
reg[12:0] con;
UART_top UART_top(
clk,
res,
RX,
TX
);
initial begin
clk<=0;res<=0;con<=0;
RX_send<={1'b1,8'h09,1'b0,1'b1,8'h06,1'b0,1'b1,8'h0a,1'b0,16'hffff};
//发送的数据8'h09,8'h06,发送的操作符8'h0a;
#17 res<=1;
#1000 $stop;//仿真结束
end
always #5 clk<=~clk;
//发送数据
//连续右移
always@(posedge clk)begin
if(con==5000-1)begin
con<=0
end
else begin
con<=con+1;
end
if(con==0)begin
RX_send[44:0]<=RX_send[45:1];//错一项
RX_send[45]<=RX_send[0];//反复右移旋转
end
end
endmodule
编译:
先把几个模块编译,然后编译top